@react-three/fiber 10.0.0-alpha.1 → 10.0.0-canary.b0fafc8
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/LICENSE +21 -21
- package/dist/index.cjs +1170 -557
- package/dist/index.d.cts +2001 -1274
- package/dist/index.d.mts +2001 -1274
- package/dist/index.d.ts +2001 -1274
- package/dist/index.mjs +1154 -561
- package/dist/legacy.cjs +1158 -564
- package/dist/legacy.d.cts +2002 -1275
- package/dist/legacy.d.mts +2002 -1275
- package/dist/legacy.d.ts +2002 -1275
- package/dist/legacy.mjs +1142 -568
- package/dist/webgpu/index.cjs +1365 -504
- package/dist/webgpu/index.d.cts +2180 -1290
- package/dist/webgpu/index.d.mts +2180 -1290
- package/dist/webgpu/index.d.ts +2180 -1290
- package/dist/webgpu/index.mjs +1346 -508
- package/package.json +7 -5
- package/react-reconciler/constants.js +1 -9
- package/react-reconciler/index.js +4 -20
- package/readme.md +244 -318
package/dist/legacy.mjs
CHANGED
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
import * as three from 'three';
|
|
2
|
-
import { WebGLRenderTarget, Frustum, Matrix4, Group, BoxGeometry, MeshBasicNodeMaterial, Mesh, Node, NodeUpdateType, Layers, RGBAFormat, UnsignedByteType, Vector3, Vector2, TextureLoader, Texture as Texture$1,
|
|
3
|
-
import { jsx, Fragment } from 'react/jsx-runtime';
|
|
2
|
+
import { WebGLRenderTarget, CubeReflectionMapping, EquirectangularReflectionMapping, CubeTextureLoader, Scene, WebGLCubeRenderTarget, HalfFloatType, Color, Frustum, Matrix4, Group, BoxGeometry, MeshBasicNodeMaterial, Mesh, Node, NodeUpdateType, Layers, SRGBColorSpace, RGBAFormat, UnsignedByteType, Vector3, Vector2, TextureLoader, Texture as Texture$1, Raycaster, OrthographicCamera, PerspectiveCamera, PCFSoftShadowMap, VSMShadowMap, PCFShadowMap, BasicShadowMap, ACESFilmicToneMapping, WebGLRenderer } from 'three';
|
|
3
|
+
import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
|
|
4
4
|
import * as React from 'react';
|
|
5
|
-
import React__default, {
|
|
5
|
+
import React__default, { useLayoutEffect, useRef, useMemo, useEffect, useContext, useImperativeHandle, useCallback, useState } from 'react';
|
|
6
6
|
import useMeasure from 'react-use-measure';
|
|
7
7
|
import { useFiber, useContextBridge, traverseFiber, FiberProvider } from 'its-fine';
|
|
8
|
+
import { useThree as useThree$1, useLoader as useLoader$1, useFrame as useFrame$1, createPortal as createPortal$1, applyProps as applyProps$1, extend as extend$1 } from '@react-three/fiber';
|
|
9
|
+
import { GroundedSkybox } from 'three/examples/jsm/objects/GroundedSkybox.js';
|
|
10
|
+
import { HDRLoader } from 'three/examples/jsm/loaders/HDRLoader.js';
|
|
11
|
+
import { EXRLoader } from 'three/examples/jsm/loaders/EXRLoader.js';
|
|
12
|
+
import { UltraHDRLoader } from 'three/examples/jsm/loaders/UltraHDRLoader.js';
|
|
13
|
+
import { GainMapLoader } from '@monogrid/gainmap-js';
|
|
8
14
|
import Tb, { unstable_scheduleCallback, unstable_IdlePriority } from 'scheduler';
|
|
9
15
|
import { createWithEqualityFn } from 'zustand/traditional';
|
|
10
16
|
import { suspend, preload, clear } from 'suspend-react';
|
|
@@ -45,6 +51,374 @@ const THREE = /*#__PURE__*/_mergeNamespaces({
|
|
|
45
51
|
WebGPURenderer: WebGPURenderer
|
|
46
52
|
}, [three]);
|
|
47
53
|
|
|
54
|
+
const primaryRegistry = /* @__PURE__ */ new Map();
|
|
55
|
+
const pendingSubscribers = /* @__PURE__ */ new Map();
|
|
56
|
+
function registerPrimary(id, renderer, store) {
|
|
57
|
+
if (primaryRegistry.has(id)) {
|
|
58
|
+
console.warn(`Canvas with id="${id}" already registered. Overwriting.`);
|
|
59
|
+
}
|
|
60
|
+
const entry = { renderer, store };
|
|
61
|
+
primaryRegistry.set(id, entry);
|
|
62
|
+
const subscribers = pendingSubscribers.get(id);
|
|
63
|
+
if (subscribers) {
|
|
64
|
+
subscribers.forEach((callback) => callback(entry));
|
|
65
|
+
pendingSubscribers.delete(id);
|
|
66
|
+
}
|
|
67
|
+
return () => {
|
|
68
|
+
const currentEntry = primaryRegistry.get(id);
|
|
69
|
+
if (currentEntry?.renderer === renderer) {
|
|
70
|
+
primaryRegistry.delete(id);
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
function getPrimary(id) {
|
|
75
|
+
return primaryRegistry.get(id);
|
|
76
|
+
}
|
|
77
|
+
function waitForPrimary(id, timeout = 5e3) {
|
|
78
|
+
const existing = primaryRegistry.get(id);
|
|
79
|
+
if (existing) {
|
|
80
|
+
return Promise.resolve(existing);
|
|
81
|
+
}
|
|
82
|
+
return new Promise((resolve, reject) => {
|
|
83
|
+
const timeoutId = setTimeout(() => {
|
|
84
|
+
const subscribers = pendingSubscribers.get(id);
|
|
85
|
+
if (subscribers) {
|
|
86
|
+
const index = subscribers.indexOf(callback);
|
|
87
|
+
if (index !== -1) subscribers.splice(index, 1);
|
|
88
|
+
if (subscribers.length === 0) pendingSubscribers.delete(id);
|
|
89
|
+
}
|
|
90
|
+
reject(new Error(`Timeout waiting for canvas with id="${id}". Make sure a <Canvas id="${id}"> is mounted.`));
|
|
91
|
+
}, timeout);
|
|
92
|
+
const callback = (entry) => {
|
|
93
|
+
clearTimeout(timeoutId);
|
|
94
|
+
resolve(entry);
|
|
95
|
+
};
|
|
96
|
+
if (!pendingSubscribers.has(id)) {
|
|
97
|
+
pendingSubscribers.set(id, []);
|
|
98
|
+
}
|
|
99
|
+
pendingSubscribers.get(id).push(callback);
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
function hasPrimary(id) {
|
|
103
|
+
return primaryRegistry.has(id);
|
|
104
|
+
}
|
|
105
|
+
function unregisterPrimary(id) {
|
|
106
|
+
primaryRegistry.delete(id);
|
|
107
|
+
}
|
|
108
|
+
function getPrimaryIds() {
|
|
109
|
+
return Array.from(primaryRegistry.keys());
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const presetsObj = {
|
|
113
|
+
apartment: "lebombo_1k.hdr",
|
|
114
|
+
city: "potsdamer_platz_1k.hdr",
|
|
115
|
+
dawn: "kiara_1_dawn_1k.hdr",
|
|
116
|
+
forest: "forest_slope_1k.hdr",
|
|
117
|
+
lobby: "st_fagans_interior_1k.hdr",
|
|
118
|
+
night: "dikhololo_night_1k.hdr",
|
|
119
|
+
park: "rooitou_park_1k.hdr",
|
|
120
|
+
studio: "studio_small_03_1k.hdr",
|
|
121
|
+
sunset: "venice_sunset_1k.hdr",
|
|
122
|
+
warehouse: "empty_warehouse_01_1k.hdr"
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
const CUBEMAP_ROOT = "https://raw.githack.com/pmndrs/drei-assets/456060a26bbeb8fdf79326f224b6d99b8bcce736/hdri/";
|
|
126
|
+
const isArray = (arr) => Array.isArray(arr);
|
|
127
|
+
const defaultFiles = ["/px.png", "/nx.png", "/py.png", "/ny.png", "/pz.png", "/nz.png"];
|
|
128
|
+
function useEnvironment({
|
|
129
|
+
files = defaultFiles,
|
|
130
|
+
path = "",
|
|
131
|
+
preset = void 0,
|
|
132
|
+
colorSpace = void 0,
|
|
133
|
+
extensions
|
|
134
|
+
} = {}) {
|
|
135
|
+
if (preset) {
|
|
136
|
+
validatePreset(preset);
|
|
137
|
+
files = presetsObj[preset];
|
|
138
|
+
path = CUBEMAP_ROOT;
|
|
139
|
+
}
|
|
140
|
+
const multiFile = isArray(files);
|
|
141
|
+
const { extension, isCubemap } = getExtension(files);
|
|
142
|
+
const loader = getLoader$1(extension);
|
|
143
|
+
if (!loader) throw new Error("useEnvironment: Unrecognized file extension: " + files);
|
|
144
|
+
const renderer = useThree$1((state) => state.renderer);
|
|
145
|
+
useLayoutEffect(() => {
|
|
146
|
+
if (extension !== "webp" && extension !== "jpg" && extension !== "jpeg") return;
|
|
147
|
+
function clearGainmapTexture() {
|
|
148
|
+
useLoader$1.clear(loader, multiFile ? [files] : files);
|
|
149
|
+
}
|
|
150
|
+
renderer.domElement.addEventListener("webglcontextlost", clearGainmapTexture, { once: true });
|
|
151
|
+
}, [files, renderer.domElement]);
|
|
152
|
+
const loaderResult = useLoader$1(
|
|
153
|
+
loader,
|
|
154
|
+
multiFile ? [files] : files,
|
|
155
|
+
(loader2) => {
|
|
156
|
+
if (extension === "webp" || extension === "jpg" || extension === "jpeg") {
|
|
157
|
+
loader2.setRenderer?.(renderer);
|
|
158
|
+
}
|
|
159
|
+
loader2.setPath?.(path);
|
|
160
|
+
if (extensions) extensions(loader2);
|
|
161
|
+
}
|
|
162
|
+
);
|
|
163
|
+
let texture = multiFile ? (
|
|
164
|
+
// @ts-ignore
|
|
165
|
+
loaderResult[0]
|
|
166
|
+
) : loaderResult;
|
|
167
|
+
if (extension === "jpg" || extension === "jpeg" || extension === "webp") {
|
|
168
|
+
texture = texture.renderTarget?.texture;
|
|
169
|
+
}
|
|
170
|
+
texture.mapping = isCubemap ? CubeReflectionMapping : EquirectangularReflectionMapping;
|
|
171
|
+
texture.colorSpace = colorSpace ?? (isCubemap ? "srgb" : "srgb-linear");
|
|
172
|
+
return texture;
|
|
173
|
+
}
|
|
174
|
+
const preloadDefaultOptions = {
|
|
175
|
+
files: defaultFiles,
|
|
176
|
+
path: "",
|
|
177
|
+
preset: void 0,
|
|
178
|
+
extensions: void 0
|
|
179
|
+
};
|
|
180
|
+
useEnvironment.preload = (preloadOptions) => {
|
|
181
|
+
const options = { ...preloadDefaultOptions, ...preloadOptions };
|
|
182
|
+
let { files, path = "" } = options;
|
|
183
|
+
const { preset, extensions } = options;
|
|
184
|
+
if (preset) {
|
|
185
|
+
validatePreset(preset);
|
|
186
|
+
files = presetsObj[preset];
|
|
187
|
+
path = CUBEMAP_ROOT;
|
|
188
|
+
}
|
|
189
|
+
const { extension } = getExtension(files);
|
|
190
|
+
if (extension === "webp" || extension === "jpg" || extension === "jpeg") {
|
|
191
|
+
throw new Error("useEnvironment: Preloading gainmaps is not supported");
|
|
192
|
+
}
|
|
193
|
+
const loader = getLoader$1(extension);
|
|
194
|
+
if (!loader) throw new Error("useEnvironment: Unrecognized file extension: " + files);
|
|
195
|
+
useLoader$1.preload(loader, isArray(files) ? [files] : files, (loader2) => {
|
|
196
|
+
loader2.setPath?.(path);
|
|
197
|
+
if (extensions) extensions(loader2);
|
|
198
|
+
});
|
|
199
|
+
};
|
|
200
|
+
const clearDefaultOptins = {
|
|
201
|
+
files: defaultFiles,
|
|
202
|
+
preset: void 0
|
|
203
|
+
};
|
|
204
|
+
useEnvironment.clear = (clearOptions) => {
|
|
205
|
+
const options = { ...clearDefaultOptins, ...clearOptions };
|
|
206
|
+
let { files } = options;
|
|
207
|
+
const { preset } = options;
|
|
208
|
+
if (preset) {
|
|
209
|
+
validatePreset(preset);
|
|
210
|
+
files = presetsObj[preset];
|
|
211
|
+
}
|
|
212
|
+
const { extension } = getExtension(files);
|
|
213
|
+
const loader = getLoader$1(extension);
|
|
214
|
+
if (!loader) throw new Error("useEnvironment: Unrecognized file extension: " + files);
|
|
215
|
+
useLoader$1.clear(loader, isArray(files) ? [files] : files);
|
|
216
|
+
};
|
|
217
|
+
function validatePreset(preset) {
|
|
218
|
+
if (!(preset in presetsObj)) throw new Error("Preset must be one of: " + Object.keys(presetsObj).join(", "));
|
|
219
|
+
}
|
|
220
|
+
function getExtension(files) {
|
|
221
|
+
const isCubemap = isArray(files) && files.length === 6;
|
|
222
|
+
const isGainmap = isArray(files) && files.length === 3 && files.some((file) => file.endsWith("json"));
|
|
223
|
+
const firstEntry = isArray(files) ? files[0] : files;
|
|
224
|
+
const extension = isCubemap ? "cube" : isGainmap ? "webp" : firstEntry.startsWith("data:application/exr") ? "exr" : firstEntry.startsWith("data:application/hdr") ? "hdr" : firstEntry.startsWith("data:image/jpeg") ? "jpg" : firstEntry.split(".").pop()?.split("?")?.shift()?.toLowerCase();
|
|
225
|
+
return { extension, isCubemap, isGainmap };
|
|
226
|
+
}
|
|
227
|
+
function getLoader$1(extension) {
|
|
228
|
+
const loader = extension === "cube" ? CubeTextureLoader : extension === "hdr" ? HDRLoader : extension === "exr" ? EXRLoader : extension === "jpg" || extension === "jpeg" ? UltraHDRLoader : extension === "webp" ? GainMapLoader : null;
|
|
229
|
+
return loader;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
const isRef$1 = (obj) => obj.current && obj.current.isScene;
|
|
233
|
+
const resolveScene = (scene) => isRef$1(scene) ? scene.current : scene;
|
|
234
|
+
function setEnvProps(background, scene, defaultScene, texture, sceneProps = {}) {
|
|
235
|
+
sceneProps = {
|
|
236
|
+
backgroundBlurriness: 0,
|
|
237
|
+
backgroundIntensity: 1,
|
|
238
|
+
backgroundRotation: [0, 0, 0],
|
|
239
|
+
environmentIntensity: 1,
|
|
240
|
+
environmentRotation: [0, 0, 0],
|
|
241
|
+
...sceneProps
|
|
242
|
+
};
|
|
243
|
+
const target = resolveScene(scene || defaultScene);
|
|
244
|
+
const oldbg = target.background;
|
|
245
|
+
const oldenv = target.environment;
|
|
246
|
+
const oldSceneProps = {
|
|
247
|
+
// @ts-ignore
|
|
248
|
+
backgroundBlurriness: target.backgroundBlurriness,
|
|
249
|
+
// @ts-ignore
|
|
250
|
+
backgroundIntensity: target.backgroundIntensity,
|
|
251
|
+
// @ts-ignore
|
|
252
|
+
backgroundRotation: target.backgroundRotation?.clone?.() ?? [0, 0, 0],
|
|
253
|
+
// @ts-ignore
|
|
254
|
+
environmentIntensity: target.environmentIntensity,
|
|
255
|
+
// @ts-ignore
|
|
256
|
+
environmentRotation: target.environmentRotation?.clone?.() ?? [0, 0, 0]
|
|
257
|
+
};
|
|
258
|
+
if (background !== "only") target.environment = texture;
|
|
259
|
+
if (background) target.background = texture;
|
|
260
|
+
applyProps$1(target, sceneProps);
|
|
261
|
+
return () => {
|
|
262
|
+
if (background !== "only") target.environment = oldenv;
|
|
263
|
+
if (background) target.background = oldbg;
|
|
264
|
+
applyProps$1(target, oldSceneProps);
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
function EnvironmentMap({ scene, background = false, map, ...config }) {
|
|
268
|
+
const defaultScene = useThree$1((state) => state.scene);
|
|
269
|
+
React.useLayoutEffect(() => {
|
|
270
|
+
if (map) return setEnvProps(background, scene, defaultScene, map, config);
|
|
271
|
+
});
|
|
272
|
+
return null;
|
|
273
|
+
}
|
|
274
|
+
function EnvironmentCube({
|
|
275
|
+
background = false,
|
|
276
|
+
scene,
|
|
277
|
+
blur,
|
|
278
|
+
backgroundBlurriness,
|
|
279
|
+
backgroundIntensity,
|
|
280
|
+
backgroundRotation,
|
|
281
|
+
environmentIntensity,
|
|
282
|
+
environmentRotation,
|
|
283
|
+
...rest
|
|
284
|
+
}) {
|
|
285
|
+
const texture = useEnvironment(rest);
|
|
286
|
+
const defaultScene = useThree$1((state) => state.scene);
|
|
287
|
+
React.useLayoutEffect(() => {
|
|
288
|
+
return setEnvProps(background, scene, defaultScene, texture, {
|
|
289
|
+
backgroundBlurriness: blur ?? backgroundBlurriness,
|
|
290
|
+
backgroundIntensity,
|
|
291
|
+
backgroundRotation,
|
|
292
|
+
environmentIntensity,
|
|
293
|
+
environmentRotation
|
|
294
|
+
});
|
|
295
|
+
});
|
|
296
|
+
React.useEffect(() => {
|
|
297
|
+
return () => {
|
|
298
|
+
texture.dispose();
|
|
299
|
+
};
|
|
300
|
+
}, [texture]);
|
|
301
|
+
return null;
|
|
302
|
+
}
|
|
303
|
+
function EnvironmentPortal({
|
|
304
|
+
children,
|
|
305
|
+
near = 0.1,
|
|
306
|
+
far = 1e3,
|
|
307
|
+
resolution = 256,
|
|
308
|
+
frames = 1,
|
|
309
|
+
map,
|
|
310
|
+
background = false,
|
|
311
|
+
blur,
|
|
312
|
+
backgroundBlurriness,
|
|
313
|
+
backgroundIntensity,
|
|
314
|
+
backgroundRotation,
|
|
315
|
+
environmentIntensity,
|
|
316
|
+
environmentRotation,
|
|
317
|
+
scene,
|
|
318
|
+
files,
|
|
319
|
+
path,
|
|
320
|
+
preset = void 0,
|
|
321
|
+
extensions
|
|
322
|
+
}) {
|
|
323
|
+
const gl = useThree$1((state) => state.gl);
|
|
324
|
+
const defaultScene = useThree$1((state) => state.scene);
|
|
325
|
+
const camera = React.useRef(null);
|
|
326
|
+
const [virtualScene] = React.useState(() => new Scene());
|
|
327
|
+
const fbo = React.useMemo(() => {
|
|
328
|
+
const fbo2 = new WebGLCubeRenderTarget(resolution);
|
|
329
|
+
fbo2.texture.type = HalfFloatType;
|
|
330
|
+
return fbo2;
|
|
331
|
+
}, [resolution]);
|
|
332
|
+
React.useEffect(() => {
|
|
333
|
+
return () => {
|
|
334
|
+
fbo.dispose();
|
|
335
|
+
};
|
|
336
|
+
}, [fbo]);
|
|
337
|
+
React.useLayoutEffect(() => {
|
|
338
|
+
if (frames === 1) {
|
|
339
|
+
const autoClear = gl.autoClear;
|
|
340
|
+
gl.autoClear = true;
|
|
341
|
+
camera.current.update(gl, virtualScene);
|
|
342
|
+
gl.autoClear = autoClear;
|
|
343
|
+
}
|
|
344
|
+
return setEnvProps(background, scene, defaultScene, fbo.texture, {
|
|
345
|
+
backgroundBlurriness: blur ?? backgroundBlurriness,
|
|
346
|
+
backgroundIntensity,
|
|
347
|
+
backgroundRotation,
|
|
348
|
+
environmentIntensity,
|
|
349
|
+
environmentRotation
|
|
350
|
+
});
|
|
351
|
+
}, [children, virtualScene, fbo.texture, scene, defaultScene, background, frames, gl]);
|
|
352
|
+
let count = 1;
|
|
353
|
+
useFrame$1(() => {
|
|
354
|
+
if (frames === Infinity || count < frames) {
|
|
355
|
+
const autoClear = gl.autoClear;
|
|
356
|
+
gl.autoClear = true;
|
|
357
|
+
camera.current.update(gl, virtualScene);
|
|
358
|
+
gl.autoClear = autoClear;
|
|
359
|
+
count++;
|
|
360
|
+
}
|
|
361
|
+
});
|
|
362
|
+
return /* @__PURE__ */ jsx(Fragment, { children: createPortal$1(
|
|
363
|
+
/* @__PURE__ */ jsxs(Fragment, { children: [
|
|
364
|
+
children,
|
|
365
|
+
/* @__PURE__ */ jsx("cubeCamera", { ref: camera, args: [near, far, fbo] }),
|
|
366
|
+
files || preset ? /* @__PURE__ */ jsx(EnvironmentCube, { background: true, files, preset, path, extensions }) : map ? /* @__PURE__ */ jsx(EnvironmentMap, { background: true, map, extensions }) : null
|
|
367
|
+
] }),
|
|
368
|
+
virtualScene
|
|
369
|
+
) });
|
|
370
|
+
}
|
|
371
|
+
function EnvironmentGround(props) {
|
|
372
|
+
const textureDefault = useEnvironment(props);
|
|
373
|
+
const texture = props.map || textureDefault;
|
|
374
|
+
React.useMemo(() => extend$1({ GroundProjectedEnvImpl: GroundedSkybox }), []);
|
|
375
|
+
React.useEffect(() => {
|
|
376
|
+
return () => {
|
|
377
|
+
textureDefault.dispose();
|
|
378
|
+
};
|
|
379
|
+
}, [textureDefault]);
|
|
380
|
+
const height = props.ground?.height ?? 15;
|
|
381
|
+
const radius = props.ground?.radius ?? 60;
|
|
382
|
+
const scale = props.ground?.scale ?? 1e3;
|
|
383
|
+
const args = React.useMemo(
|
|
384
|
+
() => [texture, height, radius],
|
|
385
|
+
[texture, height, radius]
|
|
386
|
+
);
|
|
387
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
388
|
+
/* @__PURE__ */ jsx(EnvironmentMap, { ...props, map: texture }),
|
|
389
|
+
/* @__PURE__ */ jsx("groundProjectedEnvImpl", { args, scale })
|
|
390
|
+
] });
|
|
391
|
+
}
|
|
392
|
+
function EnvironmentColor({ color, scene }) {
|
|
393
|
+
const defaultScene = useThree$1((state) => state.scene);
|
|
394
|
+
React.useLayoutEffect(() => {
|
|
395
|
+
if (color === void 0) return;
|
|
396
|
+
const target = resolveScene(scene || defaultScene);
|
|
397
|
+
const oldBg = target.background;
|
|
398
|
+
target.background = new Color(color);
|
|
399
|
+
return () => {
|
|
400
|
+
target.background = oldBg;
|
|
401
|
+
};
|
|
402
|
+
});
|
|
403
|
+
return null;
|
|
404
|
+
}
|
|
405
|
+
function EnvironmentDualSource(props) {
|
|
406
|
+
const { backgroundFiles, ...envProps } = props;
|
|
407
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
408
|
+
/* @__PURE__ */ jsx(EnvironmentCube, { ...envProps, background: false }),
|
|
409
|
+
/* @__PURE__ */ jsx(EnvironmentCube, { ...props, files: backgroundFiles, background: "only" })
|
|
410
|
+
] });
|
|
411
|
+
}
|
|
412
|
+
function Environment(props) {
|
|
413
|
+
if (props.color && !props.files && !props.preset && !props.map) {
|
|
414
|
+
return /* @__PURE__ */ jsx(EnvironmentColor, { ...props });
|
|
415
|
+
}
|
|
416
|
+
if (props.backgroundFiles && props.backgroundFiles !== props.files) {
|
|
417
|
+
return /* @__PURE__ */ jsx(EnvironmentDualSource, { ...props });
|
|
418
|
+
}
|
|
419
|
+
return props.ground ? /* @__PURE__ */ jsx(EnvironmentGround, { ...props }) : props.map ? /* @__PURE__ */ jsx(EnvironmentMap, { ...props }) : props.children ? /* @__PURE__ */ jsx(EnvironmentPortal, { ...props }) : /* @__PURE__ */ jsx(EnvironmentCube, { ...props });
|
|
420
|
+
}
|
|
421
|
+
|
|
48
422
|
var __defProp$2 = Object.defineProperty;
|
|
49
423
|
var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
50
424
|
var __publicField$2 = (obj, key, value) => __defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
@@ -224,7 +598,8 @@ function prepare(target, root, type, props) {
|
|
|
224
598
|
object,
|
|
225
599
|
eventCount: 0,
|
|
226
600
|
handlers: {},
|
|
227
|
-
isHidden: false
|
|
601
|
+
isHidden: false,
|
|
602
|
+
deferredRefs: []
|
|
228
603
|
};
|
|
229
604
|
if (object) object.__r3f = instance;
|
|
230
605
|
}
|
|
@@ -273,7 +648,7 @@ function createOcclusionObserverNode(store, uniform) {
|
|
|
273
648
|
let occlusionSetupPromise = null;
|
|
274
649
|
function enableOcclusion(store) {
|
|
275
650
|
const state = store.getState();
|
|
276
|
-
const { internal, renderer
|
|
651
|
+
const { internal, renderer } = state;
|
|
277
652
|
if (internal.occlusionEnabled || occlusionSetupPromise) return;
|
|
278
653
|
const hasOcclusionSupport = typeof renderer?.isOccluded === "function";
|
|
279
654
|
if (!hasOcclusionSupport) {
|
|
@@ -436,6 +811,22 @@ function hasVisibilityHandlers(handlers) {
|
|
|
436
811
|
return !!(handlers.onFramed || handlers.onOccluded || handlers.onVisible);
|
|
437
812
|
}
|
|
438
813
|
|
|
814
|
+
const FROM_REF = Symbol.for("@react-three/fiber.fromRef");
|
|
815
|
+
function fromRef(ref) {
|
|
816
|
+
return { [FROM_REF]: ref };
|
|
817
|
+
}
|
|
818
|
+
function isFromRef(value) {
|
|
819
|
+
return value !== null && typeof value === "object" && FROM_REF in value;
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
const ONCE = Symbol.for("@react-three/fiber.once");
|
|
823
|
+
function once(...args) {
|
|
824
|
+
return { [ONCE]: args.length ? args : true };
|
|
825
|
+
}
|
|
826
|
+
function isOnce(value) {
|
|
827
|
+
return value !== null && typeof value === "object" && ONCE in value;
|
|
828
|
+
}
|
|
829
|
+
|
|
439
830
|
const RESERVED_PROPS = [
|
|
440
831
|
"children",
|
|
441
832
|
"key",
|
|
@@ -506,7 +897,7 @@ function getMemoizedPrototype(root) {
|
|
|
506
897
|
ctor = new root.constructor();
|
|
507
898
|
MEMOIZED_PROTOTYPES.set(root.constructor, ctor);
|
|
508
899
|
}
|
|
509
|
-
} catch
|
|
900
|
+
} catch {
|
|
510
901
|
}
|
|
511
902
|
return ctor;
|
|
512
903
|
}
|
|
@@ -537,7 +928,7 @@ function applyProps(object, props) {
|
|
|
537
928
|
const rootState = instance && findInitialRoot(instance).getState();
|
|
538
929
|
const prevHandlers = instance?.eventCount;
|
|
539
930
|
for (const prop in props) {
|
|
540
|
-
|
|
931
|
+
const value = props[prop];
|
|
541
932
|
if (RESERVED_PROPS.includes(prop)) continue;
|
|
542
933
|
if (instance && EVENT_REGEX.test(prop)) {
|
|
543
934
|
if (typeof value === "function") instance.handlers[prop] = value;
|
|
@@ -552,6 +943,25 @@ function applyProps(object, props) {
|
|
|
552
943
|
continue;
|
|
553
944
|
}
|
|
554
945
|
if (value === void 0) continue;
|
|
946
|
+
if (isFromRef(value)) {
|
|
947
|
+
instance?.deferredRefs?.push({ prop, ref: value[FROM_REF] });
|
|
948
|
+
continue;
|
|
949
|
+
}
|
|
950
|
+
if (isOnce(value)) {
|
|
951
|
+
if (instance?.appliedOnce?.has(prop)) continue;
|
|
952
|
+
if (instance) {
|
|
953
|
+
instance.appliedOnce ?? (instance.appliedOnce = /* @__PURE__ */ new Set());
|
|
954
|
+
instance.appliedOnce.add(prop);
|
|
955
|
+
}
|
|
956
|
+
const { root: targetRoot, key: targetKey } = resolve(object, prop);
|
|
957
|
+
const args = value[ONCE];
|
|
958
|
+
if (typeof targetRoot[targetKey] === "function") {
|
|
959
|
+
targetRoot[targetKey](...args === true ? [] : args);
|
|
960
|
+
} else if (args !== true && args.length > 0) {
|
|
961
|
+
targetRoot[targetKey] = args[0];
|
|
962
|
+
}
|
|
963
|
+
continue;
|
|
964
|
+
}
|
|
555
965
|
let { root, key, target } = resolve(object, prop);
|
|
556
966
|
if (target === void 0 && (typeof root !== "object" || root === null)) {
|
|
557
967
|
throw Error(`R3F: Cannot set "${prop}". Ensure it is an object before setting "${key}".`);
|
|
@@ -574,7 +984,7 @@ function applyProps(object, props) {
|
|
|
574
984
|
else target.set(value);
|
|
575
985
|
} else {
|
|
576
986
|
root[key] = value;
|
|
577
|
-
if (rootState &&
|
|
987
|
+
if (rootState && rootState.renderer?.outputColorSpace === SRGBColorSpace && colorMaps.includes(key) && isTexture(value) && root[key]?.isTexture && // sRGB textures must be RGBA8 since r137 https://github.com/mrdoob/three.js/pull/23129
|
|
578
988
|
root[key].format === RGBAFormat && root[key].type === UnsignedByteType) {
|
|
579
989
|
root[key].colorSpace = rootState.textureColorSpace;
|
|
580
990
|
}
|
|
@@ -689,13 +1099,14 @@ function createEvents(store) {
|
|
|
689
1099
|
for (const hit of hits) {
|
|
690
1100
|
let eventObject = hit.object;
|
|
691
1101
|
while (eventObject) {
|
|
692
|
-
if (eventObject.__r3f?.eventCount)
|
|
1102
|
+
if (eventObject.__r3f?.eventCount) {
|
|
693
1103
|
intersections.push({ ...hit, eventObject });
|
|
1104
|
+
}
|
|
694
1105
|
eventObject = eventObject.parent;
|
|
695
1106
|
}
|
|
696
1107
|
}
|
|
697
1108
|
if ("pointerId" in event && state.internal.capturedMap.has(event.pointerId)) {
|
|
698
|
-
for (
|
|
1109
|
+
for (const captureData of state.internal.capturedMap.get(event.pointerId).values()) {
|
|
699
1110
|
if (!duplicates.has(makeId(captureData.intersection))) intersections.push(captureData.intersection);
|
|
700
1111
|
}
|
|
701
1112
|
}
|
|
@@ -725,12 +1136,12 @@ function createEvents(store) {
|
|
|
725
1136
|
releaseInternalPointerCapture(internal.capturedMap, hit.eventObject, captures, id);
|
|
726
1137
|
}
|
|
727
1138
|
};
|
|
728
|
-
|
|
729
|
-
for (
|
|
730
|
-
|
|
1139
|
+
const extractEventProps = {};
|
|
1140
|
+
for (const prop in event) {
|
|
1141
|
+
const property = event[prop];
|
|
731
1142
|
if (typeof property !== "function") extractEventProps[prop] = property;
|
|
732
1143
|
}
|
|
733
|
-
|
|
1144
|
+
const raycastEvent = {
|
|
734
1145
|
...hit,
|
|
735
1146
|
...extractEventProps,
|
|
736
1147
|
pointer,
|
|
@@ -930,7 +1341,7 @@ function createPointerEvents(store) {
|
|
|
930
1341
|
return {
|
|
931
1342
|
priority: 1,
|
|
932
1343
|
enabled: true,
|
|
933
|
-
compute(event, state
|
|
1344
|
+
compute(event, state) {
|
|
934
1345
|
state.pointer.set(event.offsetX / state.size.width * 2 - 1, -(event.offsetY / state.size.height) * 2 + 1);
|
|
935
1346
|
state.raycaster.setFromCamera(state.pointer, state.camera);
|
|
936
1347
|
},
|
|
@@ -1028,300 +1439,26 @@ function notifyAlpha({ message, link }) {
|
|
|
1028
1439
|
}
|
|
1029
1440
|
}
|
|
1030
1441
|
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
}
|
|
1052
|
-
}
|
|
1053
|
-
let performanceTimeout = void 0;
|
|
1054
|
-
const setPerformanceCurrent = (current) => set((state2) => ({ performance: { ...state2.performance, current } }));
|
|
1055
|
-
const pointer = new Vector2();
|
|
1056
|
-
const rootState = {
|
|
1057
|
-
set,
|
|
1058
|
-
get,
|
|
1059
|
-
// Mock objects that have to be configured
|
|
1060
|
-
gl: null,
|
|
1061
|
-
renderer: null,
|
|
1062
|
-
camera: null,
|
|
1063
|
-
frustum: new Frustum(),
|
|
1064
|
-
autoUpdateFrustum: true,
|
|
1065
|
-
raycaster: null,
|
|
1066
|
-
events: { priority: 1, enabled: true, connected: false },
|
|
1067
|
-
scene: null,
|
|
1068
|
-
rootScene: null,
|
|
1069
|
-
xr: null,
|
|
1070
|
-
inspector: null,
|
|
1071
|
-
invalidate: (frames = 1, stackFrames = false) => invalidate(get(), frames, stackFrames),
|
|
1072
|
-
advance: (timestamp, runGlobalEffects) => advance(timestamp, runGlobalEffects, get()),
|
|
1073
|
-
legacy: false,
|
|
1074
|
-
linear: false,
|
|
1075
|
-
flat: false,
|
|
1076
|
-
textureColorSpace: "srgb",
|
|
1077
|
-
isLegacy: false,
|
|
1078
|
-
webGPUSupported: false,
|
|
1079
|
-
isNative: false,
|
|
1080
|
-
controls: null,
|
|
1081
|
-
pointer,
|
|
1082
|
-
mouse: pointer,
|
|
1083
|
-
frameloop: "always",
|
|
1084
|
-
onPointerMissed: void 0,
|
|
1085
|
-
onDragOverMissed: void 0,
|
|
1086
|
-
onDropMissed: void 0,
|
|
1087
|
-
performance: {
|
|
1088
|
-
current: 1,
|
|
1089
|
-
min: 0.5,
|
|
1090
|
-
max: 1,
|
|
1091
|
-
debounce: 200,
|
|
1092
|
-
regress: () => {
|
|
1093
|
-
const state2 = get();
|
|
1094
|
-
if (performanceTimeout) clearTimeout(performanceTimeout);
|
|
1095
|
-
if (state2.performance.current !== state2.performance.min) setPerformanceCurrent(state2.performance.min);
|
|
1096
|
-
performanceTimeout = setTimeout(
|
|
1097
|
-
() => setPerformanceCurrent(get().performance.max),
|
|
1098
|
-
state2.performance.debounce
|
|
1099
|
-
);
|
|
1100
|
-
}
|
|
1101
|
-
},
|
|
1102
|
-
size: { width: 0, height: 0, top: 0, left: 0 },
|
|
1103
|
-
viewport: {
|
|
1104
|
-
initialDpr: 0,
|
|
1105
|
-
dpr: 0,
|
|
1106
|
-
width: 0,
|
|
1107
|
-
height: 0,
|
|
1108
|
-
top: 0,
|
|
1109
|
-
left: 0,
|
|
1110
|
-
aspect: 0,
|
|
1111
|
-
distance: 0,
|
|
1112
|
-
factor: 0,
|
|
1113
|
-
getCurrentViewport
|
|
1114
|
-
},
|
|
1115
|
-
setEvents: (events) => set((state2) => ({ ...state2, events: { ...state2.events, ...events } })),
|
|
1116
|
-
setSize: (width, height, top = 0, left = 0) => {
|
|
1117
|
-
const camera = get().camera;
|
|
1118
|
-
const size = { width, height, top, left };
|
|
1119
|
-
set((state2) => ({ size, viewport: { ...state2.viewport, ...getCurrentViewport(camera, defaultTarget, size) } }));
|
|
1120
|
-
},
|
|
1121
|
-
setDpr: (dpr) => set((state2) => {
|
|
1122
|
-
const resolved = calculateDpr(dpr);
|
|
1123
|
-
return { viewport: { ...state2.viewport, dpr: resolved, initialDpr: state2.viewport.initialDpr || resolved } };
|
|
1124
|
-
}),
|
|
1125
|
-
setFrameloop: (frameloop = "always") => {
|
|
1126
|
-
set(() => ({ frameloop }));
|
|
1127
|
-
},
|
|
1128
|
-
setError: (error) => set(() => ({ error })),
|
|
1129
|
-
error: null,
|
|
1130
|
-
//* TSL State (managed via hooks: useUniforms, useNodes, useTextures, usePostProcessing) ==============================
|
|
1131
|
-
uniforms: {},
|
|
1132
|
-
nodes: {},
|
|
1133
|
-
textures: /* @__PURE__ */ new Map(),
|
|
1134
|
-
postProcessing: null,
|
|
1135
|
-
passes: {},
|
|
1136
|
-
previousRoot: void 0,
|
|
1137
|
-
internal: {
|
|
1138
|
-
// Events
|
|
1139
|
-
interaction: [],
|
|
1140
|
-
hovered: /* @__PURE__ */ new Map(),
|
|
1141
|
-
subscribers: [],
|
|
1142
|
-
initialClick: [0, 0],
|
|
1143
|
-
initialHits: [],
|
|
1144
|
-
capturedMap: /* @__PURE__ */ new Map(),
|
|
1145
|
-
lastEvent: React.createRef(),
|
|
1146
|
-
// Visibility tracking (onFramed, onOccluded, onVisible)
|
|
1147
|
-
visibilityRegistry: /* @__PURE__ */ new Map(),
|
|
1148
|
-
// Occlusion system (WebGPU only)
|
|
1149
|
-
occlusionEnabled: false,
|
|
1150
|
-
occlusionObserver: null,
|
|
1151
|
-
occlusionCache: /* @__PURE__ */ new Map(),
|
|
1152
|
-
helperGroup: null,
|
|
1153
|
-
// Updates
|
|
1154
|
-
active: false,
|
|
1155
|
-
frames: 0,
|
|
1156
|
-
priority: 0,
|
|
1157
|
-
subscribe: (ref, priority, store) => {
|
|
1158
|
-
const internal = get().internal;
|
|
1159
|
-
internal.priority = internal.priority + (priority > 0 ? 1 : 0);
|
|
1160
|
-
internal.subscribers.push({ ref, priority, store });
|
|
1161
|
-
internal.subscribers = internal.subscribers.sort((a, b) => a.priority - b.priority);
|
|
1162
|
-
return () => {
|
|
1163
|
-
const internal2 = get().internal;
|
|
1164
|
-
if (internal2?.subscribers) {
|
|
1165
|
-
internal2.priority = internal2.priority - (priority > 0 ? 1 : 0);
|
|
1166
|
-
internal2.subscribers = internal2.subscribers.filter((s) => s.ref !== ref);
|
|
1167
|
-
}
|
|
1168
|
-
};
|
|
1169
|
-
},
|
|
1170
|
-
// Renderer Storage (single source of truth)
|
|
1171
|
-
actualRenderer: null,
|
|
1172
|
-
// Scheduler for useFrameNext (initialized in renderer.tsx)
|
|
1173
|
-
scheduler: null
|
|
1174
|
-
}
|
|
1175
|
-
};
|
|
1176
|
-
return rootState;
|
|
1177
|
-
});
|
|
1178
|
-
const state = rootStore.getState();
|
|
1179
|
-
Object.defineProperty(state, "gl", {
|
|
1180
|
-
get() {
|
|
1181
|
-
const currentState = rootStore.getState();
|
|
1182
|
-
if (!currentState.isLegacy && currentState.internal.actualRenderer) {
|
|
1183
|
-
const stack = new Error().stack || "";
|
|
1184
|
-
const isInternalAccess = stack.includes("zustand") || stack.includes("setState") || stack.includes("Object.assign") || stack.includes("react-three-fiber/packages/fiber/src/core");
|
|
1185
|
-
if (!isInternalAccess) {
|
|
1186
|
-
const cleanedStack = stack.split("\n").slice(2).join("\n") || "Stack trace unavailable";
|
|
1187
|
-
notifyDepreciated({
|
|
1188
|
-
heading: "Accessing state.gl in WebGPU mode",
|
|
1189
|
-
body: "Please use state.renderer instead. state.gl is deprecated and will be removed in future versions.\n\nFor backwards compatibility, state.gl currently maps to state.renderer, but this may cause issues with libraries expecting WebGLRenderer.\n\nAccessed from:\n" + cleanedStack
|
|
1190
|
-
});
|
|
1191
|
-
}
|
|
1192
|
-
}
|
|
1193
|
-
return currentState.internal.actualRenderer;
|
|
1194
|
-
},
|
|
1195
|
-
set(value) {
|
|
1196
|
-
rootStore.getState().internal.actualRenderer = value;
|
|
1197
|
-
},
|
|
1198
|
-
enumerable: true,
|
|
1199
|
-
configurable: true
|
|
1200
|
-
});
|
|
1201
|
-
Object.defineProperty(state, "renderer", {
|
|
1202
|
-
get() {
|
|
1203
|
-
return rootStore.getState().internal.actualRenderer;
|
|
1204
|
-
},
|
|
1205
|
-
set(value) {
|
|
1206
|
-
rootStore.getState().internal.actualRenderer = value;
|
|
1207
|
-
},
|
|
1208
|
-
enumerable: true,
|
|
1209
|
-
configurable: true
|
|
1210
|
-
});
|
|
1211
|
-
let oldScene = state.scene;
|
|
1212
|
-
rootStore.subscribe(() => {
|
|
1213
|
-
const currentState = rootStore.getState();
|
|
1214
|
-
const { scene, rootScene, set } = currentState;
|
|
1215
|
-
if (scene !== oldScene) {
|
|
1216
|
-
oldScene = scene;
|
|
1217
|
-
if (scene?.isScene && scene !== rootScene) {
|
|
1218
|
-
set({ rootScene: scene });
|
|
1219
|
-
}
|
|
1220
|
-
}
|
|
1221
|
-
});
|
|
1222
|
-
let oldSize = state.size;
|
|
1223
|
-
let oldDpr = state.viewport.dpr;
|
|
1224
|
-
let oldCamera = state.camera;
|
|
1225
|
-
rootStore.subscribe(() => {
|
|
1226
|
-
const { camera, size, viewport, set, internal } = rootStore.getState();
|
|
1227
|
-
const actualRenderer = internal.actualRenderer;
|
|
1228
|
-
if (size.width !== oldSize.width || size.height !== oldSize.height || viewport.dpr !== oldDpr) {
|
|
1229
|
-
oldSize = size;
|
|
1230
|
-
oldDpr = viewport.dpr;
|
|
1231
|
-
updateCamera(camera, size);
|
|
1232
|
-
if (viewport.dpr > 0) actualRenderer.setPixelRatio(viewport.dpr);
|
|
1233
|
-
const updateStyle = typeof HTMLCanvasElement !== "undefined" && actualRenderer.domElement instanceof HTMLCanvasElement;
|
|
1234
|
-
actualRenderer.setSize(size.width, size.height, updateStyle);
|
|
1235
|
-
}
|
|
1236
|
-
if (camera !== oldCamera) {
|
|
1237
|
-
oldCamera = camera;
|
|
1238
|
-
const { rootScene } = rootStore.getState();
|
|
1239
|
-
if (camera && rootScene && !camera.parent) {
|
|
1240
|
-
rootScene.add(camera);
|
|
1241
|
-
}
|
|
1242
|
-
set((state2) => ({ viewport: { ...state2.viewport, ...state2.viewport.getCurrentViewport(camera) } }));
|
|
1243
|
-
const currentState = rootStore.getState();
|
|
1244
|
-
if (currentState.autoUpdateFrustum && camera) {
|
|
1245
|
-
updateFrustum(camera, currentState.frustum);
|
|
1246
|
-
}
|
|
1247
|
-
}
|
|
1248
|
-
});
|
|
1249
|
-
rootStore.subscribe((state2) => invalidate(state2));
|
|
1250
|
-
return rootStore;
|
|
1251
|
-
};
|
|
1252
|
-
|
|
1253
|
-
const memoizedLoaders = /* @__PURE__ */ new WeakMap();
|
|
1254
|
-
const isConstructor$1 = (value) => typeof value === "function" && value?.prototype?.constructor === value;
|
|
1255
|
-
function getLoader(Proto) {
|
|
1256
|
-
if (isConstructor$1(Proto)) {
|
|
1257
|
-
let loader = memoizedLoaders.get(Proto);
|
|
1258
|
-
if (!loader) {
|
|
1259
|
-
loader = new Proto();
|
|
1260
|
-
memoizedLoaders.set(Proto, loader);
|
|
1261
|
-
}
|
|
1262
|
-
return loader;
|
|
1263
|
-
}
|
|
1264
|
-
return Proto;
|
|
1265
|
-
}
|
|
1266
|
-
function loadingFn(extensions, onProgress) {
|
|
1267
|
-
return function(Proto, input) {
|
|
1268
|
-
const loader = getLoader(Proto);
|
|
1269
|
-
if (extensions) extensions(loader);
|
|
1270
|
-
if ("loadAsync" in loader && typeof loader.loadAsync === "function") {
|
|
1271
|
-
return loader.loadAsync(input, onProgress).then((data) => {
|
|
1272
|
-
if (isObject3D(data?.scene)) Object.assign(data, buildGraph(data.scene));
|
|
1273
|
-
return data;
|
|
1274
|
-
});
|
|
1275
|
-
}
|
|
1276
|
-
return new Promise(
|
|
1277
|
-
(res, reject) => loader.load(
|
|
1278
|
-
input,
|
|
1279
|
-
(data) => {
|
|
1280
|
-
if (isObject3D(data?.scene)) Object.assign(data, buildGraph(data.scene));
|
|
1281
|
-
res(data);
|
|
1282
|
-
},
|
|
1283
|
-
onProgress,
|
|
1284
|
-
(error) => reject(new Error(`Could not load ${input}: ${error?.message}`))
|
|
1285
|
-
)
|
|
1286
|
-
);
|
|
1287
|
-
};
|
|
1288
|
-
}
|
|
1289
|
-
function useLoader(loader, input, extensions, onProgress) {
|
|
1290
|
-
const keys = Array.isArray(input) ? input : [input];
|
|
1291
|
-
const fn = loadingFn(extensions, onProgress);
|
|
1292
|
-
const results = keys.map((key) => suspend(fn, [loader, key], { equal: is.equ }));
|
|
1293
|
-
return Array.isArray(input) ? results : results[0];
|
|
1294
|
-
}
|
|
1295
|
-
useLoader.preload = function(loader, input, extensions, onProgress) {
|
|
1296
|
-
const keys = Array.isArray(input) ? input : [input];
|
|
1297
|
-
keys.forEach((key) => preload(loadingFn(extensions, onProgress), [loader, key]));
|
|
1298
|
-
};
|
|
1299
|
-
useLoader.clear = function(loader, input) {
|
|
1300
|
-
const keys = Array.isArray(input) ? input : [input];
|
|
1301
|
-
keys.forEach((key) => clear([loader, key]));
|
|
1302
|
-
};
|
|
1303
|
-
useLoader.loader = getLoader;
|
|
1304
|
-
|
|
1305
|
-
var __defProp$1 = Object.defineProperty;
|
|
1306
|
-
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1307
|
-
var __publicField$1 = (obj, key, value) => __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1308
|
-
const DEFAULT_PHASES = ["start", "input", "physics", "update", "render", "finish"];
|
|
1309
|
-
class PhaseGraph {
|
|
1310
|
-
constructor() {
|
|
1311
|
-
/** Ordered list of phase nodes */
|
|
1312
|
-
__publicField$1(this, "phases", []);
|
|
1313
|
-
/** Quick lookup by name */
|
|
1314
|
-
__publicField$1(this, "phaseMap", /* @__PURE__ */ new Map());
|
|
1315
|
-
/** Cached ordered names (invalidated on changes) */
|
|
1316
|
-
__publicField$1(this, "orderedNamesCache", null);
|
|
1317
|
-
this.initializeDefaultPhases();
|
|
1318
|
-
}
|
|
1319
|
-
//* Initialization --------------------------------
|
|
1320
|
-
initializeDefaultPhases() {
|
|
1321
|
-
for (const name of DEFAULT_PHASES) {
|
|
1322
|
-
const node = { name, isAutoGenerated: false };
|
|
1323
|
-
this.phases.push(node);
|
|
1324
|
-
this.phaseMap.set(name, node);
|
|
1442
|
+
var __defProp$1 = Object.defineProperty;
|
|
1443
|
+
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1444
|
+
var __publicField$1 = (obj, key, value) => __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1445
|
+
const DEFAULT_PHASES = ["start", "input", "physics", "update", "render", "finish"];
|
|
1446
|
+
class PhaseGraph {
|
|
1447
|
+
constructor() {
|
|
1448
|
+
/** Ordered list of phase nodes */
|
|
1449
|
+
__publicField$1(this, "phases", []);
|
|
1450
|
+
/** Quick lookup by name */
|
|
1451
|
+
__publicField$1(this, "phaseMap", /* @__PURE__ */ new Map());
|
|
1452
|
+
/** Cached ordered names (invalidated on changes) */
|
|
1453
|
+
__publicField$1(this, "orderedNamesCache", null);
|
|
1454
|
+
this.initializeDefaultPhases();
|
|
1455
|
+
}
|
|
1456
|
+
//* Initialization --------------------------------
|
|
1457
|
+
initializeDefaultPhases() {
|
|
1458
|
+
for (const name of DEFAULT_PHASES) {
|
|
1459
|
+
const node = { name, isAutoGenerated: false };
|
|
1460
|
+
this.phases.push(node);
|
|
1461
|
+
this.phaseMap.set(name, node);
|
|
1325
1462
|
}
|
|
1326
1463
|
this.invalidateCache();
|
|
1327
1464
|
}
|
|
@@ -1340,8 +1477,9 @@ class PhaseGraph {
|
|
|
1340
1477
|
const node = { name, isAutoGenerated: false };
|
|
1341
1478
|
let insertIndex = this.phases.length;
|
|
1342
1479
|
const targetIndex = this.getPhaseIndex(before ?? after);
|
|
1343
|
-
if (targetIndex !== -1)
|
|
1344
|
-
|
|
1480
|
+
if (targetIndex !== -1) {
|
|
1481
|
+
insertIndex = before ? targetIndex : targetIndex + 1;
|
|
1482
|
+
} else {
|
|
1345
1483
|
const constraintType = before ? "before" : "after";
|
|
1346
1484
|
console.warn(`[useFrame] Phase "${before ?? after}" not found for '${constraintType}' constraint`);
|
|
1347
1485
|
}
|
|
@@ -2206,132 +2344,445 @@ const _Scheduler = class _Scheduler {
|
|
|
2206
2344
|
console.error(`[Scheduler] Error in global job "${job.id}":`, error);
|
|
2207
2345
|
}
|
|
2208
2346
|
}
|
|
2209
|
-
}
|
|
2210
|
-
/**
|
|
2211
|
-
* Execute all jobs for a single root in sorted order.
|
|
2212
|
-
* Rebuilds sorted job list if needed, then dispatches each job.
|
|
2213
|
-
* Errors are caught and propagated via triggerError.
|
|
2214
|
-
* @param {RootEntry} root - The root entry to tick
|
|
2215
|
-
* @param {number} timestamp - RAF timestamp in milliseconds
|
|
2216
|
-
* @param {number} delta - Time since last frame in seconds
|
|
2217
|
-
* @returns {void}
|
|
2218
|
-
* @private
|
|
2219
|
-
*/
|
|
2220
|
-
tickRoot(root, timestamp, delta) {
|
|
2221
|
-
if (root.needsRebuild) {
|
|
2222
|
-
root.sortedJobs = rebuildSortedJobs(root.jobs, this.phaseGraph);
|
|
2223
|
-
root.needsRebuild = false;
|
|
2224
|
-
}
|
|
2225
|
-
const providedState = root.getState?.() ?? {};
|
|
2226
|
-
const frameState = {
|
|
2227
|
-
...providedState,
|
|
2228
|
-
time: timestamp,
|
|
2229
|
-
delta,
|
|
2230
|
-
elapsed: this.loopState.elapsedTime / 1e3,
|
|
2231
|
-
// Convert ms to seconds
|
|
2232
|
-
frame: this.loopState.frameCount
|
|
2233
|
-
};
|
|
2234
|
-
for (const job of root.sortedJobs) {
|
|
2235
|
-
if (!shouldRun(job, timestamp)) continue;
|
|
2236
|
-
try {
|
|
2237
|
-
job.callback(frameState, delta);
|
|
2238
|
-
} catch (error) {
|
|
2239
|
-
console.error(`[Scheduler] Error in job "${job.id}":`, error);
|
|
2240
|
-
this.triggerError(error instanceof Error ? error : new Error(String(error)));
|
|
2347
|
+
}
|
|
2348
|
+
/**
|
|
2349
|
+
* Execute all jobs for a single root in sorted order.
|
|
2350
|
+
* Rebuilds sorted job list if needed, then dispatches each job.
|
|
2351
|
+
* Errors are caught and propagated via triggerError.
|
|
2352
|
+
* @param {RootEntry} root - The root entry to tick
|
|
2353
|
+
* @param {number} timestamp - RAF timestamp in milliseconds
|
|
2354
|
+
* @param {number} delta - Time since last frame in seconds
|
|
2355
|
+
* @returns {void}
|
|
2356
|
+
* @private
|
|
2357
|
+
*/
|
|
2358
|
+
tickRoot(root, timestamp, delta) {
|
|
2359
|
+
if (root.needsRebuild) {
|
|
2360
|
+
root.sortedJobs = rebuildSortedJobs(root.jobs, this.phaseGraph);
|
|
2361
|
+
root.needsRebuild = false;
|
|
2362
|
+
}
|
|
2363
|
+
const providedState = root.getState?.() ?? {};
|
|
2364
|
+
const frameState = {
|
|
2365
|
+
...providedState,
|
|
2366
|
+
time: timestamp,
|
|
2367
|
+
delta,
|
|
2368
|
+
elapsed: this.loopState.elapsedTime / 1e3,
|
|
2369
|
+
// Convert ms to seconds
|
|
2370
|
+
frame: this.loopState.frameCount
|
|
2371
|
+
};
|
|
2372
|
+
for (const job of root.sortedJobs) {
|
|
2373
|
+
if (!shouldRun(job, timestamp)) continue;
|
|
2374
|
+
try {
|
|
2375
|
+
job.callback(frameState, delta);
|
|
2376
|
+
} catch (error) {
|
|
2377
|
+
console.error(`[Scheduler] Error in job "${job.id}":`, error);
|
|
2378
|
+
this.triggerError(error instanceof Error ? error : new Error(String(error)));
|
|
2379
|
+
}
|
|
2380
|
+
}
|
|
2381
|
+
}
|
|
2382
|
+
//* Debug & Inspection Methods ================================
|
|
2383
|
+
/**
|
|
2384
|
+
* Get the total number of registered jobs across all roots.
|
|
2385
|
+
* Includes both per-root jobs and global before/after jobs.
|
|
2386
|
+
* @returns {number} Total job count
|
|
2387
|
+
*/
|
|
2388
|
+
getJobCount() {
|
|
2389
|
+
let count = 0;
|
|
2390
|
+
for (const root of this.roots.values()) {
|
|
2391
|
+
count += root.jobs.size;
|
|
2392
|
+
}
|
|
2393
|
+
return count + this.globalBeforeJobs.size + this.globalAfterJobs.size;
|
|
2394
|
+
}
|
|
2395
|
+
/**
|
|
2396
|
+
* Get all registered job IDs across all roots.
|
|
2397
|
+
* Includes both per-root jobs and global before/after jobs.
|
|
2398
|
+
* @returns {string[]} Array of all job IDs
|
|
2399
|
+
*/
|
|
2400
|
+
getJobIds() {
|
|
2401
|
+
const ids = [];
|
|
2402
|
+
for (const root of this.roots.values()) {
|
|
2403
|
+
ids.push(...root.jobs.keys());
|
|
2404
|
+
}
|
|
2405
|
+
ids.push(...this.globalBeforeJobs.keys());
|
|
2406
|
+
ids.push(...this.globalAfterJobs.keys());
|
|
2407
|
+
return ids;
|
|
2408
|
+
}
|
|
2409
|
+
/**
|
|
2410
|
+
* Get the number of registered roots (Canvas instances).
|
|
2411
|
+
* @returns {number} Number of registered roots
|
|
2412
|
+
*/
|
|
2413
|
+
getRootCount() {
|
|
2414
|
+
return this.roots.size;
|
|
2415
|
+
}
|
|
2416
|
+
/**
|
|
2417
|
+
* Check if any user (non-system) jobs are registered in a specific phase.
|
|
2418
|
+
* Used by the default render job to know if a user has taken over rendering.
|
|
2419
|
+
*
|
|
2420
|
+
* @param phase The phase to check
|
|
2421
|
+
* @param rootId Optional root ID to check (checks all roots if not provided)
|
|
2422
|
+
* @returns true if any user jobs exist in the phase
|
|
2423
|
+
*/
|
|
2424
|
+
hasUserJobsInPhase(phase, rootId) {
|
|
2425
|
+
const rootsToCheck = rootId ? [this.roots.get(rootId)].filter(Boolean) : Array.from(this.roots.values());
|
|
2426
|
+
return rootsToCheck.some((root) => {
|
|
2427
|
+
if (!root) return false;
|
|
2428
|
+
for (const job of root.jobs.values()) {
|
|
2429
|
+
if (job.phase === phase && !job.system && job.enabled) return true;
|
|
2430
|
+
}
|
|
2431
|
+
return false;
|
|
2432
|
+
});
|
|
2433
|
+
}
|
|
2434
|
+
//* Utility Methods ================================
|
|
2435
|
+
/**
|
|
2436
|
+
* Generate a unique root ID for automatic root registration.
|
|
2437
|
+
* @returns {string} A unique root ID in the format 'root_N'
|
|
2438
|
+
*/
|
|
2439
|
+
generateRootId() {
|
|
2440
|
+
return `root_${this.nextRootIndex++}`;
|
|
2441
|
+
}
|
|
2442
|
+
/**
|
|
2443
|
+
* Generate a unique job ID.
|
|
2444
|
+
* @returns {string} A unique job ID in the format 'job_N'
|
|
2445
|
+
* @private
|
|
2446
|
+
*/
|
|
2447
|
+
generateJobId() {
|
|
2448
|
+
return `job_${this.nextJobIndex}`;
|
|
2449
|
+
}
|
|
2450
|
+
/**
|
|
2451
|
+
* Normalize before/after constraints to a Set.
|
|
2452
|
+
* Handles undefined, single string, or array inputs.
|
|
2453
|
+
* @param {string | string[] | undefined} value - The constraint value(s)
|
|
2454
|
+
* @returns {Set<string>} Normalized Set of constraint strings
|
|
2455
|
+
* @private
|
|
2456
|
+
*/
|
|
2457
|
+
normalizeConstraints(value) {
|
|
2458
|
+
if (!value) return /* @__PURE__ */ new Set();
|
|
2459
|
+
if (Array.isArray(value)) return new Set(value);
|
|
2460
|
+
return /* @__PURE__ */ new Set([value]);
|
|
2461
|
+
}
|
|
2462
|
+
};
|
|
2463
|
+
//* Static State & Methods (Singleton Usage) ================================
|
|
2464
|
+
//* Cross-Bundle Singleton Key ==============================
|
|
2465
|
+
// Use Symbol.for() to ensure scheduler is shared across bundle boundaries
|
|
2466
|
+
// This prevents issues when mixing imports from @react-three/fiber and @react-three/fiber/webgpu
|
|
2467
|
+
__publicField(_Scheduler, "INSTANCE_KEY", Symbol.for("@react-three/fiber.scheduler"));
|
|
2468
|
+
let Scheduler = _Scheduler;
|
|
2469
|
+
const getScheduler = () => Scheduler.get();
|
|
2470
|
+
if (hmrData) {
|
|
2471
|
+
hmrData.accept?.();
|
|
2472
|
+
}
|
|
2473
|
+
|
|
2474
|
+
const R3F_CONTEXT = Symbol.for("@react-three/fiber.context");
|
|
2475
|
+
const context = globalThis[R3F_CONTEXT] ?? (globalThis[R3F_CONTEXT] = React.createContext(null));
|
|
2476
|
+
const createStore = (invalidate, advance) => {
|
|
2477
|
+
const rootStore = createWithEqualityFn((set, get) => {
|
|
2478
|
+
const position = new Vector3();
|
|
2479
|
+
const defaultTarget = new Vector3();
|
|
2480
|
+
const tempTarget = new Vector3();
|
|
2481
|
+
function getCurrentViewport(camera = get().camera, target = defaultTarget, size = get().size) {
|
|
2482
|
+
const { width, height, top, left } = size;
|
|
2483
|
+
const aspect = width / height;
|
|
2484
|
+
if (target.isVector3) tempTarget.copy(target);
|
|
2485
|
+
else tempTarget.set(...target);
|
|
2486
|
+
const distance = camera.getWorldPosition(position).distanceTo(tempTarget);
|
|
2487
|
+
if (isOrthographicCamera(camera)) {
|
|
2488
|
+
return { width: width / camera.zoom, height: height / camera.zoom, top, left, factor: 1, distance, aspect };
|
|
2489
|
+
} else {
|
|
2490
|
+
const fov = camera.fov * Math.PI / 180;
|
|
2491
|
+
const h = 2 * Math.tan(fov / 2) * distance;
|
|
2492
|
+
const w = h * (width / height);
|
|
2493
|
+
return { width: w, height: h, top, left, factor: width / w, distance, aspect };
|
|
2494
|
+
}
|
|
2495
|
+
}
|
|
2496
|
+
let performanceTimeout = void 0;
|
|
2497
|
+
const setPerformanceCurrent = (current) => set((state2) => ({ performance: { ...state2.performance, current } }));
|
|
2498
|
+
const pointer = new Vector2();
|
|
2499
|
+
const rootState = {
|
|
2500
|
+
set,
|
|
2501
|
+
get,
|
|
2502
|
+
// Mock objects that have to be configured
|
|
2503
|
+
// primaryStore is set after store creation (self-reference for primary, primary's store for secondary)
|
|
2504
|
+
primaryStore: null,
|
|
2505
|
+
gl: null,
|
|
2506
|
+
renderer: null,
|
|
2507
|
+
camera: null,
|
|
2508
|
+
frustum: new Frustum(),
|
|
2509
|
+
autoUpdateFrustum: true,
|
|
2510
|
+
raycaster: null,
|
|
2511
|
+
events: { priority: 1, enabled: true, connected: false },
|
|
2512
|
+
scene: null,
|
|
2513
|
+
rootScene: null,
|
|
2514
|
+
xr: null,
|
|
2515
|
+
inspector: null,
|
|
2516
|
+
invalidate: (frames = 1, stackFrames = false) => invalidate(get(), frames, stackFrames),
|
|
2517
|
+
advance: (timestamp, runGlobalEffects) => advance(timestamp, runGlobalEffects, get()),
|
|
2518
|
+
textureColorSpace: SRGBColorSpace,
|
|
2519
|
+
isLegacy: false,
|
|
2520
|
+
webGPUSupported: false,
|
|
2521
|
+
isNative: false,
|
|
2522
|
+
controls: null,
|
|
2523
|
+
pointer,
|
|
2524
|
+
mouse: pointer,
|
|
2525
|
+
frameloop: "always",
|
|
2526
|
+
onPointerMissed: void 0,
|
|
2527
|
+
onDragOverMissed: void 0,
|
|
2528
|
+
onDropMissed: void 0,
|
|
2529
|
+
performance: {
|
|
2530
|
+
current: 1,
|
|
2531
|
+
min: 0.5,
|
|
2532
|
+
max: 1,
|
|
2533
|
+
debounce: 200,
|
|
2534
|
+
regress: () => {
|
|
2535
|
+
const state2 = get();
|
|
2536
|
+
if (performanceTimeout) clearTimeout(performanceTimeout);
|
|
2537
|
+
if (state2.performance.current !== state2.performance.min) setPerformanceCurrent(state2.performance.min);
|
|
2538
|
+
performanceTimeout = setTimeout(
|
|
2539
|
+
() => setPerformanceCurrent(get().performance.max),
|
|
2540
|
+
state2.performance.debounce
|
|
2541
|
+
);
|
|
2542
|
+
}
|
|
2543
|
+
},
|
|
2544
|
+
size: { width: 0, height: 0, top: 0, left: 0 },
|
|
2545
|
+
viewport: {
|
|
2546
|
+
initialDpr: 0,
|
|
2547
|
+
dpr: 0,
|
|
2548
|
+
width: 0,
|
|
2549
|
+
height: 0,
|
|
2550
|
+
top: 0,
|
|
2551
|
+
left: 0,
|
|
2552
|
+
aspect: 0,
|
|
2553
|
+
distance: 0,
|
|
2554
|
+
factor: 0,
|
|
2555
|
+
getCurrentViewport
|
|
2556
|
+
},
|
|
2557
|
+
setEvents: (events) => set((state2) => ({ ...state2, events: { ...state2.events, ...events } })),
|
|
2558
|
+
setSize: (width, height, top, left) => {
|
|
2559
|
+
const state2 = get();
|
|
2560
|
+
if (width === void 0) {
|
|
2561
|
+
set({ _sizeImperative: false });
|
|
2562
|
+
if (state2._sizeProps) {
|
|
2563
|
+
const { width: propW, height: propH } = state2._sizeProps;
|
|
2564
|
+
if (propW !== void 0 || propH !== void 0) {
|
|
2565
|
+
const currentSize = state2.size;
|
|
2566
|
+
const newSize = {
|
|
2567
|
+
width: propW ?? currentSize.width,
|
|
2568
|
+
height: propH ?? currentSize.height,
|
|
2569
|
+
top: currentSize.top,
|
|
2570
|
+
left: currentSize.left
|
|
2571
|
+
};
|
|
2572
|
+
set((s) => ({
|
|
2573
|
+
size: newSize,
|
|
2574
|
+
viewport: { ...s.viewport, ...getCurrentViewport(state2.camera, defaultTarget, newSize) }
|
|
2575
|
+
}));
|
|
2576
|
+
getScheduler().invalidate();
|
|
2577
|
+
}
|
|
2578
|
+
}
|
|
2579
|
+
return;
|
|
2580
|
+
}
|
|
2581
|
+
const w = width;
|
|
2582
|
+
const h = height ?? width;
|
|
2583
|
+
const t = top ?? state2.size.top;
|
|
2584
|
+
const l = left ?? state2.size.left;
|
|
2585
|
+
const size = { width: w, height: h, top: t, left: l };
|
|
2586
|
+
set((s) => ({
|
|
2587
|
+
size,
|
|
2588
|
+
viewport: { ...s.viewport, ...getCurrentViewport(state2.camera, defaultTarget, size) },
|
|
2589
|
+
_sizeImperative: true
|
|
2590
|
+
}));
|
|
2591
|
+
getScheduler().invalidate();
|
|
2592
|
+
},
|
|
2593
|
+
setDpr: (dpr) => set((state2) => {
|
|
2594
|
+
const resolved = calculateDpr(dpr);
|
|
2595
|
+
return { viewport: { ...state2.viewport, dpr: resolved, initialDpr: state2.viewport.initialDpr || resolved } };
|
|
2596
|
+
}),
|
|
2597
|
+
setFrameloop: (frameloop = "always") => {
|
|
2598
|
+
set(() => ({ frameloop }));
|
|
2599
|
+
},
|
|
2600
|
+
setError: (error) => set(() => ({ error })),
|
|
2601
|
+
error: null,
|
|
2602
|
+
//* TSL State (managed via hooks: useUniforms, useNodes, useTextures, usePostProcessing) ==============================
|
|
2603
|
+
uniforms: {},
|
|
2604
|
+
nodes: {},
|
|
2605
|
+
textures: /* @__PURE__ */ new Map(),
|
|
2606
|
+
postProcessing: null,
|
|
2607
|
+
passes: {},
|
|
2608
|
+
_hmrVersion: 0,
|
|
2609
|
+
_sizeImperative: false,
|
|
2610
|
+
_sizeProps: null,
|
|
2611
|
+
previousRoot: void 0,
|
|
2612
|
+
internal: {
|
|
2613
|
+
// Events
|
|
2614
|
+
interaction: [],
|
|
2615
|
+
hovered: /* @__PURE__ */ new Map(),
|
|
2616
|
+
subscribers: [],
|
|
2617
|
+
initialClick: [0, 0],
|
|
2618
|
+
initialHits: [],
|
|
2619
|
+
capturedMap: /* @__PURE__ */ new Map(),
|
|
2620
|
+
lastEvent: React.createRef(),
|
|
2621
|
+
// Visibility tracking (onFramed, onOccluded, onVisible)
|
|
2622
|
+
visibilityRegistry: /* @__PURE__ */ new Map(),
|
|
2623
|
+
// Occlusion system (WebGPU only)
|
|
2624
|
+
occlusionEnabled: false,
|
|
2625
|
+
occlusionObserver: null,
|
|
2626
|
+
occlusionCache: /* @__PURE__ */ new Map(),
|
|
2627
|
+
helperGroup: null,
|
|
2628
|
+
// Updates
|
|
2629
|
+
active: false,
|
|
2630
|
+
frames: 0,
|
|
2631
|
+
priority: 0,
|
|
2632
|
+
subscribe: (ref, priority, store) => {
|
|
2633
|
+
const internal = get().internal;
|
|
2634
|
+
internal.priority = internal.priority + (priority > 0 ? 1 : 0);
|
|
2635
|
+
internal.subscribers.push({ ref, priority, store });
|
|
2636
|
+
internal.subscribers = internal.subscribers.sort((a, b) => a.priority - b.priority);
|
|
2637
|
+
return () => {
|
|
2638
|
+
const internal2 = get().internal;
|
|
2639
|
+
if (internal2?.subscribers) {
|
|
2640
|
+
internal2.priority = internal2.priority - (priority > 0 ? 1 : 0);
|
|
2641
|
+
internal2.subscribers = internal2.subscribers.filter((s) => s.ref !== ref);
|
|
2642
|
+
}
|
|
2643
|
+
};
|
|
2644
|
+
},
|
|
2645
|
+
// Renderer Storage (single source of truth)
|
|
2646
|
+
actualRenderer: null,
|
|
2647
|
+
// Scheduler for useFrameNext (initialized in renderer.tsx)
|
|
2648
|
+
scheduler: null
|
|
2649
|
+
}
|
|
2650
|
+
};
|
|
2651
|
+
return rootState;
|
|
2652
|
+
});
|
|
2653
|
+
const state = rootStore.getState();
|
|
2654
|
+
Object.defineProperty(state, "gl", {
|
|
2655
|
+
get() {
|
|
2656
|
+
const currentState = rootStore.getState();
|
|
2657
|
+
if (!currentState.isLegacy && currentState.internal.actualRenderer) {
|
|
2658
|
+
const stack = new Error().stack || "";
|
|
2659
|
+
const isInternalAccess = stack.includes("zustand") || stack.includes("setState") || stack.includes("Object.assign") || stack.includes("react-three-fiber/packages/fiber/src/core");
|
|
2660
|
+
if (!isInternalAccess) {
|
|
2661
|
+
const cleanedStack = stack.split("\n").slice(2).join("\n") || "Stack trace unavailable";
|
|
2662
|
+
notifyDepreciated({
|
|
2663
|
+
heading: "Accessing state.gl in WebGPU mode",
|
|
2664
|
+
body: "Please use state.renderer instead. state.gl is deprecated and will be removed in future versions.\n\nFor backwards compatibility, state.gl currently maps to state.renderer, but this may cause issues with libraries expecting WebGLRenderer.\n\nAccessed from:\n" + cleanedStack
|
|
2665
|
+
});
|
|
2666
|
+
}
|
|
2667
|
+
}
|
|
2668
|
+
return currentState.internal.actualRenderer;
|
|
2669
|
+
},
|
|
2670
|
+
set(value) {
|
|
2671
|
+
rootStore.getState().internal.actualRenderer = value;
|
|
2672
|
+
},
|
|
2673
|
+
enumerable: true,
|
|
2674
|
+
configurable: true
|
|
2675
|
+
});
|
|
2676
|
+
Object.defineProperty(state, "renderer", {
|
|
2677
|
+
get() {
|
|
2678
|
+
return rootStore.getState().internal.actualRenderer;
|
|
2679
|
+
},
|
|
2680
|
+
set(value) {
|
|
2681
|
+
rootStore.getState().internal.actualRenderer = value;
|
|
2682
|
+
},
|
|
2683
|
+
enumerable: true,
|
|
2684
|
+
configurable: true
|
|
2685
|
+
});
|
|
2686
|
+
let oldScene = state.scene;
|
|
2687
|
+
rootStore.subscribe(() => {
|
|
2688
|
+
const currentState = rootStore.getState();
|
|
2689
|
+
const { scene, rootScene, set } = currentState;
|
|
2690
|
+
if (scene !== oldScene) {
|
|
2691
|
+
oldScene = scene;
|
|
2692
|
+
if (scene?.isScene && scene !== rootScene) {
|
|
2693
|
+
set({ rootScene: scene });
|
|
2694
|
+
}
|
|
2695
|
+
}
|
|
2696
|
+
});
|
|
2697
|
+
let oldSize = state.size;
|
|
2698
|
+
let oldDpr = state.viewport.dpr;
|
|
2699
|
+
let oldCamera = state.camera;
|
|
2700
|
+
rootStore.subscribe(() => {
|
|
2701
|
+
const { camera, size, viewport, set, internal } = rootStore.getState();
|
|
2702
|
+
const actualRenderer = internal.actualRenderer;
|
|
2703
|
+
const canvasTarget = internal.canvasTarget;
|
|
2704
|
+
if (size.width !== oldSize.width || size.height !== oldSize.height || viewport.dpr !== oldDpr) {
|
|
2705
|
+
oldSize = size;
|
|
2706
|
+
oldDpr = viewport.dpr;
|
|
2707
|
+
updateCamera(camera, size);
|
|
2708
|
+
if (canvasTarget) {
|
|
2709
|
+
if (viewport.dpr > 0) canvasTarget.setPixelRatio(viewport.dpr);
|
|
2710
|
+
const updateStyle = typeof HTMLCanvasElement !== "undefined" && canvasTarget.domElement instanceof HTMLCanvasElement;
|
|
2711
|
+
canvasTarget.setSize(size.width, size.height, updateStyle);
|
|
2712
|
+
} else {
|
|
2713
|
+
if (viewport.dpr > 0) actualRenderer.setPixelRatio(viewport.dpr);
|
|
2714
|
+
const updateStyle = typeof HTMLCanvasElement !== "undefined" && actualRenderer.domElement instanceof HTMLCanvasElement;
|
|
2715
|
+
actualRenderer.setSize(size.width, size.height, updateStyle);
|
|
2716
|
+
}
|
|
2717
|
+
}
|
|
2718
|
+
if (camera !== oldCamera) {
|
|
2719
|
+
oldCamera = camera;
|
|
2720
|
+
const { rootScene } = rootStore.getState();
|
|
2721
|
+
if (camera && rootScene && !camera.parent) {
|
|
2722
|
+
rootScene.add(camera);
|
|
2723
|
+
}
|
|
2724
|
+
set((state2) => ({ viewport: { ...state2.viewport, ...state2.viewport.getCurrentViewport(camera) } }));
|
|
2725
|
+
const currentState = rootStore.getState();
|
|
2726
|
+
if (currentState.autoUpdateFrustum && camera) {
|
|
2727
|
+
updateFrustum(camera, currentState.frustum);
|
|
2241
2728
|
}
|
|
2242
2729
|
}
|
|
2243
|
-
}
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2730
|
+
});
|
|
2731
|
+
rootStore.subscribe((state2) => invalidate(state2));
|
|
2732
|
+
return rootStore;
|
|
2733
|
+
};
|
|
2734
|
+
|
|
2735
|
+
const memoizedLoaders = /* @__PURE__ */ new WeakMap();
|
|
2736
|
+
const isConstructor$1 = (value) => typeof value === "function" && value?.prototype?.constructor === value;
|
|
2737
|
+
function getLoader(Proto) {
|
|
2738
|
+
if (isConstructor$1(Proto)) {
|
|
2739
|
+
let loader = memoizedLoaders.get(Proto);
|
|
2740
|
+
if (!loader) {
|
|
2741
|
+
loader = new Proto();
|
|
2742
|
+
memoizedLoaders.set(Proto, loader);
|
|
2254
2743
|
}
|
|
2255
|
-
return
|
|
2744
|
+
return loader;
|
|
2256
2745
|
}
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2746
|
+
return Proto;
|
|
2747
|
+
}
|
|
2748
|
+
function loadingFn(extensions, onProgress) {
|
|
2749
|
+
return function(Proto, input) {
|
|
2750
|
+
const loader = getLoader(Proto);
|
|
2751
|
+
if (extensions) extensions(loader);
|
|
2752
|
+
if ("loadAsync" in loader && typeof loader.loadAsync === "function") {
|
|
2753
|
+
return loader.loadAsync(input, onProgress).then((data) => {
|
|
2754
|
+
if (isObject3D(data?.scene)) Object.assign(data, buildGraph(data.scene));
|
|
2755
|
+
return data;
|
|
2756
|
+
});
|
|
2266
2757
|
}
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
*/
|
|
2286
|
-
hasUserJobsInPhase(phase, rootId) {
|
|
2287
|
-
const rootsToCheck = rootId ? [this.roots.get(rootId)].filter(Boolean) : Array.from(this.roots.values());
|
|
2288
|
-
return rootsToCheck.some((root) => {
|
|
2289
|
-
if (!root) return false;
|
|
2290
|
-
for (const job of root.jobs.values()) {
|
|
2291
|
-
if (job.phase === phase && !job.system && job.enabled) return true;
|
|
2292
|
-
}
|
|
2293
|
-
return false;
|
|
2294
|
-
});
|
|
2295
|
-
}
|
|
2296
|
-
//* Utility Methods ================================
|
|
2297
|
-
/**
|
|
2298
|
-
* Generate a unique root ID for automatic root registration.
|
|
2299
|
-
* @returns {string} A unique root ID in the format 'root_N'
|
|
2300
|
-
*/
|
|
2301
|
-
generateRootId() {
|
|
2302
|
-
return `root_${this.nextRootIndex++}`;
|
|
2303
|
-
}
|
|
2304
|
-
/**
|
|
2305
|
-
* Generate a unique job ID.
|
|
2306
|
-
* @returns {string} A unique job ID in the format 'job_N'
|
|
2307
|
-
* @private
|
|
2308
|
-
*/
|
|
2309
|
-
generateJobId() {
|
|
2310
|
-
return `job_${this.nextJobIndex}`;
|
|
2311
|
-
}
|
|
2312
|
-
/**
|
|
2313
|
-
* Normalize before/after constraints to a Set.
|
|
2314
|
-
* Handles undefined, single string, or array inputs.
|
|
2315
|
-
* @param {string | string[] | undefined} value - The constraint value(s)
|
|
2316
|
-
* @returns {Set<string>} Normalized Set of constraint strings
|
|
2317
|
-
* @private
|
|
2318
|
-
*/
|
|
2319
|
-
normalizeConstraints(value) {
|
|
2320
|
-
if (!value) return /* @__PURE__ */ new Set();
|
|
2321
|
-
if (Array.isArray(value)) return new Set(value);
|
|
2322
|
-
return /* @__PURE__ */ new Set([value]);
|
|
2323
|
-
}
|
|
2324
|
-
};
|
|
2325
|
-
//* Static State & Methods (Singleton Usage) ================================
|
|
2326
|
-
//* Cross-Bundle Singleton Key ==============================
|
|
2327
|
-
// Use Symbol.for() to ensure scheduler is shared across bundle boundaries
|
|
2328
|
-
// This prevents issues when mixing imports from @react-three/fiber and @react-three/fiber/webgpu
|
|
2329
|
-
__publicField(_Scheduler, "INSTANCE_KEY", Symbol.for("@react-three/fiber.scheduler"));
|
|
2330
|
-
let Scheduler = _Scheduler;
|
|
2331
|
-
const getScheduler = () => Scheduler.get();
|
|
2332
|
-
if (hmrData) {
|
|
2333
|
-
hmrData.accept?.();
|
|
2758
|
+
return new Promise(
|
|
2759
|
+
(res, reject) => loader.load(
|
|
2760
|
+
input,
|
|
2761
|
+
(data) => {
|
|
2762
|
+
if (isObject3D(data?.scene)) Object.assign(data, buildGraph(data.scene));
|
|
2763
|
+
res(data);
|
|
2764
|
+
},
|
|
2765
|
+
onProgress,
|
|
2766
|
+
(error) => reject(new Error(`Could not load ${input}: ${error?.message}`))
|
|
2767
|
+
)
|
|
2768
|
+
);
|
|
2769
|
+
};
|
|
2770
|
+
}
|
|
2771
|
+
function useLoader(loader, input, extensions, onProgress) {
|
|
2772
|
+
const keys = Array.isArray(input) ? input : [input];
|
|
2773
|
+
const fn = loadingFn(extensions, onProgress);
|
|
2774
|
+
const results = keys.map((key) => suspend(fn, [loader, key], { equal: is.equ }));
|
|
2775
|
+
return Array.isArray(input) ? results : results[0];
|
|
2334
2776
|
}
|
|
2777
|
+
useLoader.preload = function(loader, input, extensions, onProgress) {
|
|
2778
|
+
const keys = Array.isArray(input) ? input : [input];
|
|
2779
|
+
keys.forEach((key) => preload(loadingFn(extensions, onProgress), [loader, key]));
|
|
2780
|
+
};
|
|
2781
|
+
useLoader.clear = function(loader, input) {
|
|
2782
|
+
const keys = Array.isArray(input) ? input : [input];
|
|
2783
|
+
keys.forEach((key) => clear([loader, key]));
|
|
2784
|
+
};
|
|
2785
|
+
useLoader.loader = getLoader;
|
|
2335
2786
|
|
|
2336
2787
|
function useFrame(callback, priorityOrOptions) {
|
|
2337
2788
|
const store = React.useContext(context);
|
|
@@ -2512,6 +2963,9 @@ function useTexture(input, optionsOrOnLoad) {
|
|
|
2512
2963
|
const textureCache = useThree((state) => state.textures);
|
|
2513
2964
|
const options = typeof optionsOrOnLoad === "function" ? { onLoad: optionsOrOnLoad } : optionsOrOnLoad ?? {};
|
|
2514
2965
|
const { onLoad, cache = false } = options;
|
|
2966
|
+
const onLoadRef = useRef(onLoad);
|
|
2967
|
+
onLoadRef.current = onLoad;
|
|
2968
|
+
const onLoadCalledForRef = useRef(null);
|
|
2515
2969
|
const urls = useMemo(() => getUrls(input), [input]);
|
|
2516
2970
|
const cachedResult = useMemo(() => {
|
|
2517
2971
|
if (!cache) return null;
|
|
@@ -2522,9 +2976,13 @@ function useTexture(input, optionsOrOnLoad) {
|
|
|
2522
2976
|
TextureLoader,
|
|
2523
2977
|
IsObject(input) ? Object.values(input) : input
|
|
2524
2978
|
);
|
|
2979
|
+
const inputKey = urls.join("\0");
|
|
2525
2980
|
useLayoutEffect(() => {
|
|
2526
|
-
if (
|
|
2527
|
-
|
|
2981
|
+
if (cachedResult) return;
|
|
2982
|
+
if (onLoadCalledForRef.current === inputKey) return;
|
|
2983
|
+
onLoadCalledForRef.current = inputKey;
|
|
2984
|
+
onLoadRef.current?.(loadedTextures);
|
|
2985
|
+
}, [cachedResult, loadedTextures, inputKey]);
|
|
2528
2986
|
useEffect(() => {
|
|
2529
2987
|
if (cachedResult) return;
|
|
2530
2988
|
if ("initTexture" in renderer) {
|
|
@@ -2691,14 +3149,31 @@ function useTextures() {
|
|
|
2691
3149
|
}, [store]);
|
|
2692
3150
|
}
|
|
2693
3151
|
|
|
2694
|
-
function useRenderTarget(
|
|
3152
|
+
function useRenderTarget(widthOrOptions, heightOrOptions, options) {
|
|
2695
3153
|
const isLegacy = useThree((s) => s.isLegacy);
|
|
2696
3154
|
const size = useThree((s) => s.size);
|
|
3155
|
+
let width;
|
|
3156
|
+
let height;
|
|
3157
|
+
let opts;
|
|
3158
|
+
if (typeof widthOrOptions === "object") {
|
|
3159
|
+
opts = widthOrOptions;
|
|
3160
|
+
} else if (typeof widthOrOptions === "number") {
|
|
3161
|
+
width = widthOrOptions;
|
|
3162
|
+
if (typeof heightOrOptions === "object") {
|
|
3163
|
+
height = widthOrOptions;
|
|
3164
|
+
opts = heightOrOptions;
|
|
3165
|
+
} else if (typeof heightOrOptions === "number") {
|
|
3166
|
+
height = heightOrOptions;
|
|
3167
|
+
opts = options;
|
|
3168
|
+
} else {
|
|
3169
|
+
height = widthOrOptions;
|
|
3170
|
+
}
|
|
3171
|
+
}
|
|
2697
3172
|
return useMemo(() => {
|
|
2698
3173
|
const w = width ?? size.width;
|
|
2699
3174
|
const h = height ?? size.height;
|
|
2700
|
-
return new WebGLRenderTarget(w, h,
|
|
2701
|
-
}, [width, height, size.width, size.height,
|
|
3175
|
+
return new WebGLRenderTarget(w, h, opts);
|
|
3176
|
+
}, [width, height, size.width, size.height, opts, isLegacy]);
|
|
2702
3177
|
}
|
|
2703
3178
|
|
|
2704
3179
|
function useStore() {
|
|
@@ -2748,28 +3223,18 @@ function addTail(callback) {
|
|
|
2748
3223
|
function invalidate(state, frames = 1, stackFrames = false) {
|
|
2749
3224
|
getScheduler().invalidate(frames, stackFrames);
|
|
2750
3225
|
}
|
|
2751
|
-
function advance(timestamp
|
|
3226
|
+
function advance(timestamp) {
|
|
2752
3227
|
getScheduler().step(timestamp);
|
|
2753
3228
|
}
|
|
2754
3229
|
|
|
2755
|
-
const version = "10.0.0-alpha.
|
|
3230
|
+
const version = "10.0.0-alpha.2";
|
|
2756
3231
|
const packageData = {
|
|
2757
3232
|
version: version};
|
|
2758
3233
|
|
|
2759
3234
|
function Xb(Tt) {
|
|
2760
3235
|
return Tt && Tt.__esModule && Object.prototype.hasOwnProperty.call(Tt, "default") ? Tt.default : Tt;
|
|
2761
3236
|
}
|
|
2762
|
-
var Rm = { exports: {} }, Og = { exports: {} };
|
|
2763
|
-
/**
|
|
2764
|
-
* @license React
|
|
2765
|
-
* react-reconciler.production.js
|
|
2766
|
-
*
|
|
2767
|
-
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2768
|
-
*
|
|
2769
|
-
* This source code is licensed under the MIT license found in the
|
|
2770
|
-
* LICENSE file in the root directory of this source tree.
|
|
2771
|
-
*/
|
|
2772
|
-
var _b;
|
|
3237
|
+
var Rm = { exports: {} }, Og = { exports: {} }, _b;
|
|
2773
3238
|
function Kb() {
|
|
2774
3239
|
return _b || (_b = 1, (function(Tt) {
|
|
2775
3240
|
Tt.exports = function(m) {
|
|
@@ -3841,7 +4306,6 @@ Error generating stack: ` + l.message + `
|
|
|
3841
4306
|
if (J === cl || J === jc) throw J;
|
|
3842
4307
|
var Ge = Yn(29, J, null, P.mode);
|
|
3843
4308
|
return Ge.lanes = H, Ge.return = P, Ge;
|
|
3844
|
-
} finally {
|
|
3845
4309
|
}
|
|
3846
4310
|
};
|
|
3847
4311
|
}
|
|
@@ -4495,7 +4959,6 @@ Error generating stack: ` + l.message + `
|
|
|
4495
4959
|
var h = r.lastRenderedState, y = d(h, a);
|
|
4496
4960
|
if (c.hasEagerState = true, c.eagerState = y, jn(y, h)) return go(t, r, c, 0), Ne === null && Bn(), false;
|
|
4497
4961
|
} catch {
|
|
4498
|
-
} finally {
|
|
4499
4962
|
}
|
|
4500
4963
|
if (a = yo(t, r, c, l), a !== null) return nt(a, t, l), ns(a, r, l), true;
|
|
4501
4964
|
}
|
|
@@ -6916,10 +7379,7 @@ Error generating stack: ` + l.message + `
|
|
|
6916
7379
|
function vr(t, r) {
|
|
6917
7380
|
Sf(t, r), (t = t.alternate) && Sf(t, r);
|
|
6918
7381
|
}
|
|
6919
|
-
var ie = {}, Fm = React__default, tt = Tb, Lt = Object.assign, hc = Symbol.for("react.element"), zs = Symbol.for("react.transitional.element"), sa = Symbol.for("react.portal"), $a = Symbol.for("react.fragment"), kf = Symbol.for("react.strict_mode"), Cs = Symbol.for("react.profiler"), mc = Symbol.for("react.consumer"), Io = Symbol.for("react.context"), Zi = Symbol.for("react.forward_ref"), Va = Symbol.for("react.suspense"), Te = Symbol.for("react.suspense_list"), wf = Symbol.for("react.memo"), ua = Symbol.for("react.lazy");
|
|
6920
|
-
var gc = Symbol.for("react.activity");
|
|
6921
|
-
var $r = Symbol.for("react.memo_cache_sentinel");
|
|
6922
|
-
var Pf = Symbol.iterator, xf = Symbol.for("react.client.reference"), ca = Array.isArray, M = Fm.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, Yp = m.rendererVersion, zf = m.rendererPackageName, Cf = m.extraDevToolsConfig, Ts = m.getPublicInstance, Hm = m.getRootHostContext, Xp = m.getChildHostContext, Am = m.prepareForCommit, _s = m.resetAfterCommit, Vr = m.createInstance;
|
|
7382
|
+
var ie = {}, Fm = React__default, tt = Tb, Lt = Object.assign, hc = Symbol.for("react.element"), zs = Symbol.for("react.transitional.element"), sa = Symbol.for("react.portal"), $a = Symbol.for("react.fragment"), kf = Symbol.for("react.strict_mode"), Cs = Symbol.for("react.profiler"), mc = Symbol.for("react.consumer"), Io = Symbol.for("react.context"), Zi = Symbol.for("react.forward_ref"), Va = Symbol.for("react.suspense"), Te = Symbol.for("react.suspense_list"), wf = Symbol.for("react.memo"), ua = Symbol.for("react.lazy"), gc = Symbol.for("react.activity"), $r = Symbol.for("react.memo_cache_sentinel"), Pf = Symbol.iterator, xf = Symbol.for("react.client.reference"), ca = Array.isArray, M = Fm.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, Yp = m.rendererVersion, zf = m.rendererPackageName, Cf = m.extraDevToolsConfig, Ts = m.getPublicInstance, Hm = m.getRootHostContext, Xp = m.getChildHostContext, Am = m.prepareForCommit, _s = m.resetAfterCommit, Vr = m.createInstance;
|
|
6923
7383
|
m.cloneMutableInstance;
|
|
6924
7384
|
var yc = m.appendInitialChild, Kp = m.finalizeInitialChildren, Rs = m.shouldSetTextContent, bc = m.createTextInstance;
|
|
6925
7385
|
m.cloneMutableTextInstance;
|
|
@@ -7288,17 +7748,7 @@ No matching component was found for:
|
|
|
7288
7748
|
}, Tt.exports.default = Tt.exports, Object.defineProperty(Tt.exports, "__esModule", { value: true });
|
|
7289
7749
|
})(Og)), Og.exports;
|
|
7290
7750
|
}
|
|
7291
|
-
var Mg = { exports: {} };
|
|
7292
|
-
/**
|
|
7293
|
-
* @license React
|
|
7294
|
-
* react-reconciler.development.js
|
|
7295
|
-
*
|
|
7296
|
-
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
7297
|
-
*
|
|
7298
|
-
* This source code is licensed under the MIT license found in the
|
|
7299
|
-
* LICENSE file in the root directory of this source tree.
|
|
7300
|
-
*/
|
|
7301
|
-
var Rb;
|
|
7751
|
+
var Mg = { exports: {} }, Rb;
|
|
7302
7752
|
function e0() {
|
|
7303
7753
|
return Rb || (Rb = 1, (function(Tt) {
|
|
7304
7754
|
process.env.NODE_ENV !== "production" && (Tt.exports = function(m) {
|
|
@@ -13065,10 +13515,7 @@ Check the render method of %s.`, G(di) || "Unknown")), i = zo(n), i.payload = {
|
|
|
13065
13515
|
function Ic() {
|
|
13066
13516
|
return di;
|
|
13067
13517
|
}
|
|
13068
|
-
var le = {}, qm = React__default, St = Tb, ze = Object.assign, Uh = Symbol.for("react.element"), Ho = Symbol.for("react.transitional.element"), Ao = Symbol.for("react.portal"), ol = Symbol.for("react.fragment"), Lc = Symbol.for("react.strict_mode"), Uf = Symbol.for("react.profiler"), ei = Symbol.for("react.consumer"), on = Symbol.for("react.context"), jn = Symbol.for("react.forward_ref"), Nc = Symbol.for("react.suspense"), Bf = Symbol.for("react.suspense_list"), al = Symbol.for("react.memo"), kt = Symbol.for("react.lazy");
|
|
13069
|
-
var Ds = Symbol.for("react.activity");
|
|
13070
|
-
var Bh = Symbol.for("react.memo_cache_sentinel");
|
|
13071
|
-
var ni = Symbol.iterator, il = Symbol.for("react.client.reference"), fn = Array.isArray, x = qm.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, Jt = m.rendererVersion, Zt = m.rendererPackageName, jo = m.extraDevToolsConfig, ot = m.getPublicInstance, Zr = m.getRootHostContext, Dn = m.getChildHostContext, Ws = m.prepareForCommit, pa = m.resetAfterCommit, Fc = m.createInstance;
|
|
13518
|
+
var le = {}, qm = React__default, St = Tb, ze = Object.assign, Uh = Symbol.for("react.element"), Ho = Symbol.for("react.transitional.element"), Ao = Symbol.for("react.portal"), ol = Symbol.for("react.fragment"), Lc = Symbol.for("react.strict_mode"), Uf = Symbol.for("react.profiler"), ei = Symbol.for("react.consumer"), on = Symbol.for("react.context"), jn = Symbol.for("react.forward_ref"), Nc = Symbol.for("react.suspense"), Bf = Symbol.for("react.suspense_list"), al = Symbol.for("react.memo"), kt = Symbol.for("react.lazy"), Ds = Symbol.for("react.activity"), Bh = Symbol.for("react.memo_cache_sentinel"), ni = Symbol.iterator, il = Symbol.for("react.client.reference"), fn = Array.isArray, x = qm.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, Jt = m.rendererVersion, Zt = m.rendererPackageName, jo = m.extraDevToolsConfig, ot = m.getPublicInstance, Zr = m.getRootHostContext, Dn = m.getChildHostContext, Ws = m.prepareForCommit, pa = m.resetAfterCommit, Fc = m.createInstance;
|
|
13072
13519
|
m.cloneMutableInstance;
|
|
13073
13520
|
var bn = m.appendInitialChild, Ue = m.finalizeInitialChildren, ue = m.shouldSetTextContent, Do = m.createTextInstance;
|
|
13074
13521
|
m.cloneMutableTextInstance;
|
|
@@ -14036,15 +14483,6 @@ function n0() {
|
|
|
14036
14483
|
var t0 = n0();
|
|
14037
14484
|
const r0 = Xb(t0);
|
|
14038
14485
|
|
|
14039
|
-
/**
|
|
14040
|
-
* @license React
|
|
14041
|
-
* react-reconciler-constants.production.js
|
|
14042
|
-
*
|
|
14043
|
-
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
14044
|
-
*
|
|
14045
|
-
* This source code is licensed under the MIT license found in the
|
|
14046
|
-
* LICENSE file in the root directory of this source tree.
|
|
14047
|
-
*/
|
|
14048
14486
|
const t = 1, o = 8, r = 32, e = 2;
|
|
14049
14487
|
|
|
14050
14488
|
function createReconciler(config) {
|
|
@@ -14071,10 +14509,11 @@ function extend(objects) {
|
|
|
14071
14509
|
function validateInstance(type, props) {
|
|
14072
14510
|
const name = toPascalCase(type);
|
|
14073
14511
|
const target = catalogue[name];
|
|
14074
|
-
if (type !== "primitive" && !target)
|
|
14512
|
+
if (type !== "primitive" && !target) {
|
|
14075
14513
|
throw new Error(
|
|
14076
14514
|
`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`
|
|
14077
14515
|
);
|
|
14516
|
+
}
|
|
14078
14517
|
if (type === "primitive" && !props.object) throw new Error(`R3F: Primitives without 'object' are invalid!`);
|
|
14079
14518
|
if (props.args !== void 0 && !Array.isArray(props.args)) throw new Error("R3F: The args prop must be an array!");
|
|
14080
14519
|
}
|
|
@@ -14238,6 +14677,7 @@ function swapInstances() {
|
|
|
14238
14677
|
instance.object = instance.props.object ?? new target(...instance.props.args ?? []);
|
|
14239
14678
|
instance.object.__r3f = instance;
|
|
14240
14679
|
setFiberRef(fiber, instance.object);
|
|
14680
|
+
delete instance.appliedOnce;
|
|
14241
14681
|
applyProps(instance.object, instance.props);
|
|
14242
14682
|
if (instance.props.attach) {
|
|
14243
14683
|
attach(parent, instance);
|
|
@@ -14311,8 +14751,22 @@ const reconciler = /* @__PURE__ */ createReconciler({
|
|
|
14311
14751
|
const isTailSibling = fiber.sibling === null || (fiber.flags & Update) === NoFlags;
|
|
14312
14752
|
if (isTailSibling) swapInstances();
|
|
14313
14753
|
},
|
|
14314
|
-
finalizeInitialChildren: () =>
|
|
14315
|
-
|
|
14754
|
+
finalizeInitialChildren: (instance) => {
|
|
14755
|
+
for (const prop in instance.props) {
|
|
14756
|
+
if (isFromRef(instance.props[prop])) return true;
|
|
14757
|
+
}
|
|
14758
|
+
return false;
|
|
14759
|
+
},
|
|
14760
|
+
commitMount(instance) {
|
|
14761
|
+
const resolved = {};
|
|
14762
|
+
for (const prop in instance.props) {
|
|
14763
|
+
const value = instance.props[prop];
|
|
14764
|
+
if (isFromRef(value)) {
|
|
14765
|
+
const ref = value[FROM_REF];
|
|
14766
|
+
if (ref.current != null) resolved[prop] = ref.current;
|
|
14767
|
+
}
|
|
14768
|
+
}
|
|
14769
|
+
if (Object.keys(resolved).length) applyProps(instance.object, resolved);
|
|
14316
14770
|
},
|
|
14317
14771
|
getPublicInstance: (instance) => instance?.object,
|
|
14318
14772
|
prepareForCommit: () => null,
|
|
@@ -14525,14 +14979,17 @@ function createRoot(canvas) {
|
|
|
14525
14979
|
if (!prevRoot) _roots.set(canvas, { fiber, store });
|
|
14526
14980
|
let onCreated;
|
|
14527
14981
|
let lastCamera;
|
|
14528
|
-
|
|
14982
|
+
const lastConfiguredProps = {};
|
|
14529
14983
|
let configured = false;
|
|
14530
14984
|
let pending = null;
|
|
14531
14985
|
return {
|
|
14532
14986
|
async configure(props = {}) {
|
|
14533
14987
|
let resolve;
|
|
14534
14988
|
pending = new Promise((_resolve) => resolve = _resolve);
|
|
14535
|
-
|
|
14989
|
+
const {
|
|
14990
|
+
id: canvasId,
|
|
14991
|
+
primaryCanvas,
|
|
14992
|
+
scheduler: schedulerConfig,
|
|
14536
14993
|
gl: glConfig,
|
|
14537
14994
|
renderer: rendererConfig,
|
|
14538
14995
|
size: propsSize,
|
|
@@ -14540,10 +14997,7 @@ function createRoot(canvas) {
|
|
|
14540
14997
|
events,
|
|
14541
14998
|
onCreated: onCreatedCallback,
|
|
14542
14999
|
shadows = false,
|
|
14543
|
-
linear = false,
|
|
14544
|
-
flat = false,
|
|
14545
15000
|
textureColorSpace = SRGBColorSpace,
|
|
14546
|
-
legacy = false,
|
|
14547
15001
|
orthographic = false,
|
|
14548
15002
|
frameloop = "always",
|
|
14549
15003
|
dpr = [1, 2],
|
|
@@ -14554,9 +15008,11 @@ function createRoot(canvas) {
|
|
|
14554
15008
|
onDragOverMissed,
|
|
14555
15009
|
onDropMissed,
|
|
14556
15010
|
autoUpdateFrustum = true,
|
|
14557
|
-
occlusion = false
|
|
15011
|
+
occlusion = false,
|
|
15012
|
+
_sizeProps,
|
|
15013
|
+
forceEven
|
|
14558
15014
|
} = props;
|
|
14559
|
-
|
|
15015
|
+
const state = store.getState();
|
|
14560
15016
|
const defaultGLProps = {
|
|
14561
15017
|
canvas,
|
|
14562
15018
|
powerPreference: "high-performance",
|
|
@@ -14568,22 +15024,34 @@ function createRoot(canvas) {
|
|
|
14568
15024
|
"WebGPURenderer (renderer prop) is not available in this build. Use @react-three/fiber or @react-three/fiber/webgpu instead."
|
|
14569
15025
|
);
|
|
14570
15026
|
}
|
|
14571
|
-
(state.isLegacy || glConfig || !R3F_BUILD_WEBGPU);
|
|
15027
|
+
const wantsGL = (state.isLegacy || glConfig || !R3F_BUILD_WEBGPU);
|
|
14572
15028
|
if (glConfig && rendererConfig) {
|
|
14573
15029
|
throw new Error("Cannot use both gl and renderer props at the same time");
|
|
14574
15030
|
}
|
|
14575
15031
|
let renderer = state.internal.actualRenderer;
|
|
15032
|
+
if (primaryCanvas && !R3F_BUILD_WEBGPU) {
|
|
15033
|
+
throw new Error(
|
|
15034
|
+
"The `primaryCanvas` prop for multi-canvas rendering is only available with WebGPU. Use @react-three/fiber/webgpu instead."
|
|
15035
|
+
);
|
|
15036
|
+
}
|
|
15037
|
+
if (primaryCanvas && wantsGL) {
|
|
15038
|
+
throw new Error(
|
|
15039
|
+
"The `primaryCanvas` prop for multi-canvas rendering cannot be used with WebGL. Remove the `gl` prop or use WebGPU."
|
|
15040
|
+
);
|
|
15041
|
+
}
|
|
14576
15042
|
if (!state.internal.actualRenderer) {
|
|
14577
15043
|
renderer = await resolveRenderer(glConfig, defaultGLProps, WebGLRenderer);
|
|
14578
15044
|
state.internal.actualRenderer = renderer;
|
|
14579
|
-
state.set({ isLegacy: true, gl: renderer, renderer });
|
|
15045
|
+
state.set({ isLegacy: true, gl: renderer, renderer, primaryStore: store });
|
|
14580
15046
|
}
|
|
14581
15047
|
let raycaster = state.raycaster;
|
|
14582
15048
|
if (!raycaster) state.set({ raycaster: raycaster = new Raycaster() });
|
|
14583
15049
|
const { params, ...options } = raycastOptions || {};
|
|
14584
15050
|
if (!is.equ(options, raycaster, shallowLoose)) applyProps(raycaster, { ...options });
|
|
14585
|
-
if (!is.equ(params, raycaster.params, shallowLoose))
|
|
15051
|
+
if (!is.equ(params, raycaster.params, shallowLoose)) {
|
|
14586
15052
|
applyProps(raycaster, { params: { ...raycaster.params, ...params } });
|
|
15053
|
+
}
|
|
15054
|
+
let tempCamera = state.camera;
|
|
14587
15055
|
if (!state.camera || state.camera === lastCamera && !is.equ(lastCamera, cameraOptions, shallowLoose)) {
|
|
14588
15056
|
lastCamera = cameraOptions;
|
|
14589
15057
|
const isCamera = cameraOptions?.isCamera;
|
|
@@ -14603,6 +15071,7 @@ function createRoot(canvas) {
|
|
|
14603
15071
|
if (!state.camera && !cameraOptions?.rotation) camera.lookAt(0, 0, 0);
|
|
14604
15072
|
}
|
|
14605
15073
|
state.set({ camera });
|
|
15074
|
+
tempCamera = camera;
|
|
14606
15075
|
raycaster.camera = camera;
|
|
14607
15076
|
}
|
|
14608
15077
|
if (!state.scene) {
|
|
@@ -14620,7 +15089,7 @@ function createRoot(canvas) {
|
|
|
14620
15089
|
rootScene: scene,
|
|
14621
15090
|
internal: { ...prev.internal, container: scene }
|
|
14622
15091
|
}));
|
|
14623
|
-
const camera =
|
|
15092
|
+
const camera = tempCamera;
|
|
14624
15093
|
if (camera && !camera.parent) scene.add(camera);
|
|
14625
15094
|
}
|
|
14626
15095
|
if (events && !state.events.handlers) {
|
|
@@ -14634,9 +15103,17 @@ function createRoot(canvas) {
|
|
|
14634
15103
|
wasEnabled = enabled;
|
|
14635
15104
|
});
|
|
14636
15105
|
}
|
|
15106
|
+
if (_sizeProps !== void 0) {
|
|
15107
|
+
state.set({ _sizeProps });
|
|
15108
|
+
}
|
|
15109
|
+
if (forceEven !== void 0 && state.internal.forceEven !== forceEven) {
|
|
15110
|
+
state.set((prev) => ({ internal: { ...prev.internal, forceEven } }));
|
|
15111
|
+
}
|
|
14637
15112
|
const size = computeInitialSize(canvas, propsSize);
|
|
14638
|
-
if (!is.equ(size, state.size, shallowLoose)) {
|
|
15113
|
+
if (!state._sizeImperative && !is.equ(size, state.size, shallowLoose)) {
|
|
15114
|
+
const wasImperative = state._sizeImperative;
|
|
14639
15115
|
state.setSize(size.width, size.height, size.top, size.left);
|
|
15116
|
+
if (!wasImperative) state.set({ _sizeImperative: false });
|
|
14640
15117
|
}
|
|
14641
15118
|
if (dpr !== void 0 && !is.equ(dpr, lastConfiguredProps.dpr, shallowLoose)) {
|
|
14642
15119
|
state.setDpr(dpr);
|
|
@@ -14661,7 +15138,7 @@ function createRoot(canvas) {
|
|
|
14661
15138
|
const handleXRFrame = (timestamp, frame) => {
|
|
14662
15139
|
const state2 = store.getState();
|
|
14663
15140
|
if (state2.frameloop === "never") return;
|
|
14664
|
-
advance(timestamp
|
|
15141
|
+
advance(timestamp);
|
|
14665
15142
|
};
|
|
14666
15143
|
const actualRenderer = state.internal.actualRenderer;
|
|
14667
15144
|
const handleSessionChange = () => {
|
|
@@ -14673,16 +15150,16 @@ function createRoot(canvas) {
|
|
|
14673
15150
|
};
|
|
14674
15151
|
const xr = {
|
|
14675
15152
|
connect() {
|
|
14676
|
-
const { gl, renderer: renderer2
|
|
14677
|
-
const
|
|
14678
|
-
|
|
14679
|
-
|
|
15153
|
+
const { gl, renderer: renderer2 } = store.getState();
|
|
15154
|
+
const xrManager = (renderer2 || gl).xr;
|
|
15155
|
+
xrManager.addEventListener("sessionstart", handleSessionChange);
|
|
15156
|
+
xrManager.addEventListener("sessionend", handleSessionChange);
|
|
14680
15157
|
},
|
|
14681
15158
|
disconnect() {
|
|
14682
|
-
const { gl, renderer: renderer2
|
|
14683
|
-
const
|
|
14684
|
-
|
|
14685
|
-
|
|
15159
|
+
const { gl, renderer: renderer2 } = store.getState();
|
|
15160
|
+
const xrManager = (renderer2 || gl).xr;
|
|
15161
|
+
xrManager.removeEventListener("sessionstart", handleSessionChange);
|
|
15162
|
+
xrManager.removeEventListener("sessionend", handleSessionChange);
|
|
14686
15163
|
}
|
|
14687
15164
|
};
|
|
14688
15165
|
if (typeof renderer.xr?.addEventListener === "function") xr.connect();
|
|
@@ -14706,35 +15183,21 @@ function createRoot(canvas) {
|
|
|
14706
15183
|
} else if (is.obj(shadows)) {
|
|
14707
15184
|
Object.assign(renderer.shadowMap, shadows);
|
|
14708
15185
|
}
|
|
14709
|
-
if (oldEnabled !== renderer.shadowMap.enabled || oldType !== renderer.shadowMap.type)
|
|
15186
|
+
if (oldEnabled !== renderer.shadowMap.enabled || oldType !== renderer.shadowMap.type) {
|
|
14710
15187
|
renderer.shadowMap.needsUpdate = true;
|
|
14711
|
-
}
|
|
14712
|
-
{
|
|
14713
|
-
const legacyChanged = legacy !== lastConfiguredProps.legacy;
|
|
14714
|
-
const linearChanged = linear !== lastConfiguredProps.linear;
|
|
14715
|
-
const flatChanged = flat !== lastConfiguredProps.flat;
|
|
14716
|
-
if (legacyChanged) {
|
|
14717
|
-
ColorManagement.enabled = !legacy;
|
|
14718
|
-
lastConfiguredProps.legacy = legacy;
|
|
14719
15188
|
}
|
|
14720
|
-
|
|
14721
|
-
|
|
14722
|
-
|
|
14723
|
-
|
|
14724
|
-
if (!configured || flatChanged) {
|
|
14725
|
-
renderer.toneMapping = flat ? NoToneMapping : ACESFilmicToneMapping;
|
|
14726
|
-
lastConfiguredProps.flat = flat;
|
|
14727
|
-
}
|
|
14728
|
-
if (legacyChanged && state.legacy !== legacy) state.set(() => ({ legacy }));
|
|
14729
|
-
if (linearChanged && state.linear !== linear) state.set(() => ({ linear }));
|
|
14730
|
-
if (flatChanged && state.flat !== flat) state.set(() => ({ flat }));
|
|
15189
|
+
}
|
|
15190
|
+
if (!configured) {
|
|
15191
|
+
renderer.outputColorSpace = SRGBColorSpace;
|
|
15192
|
+
renderer.toneMapping = ACESFilmicToneMapping;
|
|
14731
15193
|
}
|
|
14732
15194
|
if (textureColorSpace !== lastConfiguredProps.textureColorSpace) {
|
|
14733
15195
|
if (state.textureColorSpace !== textureColorSpace) state.set(() => ({ textureColorSpace }));
|
|
14734
15196
|
lastConfiguredProps.textureColorSpace = textureColorSpace;
|
|
14735
15197
|
}
|
|
14736
|
-
if (glConfig && !is.fun(glConfig) && !isRenderer(glConfig) && !is.equ(glConfig, renderer, shallowLoose))
|
|
15198
|
+
if (glConfig && !is.fun(glConfig) && !isRenderer(glConfig) && !is.equ(glConfig, renderer, shallowLoose)) {
|
|
14737
15199
|
applyProps(renderer, glConfig);
|
|
15200
|
+
}
|
|
14738
15201
|
if (rendererConfig && !is.fun(rendererConfig) && !isRenderer(rendererConfig) && state.renderer) {
|
|
14739
15202
|
const currentRenderer = state.renderer;
|
|
14740
15203
|
if (!is.equ(rendererConfig, currentRenderer, shallowLoose)) {
|
|
@@ -14744,11 +15207,26 @@ function createRoot(canvas) {
|
|
|
14744
15207
|
const scheduler = getScheduler();
|
|
14745
15208
|
const rootId = state.internal.rootId;
|
|
14746
15209
|
if (!rootId) {
|
|
14747
|
-
const newRootId = scheduler.generateRootId();
|
|
15210
|
+
const newRootId = canvasId || scheduler.generateRootId();
|
|
14748
15211
|
const unregisterRoot = scheduler.registerRoot(newRootId, {
|
|
14749
15212
|
getState: () => store.getState(),
|
|
14750
15213
|
onError: (err) => store.getState().setError(err)
|
|
14751
15214
|
});
|
|
15215
|
+
const unregisterCanvasTarget = scheduler.register(
|
|
15216
|
+
() => {
|
|
15217
|
+
const state2 = store.getState();
|
|
15218
|
+
if (state2.internal.isMultiCanvas && state2.internal.canvasTarget) {
|
|
15219
|
+
const renderer2 = state2.internal.actualRenderer;
|
|
15220
|
+
renderer2.setCanvasTarget(state2.internal.canvasTarget);
|
|
15221
|
+
}
|
|
15222
|
+
},
|
|
15223
|
+
{
|
|
15224
|
+
id: `${newRootId}_canvasTarget`,
|
|
15225
|
+
rootId: newRootId,
|
|
15226
|
+
phase: "start",
|
|
15227
|
+
system: true
|
|
15228
|
+
}
|
|
15229
|
+
);
|
|
14752
15230
|
const unregisterFrustum = scheduler.register(
|
|
14753
15231
|
() => {
|
|
14754
15232
|
const state2 = store.getState();
|
|
@@ -14790,11 +15268,15 @@ function createRoot(canvas) {
|
|
|
14790
15268
|
}
|
|
14791
15269
|
},
|
|
14792
15270
|
{
|
|
14793
|
-
|
|
15271
|
+
// Use canvas ID directly as job ID if available, otherwise use generated rootId
|
|
15272
|
+
id: canvasId || `${newRootId}_render`,
|
|
14794
15273
|
rootId: newRootId,
|
|
14795
15274
|
phase: "render",
|
|
14796
|
-
system: true
|
|
15275
|
+
system: true,
|
|
14797
15276
|
// Internal flag: this is a system job, not user-controlled
|
|
15277
|
+
// Apply scheduler config for render ordering and rate limiting
|
|
15278
|
+
...schedulerConfig?.after && { after: schedulerConfig.after },
|
|
15279
|
+
...schedulerConfig?.fps && { fps: schedulerConfig.fps }
|
|
14798
15280
|
}
|
|
14799
15281
|
);
|
|
14800
15282
|
state.set((state2) => ({
|
|
@@ -14803,6 +15285,7 @@ function createRoot(canvas) {
|
|
|
14803
15285
|
rootId: newRootId,
|
|
14804
15286
|
unregisterRoot: () => {
|
|
14805
15287
|
unregisterRoot();
|
|
15288
|
+
unregisterCanvasTarget();
|
|
14806
15289
|
unregisterFrustum();
|
|
14807
15290
|
unregisterVisibility();
|
|
14808
15291
|
unregisterRender();
|
|
@@ -14861,15 +15344,24 @@ function unmountComponentAtNode(canvas, callback) {
|
|
|
14861
15344
|
const renderer = state.internal.actualRenderer;
|
|
14862
15345
|
const unregisterRoot = state.internal.unregisterRoot;
|
|
14863
15346
|
if (unregisterRoot) unregisterRoot();
|
|
15347
|
+
const unregisterPrimary = state.internal.unregisterPrimary;
|
|
15348
|
+
if (unregisterPrimary) unregisterPrimary();
|
|
15349
|
+
const canvasTarget = state.internal.canvasTarget;
|
|
15350
|
+
if (canvasTarget?.dispose) canvasTarget.dispose();
|
|
14864
15351
|
state.events.disconnect?.();
|
|
14865
15352
|
cleanupHelperGroup(root.store);
|
|
14866
|
-
renderer
|
|
14867
|
-
|
|
14868
|
-
|
|
15353
|
+
if (state.isLegacy && renderer) {
|
|
15354
|
+
;
|
|
15355
|
+
renderer.renderLists?.dispose?.();
|
|
15356
|
+
renderer.forceContextLoss?.();
|
|
15357
|
+
}
|
|
15358
|
+
if (!state.internal.isSecondary) {
|
|
15359
|
+
if (renderer?.xr) state.xr.disconnect();
|
|
15360
|
+
}
|
|
14869
15361
|
dispose(state.scene);
|
|
14870
15362
|
_roots.delete(canvas);
|
|
14871
15363
|
if (callback) callback(canvas);
|
|
14872
|
-
} catch
|
|
15364
|
+
} catch {
|
|
14873
15365
|
}
|
|
14874
15366
|
}, 500);
|
|
14875
15367
|
}
|
|
@@ -14877,36 +15369,34 @@ function unmountComponentAtNode(canvas, callback) {
|
|
|
14877
15369
|
}
|
|
14878
15370
|
}
|
|
14879
15371
|
function createPortal(children, container, state) {
|
|
14880
|
-
return /* @__PURE__ */ jsx(
|
|
15372
|
+
return /* @__PURE__ */ jsx(Portal, { children, container, state });
|
|
14881
15373
|
}
|
|
14882
|
-
function
|
|
15374
|
+
function Portal({ children, container, state }) {
|
|
14883
15375
|
const isRef = useCallback((obj) => obj && "current" in obj, []);
|
|
14884
|
-
const [resolvedContainer,
|
|
15376
|
+
const [resolvedContainer, _setResolvedContainer] = useState(() => {
|
|
14885
15377
|
if (isRef(container)) return container.current ?? null;
|
|
14886
15378
|
return container;
|
|
14887
15379
|
});
|
|
15380
|
+
const setResolvedContainer = useCallback(
|
|
15381
|
+
(newContainer) => {
|
|
15382
|
+
if (!newContainer || newContainer === resolvedContainer) return;
|
|
15383
|
+
_setResolvedContainer(isRef(newContainer) ? newContainer.current : newContainer);
|
|
15384
|
+
},
|
|
15385
|
+
[resolvedContainer, _setResolvedContainer, isRef]
|
|
15386
|
+
);
|
|
14888
15387
|
useMemo(() => {
|
|
14889
|
-
if (isRef(container)) {
|
|
14890
|
-
|
|
14891
|
-
|
|
14892
|
-
|
|
14893
|
-
const updated = container.current;
|
|
14894
|
-
if (updated && updated !== resolvedContainer) {
|
|
14895
|
-
setResolvedContainer(updated);
|
|
14896
|
-
}
|
|
14897
|
-
});
|
|
14898
|
-
} else if (current !== resolvedContainer) {
|
|
14899
|
-
setResolvedContainer(current);
|
|
14900
|
-
}
|
|
14901
|
-
} else if (container !== resolvedContainer) {
|
|
14902
|
-
setResolvedContainer(container);
|
|
15388
|
+
if (isRef(container) && !container.current) {
|
|
15389
|
+
return queueMicrotask(() => {
|
|
15390
|
+
setResolvedContainer(container.current);
|
|
15391
|
+
});
|
|
14903
15392
|
}
|
|
14904
|
-
|
|
15393
|
+
setResolvedContainer(container);
|
|
15394
|
+
}, [container, isRef, setResolvedContainer]);
|
|
14905
15395
|
if (!resolvedContainer) return /* @__PURE__ */ jsx(Fragment, {});
|
|
14906
15396
|
const portalKey = resolvedContainer.uuid ?? `portal-${resolvedContainer.id ?? "unknown"}`;
|
|
14907
|
-
return /* @__PURE__ */ jsx(
|
|
15397
|
+
return /* @__PURE__ */ jsx(PortalInner, { children, container: resolvedContainer, state }, portalKey);
|
|
14908
15398
|
}
|
|
14909
|
-
function
|
|
15399
|
+
function PortalInner({ state = {}, children, container }) {
|
|
14910
15400
|
const { events, size, injectScene = true, ...rest } = state;
|
|
14911
15401
|
const previousRoot = useStore();
|
|
14912
15402
|
const [raycaster] = useState(() => new Raycaster());
|
|
@@ -14927,11 +15417,12 @@ function Portal({ state = {}, children, container }) {
|
|
|
14927
15417
|
};
|
|
14928
15418
|
}, [portalScene, container, injectScene]);
|
|
14929
15419
|
const inject = useMutableCallback((rootState, injectState) => {
|
|
15420
|
+
const resolvedSize = { ...rootState.size, ...injectState.size, ...size };
|
|
14930
15421
|
let viewport = void 0;
|
|
14931
|
-
if (injectState.camera && size) {
|
|
15422
|
+
if (injectState.camera && (size || injectState.size)) {
|
|
14932
15423
|
const camera = injectState.camera;
|
|
14933
|
-
viewport = rootState.viewport.getCurrentViewport(camera, new Vector3(),
|
|
14934
|
-
if (camera !== rootState.camera) updateCamera(camera,
|
|
15424
|
+
viewport = rootState.viewport.getCurrentViewport(camera, new Vector3(), resolvedSize);
|
|
15425
|
+
if (camera !== rootState.camera) updateCamera(camera, resolvedSize);
|
|
14935
15426
|
}
|
|
14936
15427
|
return {
|
|
14937
15428
|
// The intersect consists of the previous root state
|
|
@@ -14948,7 +15439,7 @@ function Portal({ state = {}, children, container }) {
|
|
|
14948
15439
|
previousRoot,
|
|
14949
15440
|
// Events, size and viewport can be overridden by the inject layer
|
|
14950
15441
|
events: { ...rootState.events, ...injectState.events, ...events },
|
|
14951
|
-
size:
|
|
15442
|
+
size: resolvedSize,
|
|
14952
15443
|
viewport: { ...rootState.viewport, ...viewport },
|
|
14953
15444
|
// Layers are allowed to override events
|
|
14954
15445
|
setEvents: (events2) => injectState.set((state2) => ({ ...state2, events: { ...state2.events, ...events2 } })),
|
|
@@ -14982,15 +15473,13 @@ function CanvasImpl({
|
|
|
14982
15473
|
fallback,
|
|
14983
15474
|
resize,
|
|
14984
15475
|
style,
|
|
15476
|
+
id,
|
|
14985
15477
|
gl,
|
|
14986
|
-
renderer,
|
|
15478
|
+
renderer: rendererProp,
|
|
14987
15479
|
events = createPointerEvents,
|
|
14988
15480
|
eventSource,
|
|
14989
15481
|
eventPrefix,
|
|
14990
15482
|
shadows,
|
|
14991
|
-
linear,
|
|
14992
|
-
flat,
|
|
14993
|
-
legacy,
|
|
14994
15483
|
orthographic,
|
|
14995
15484
|
frameloop,
|
|
14996
15485
|
dpr,
|
|
@@ -15002,10 +15491,46 @@ function CanvasImpl({
|
|
|
15002
15491
|
onDragOverMissed,
|
|
15003
15492
|
onDropMissed,
|
|
15004
15493
|
onCreated,
|
|
15494
|
+
hmr,
|
|
15495
|
+
width,
|
|
15496
|
+
height,
|
|
15497
|
+
background,
|
|
15498
|
+
forceEven,
|
|
15005
15499
|
...props
|
|
15006
15500
|
}) {
|
|
15501
|
+
const { primaryCanvas, scheduler, ...rendererConfig } = typeof rendererProp === "object" && rendererProp !== null && !("render" in rendererProp) && ("primaryCanvas" in rendererProp || "scheduler" in rendererProp) ? rendererProp : { primaryCanvas: void 0, scheduler: void 0 };
|
|
15502
|
+
const renderer = Object.keys(rendererConfig).length > 0 ? rendererConfig : rendererProp;
|
|
15007
15503
|
React.useMemo(() => extend(THREE), []);
|
|
15008
15504
|
const Bridge = useBridge();
|
|
15505
|
+
const backgroundProps = React.useMemo(() => {
|
|
15506
|
+
if (!background) return null;
|
|
15507
|
+
if (typeof background === "object" && !background.isColor) {
|
|
15508
|
+
const { backgroundMap, envMap, files, preset, ...rest } = background;
|
|
15509
|
+
return {
|
|
15510
|
+
...rest,
|
|
15511
|
+
preset,
|
|
15512
|
+
files: envMap || files,
|
|
15513
|
+
backgroundFiles: backgroundMap,
|
|
15514
|
+
background: true
|
|
15515
|
+
};
|
|
15516
|
+
}
|
|
15517
|
+
if (typeof background === "number") {
|
|
15518
|
+
return { color: background, background: true };
|
|
15519
|
+
}
|
|
15520
|
+
if (typeof background === "string") {
|
|
15521
|
+
if (background in presetsObj) {
|
|
15522
|
+
return { preset: background, background: true };
|
|
15523
|
+
}
|
|
15524
|
+
if (/^(https?:\/\/|\/|\.\/|\.\.\/)|\\.(hdr|exr|jpg|jpeg|png|webp|gif)$/i.test(background)) {
|
|
15525
|
+
return { files: background, background: true };
|
|
15526
|
+
}
|
|
15527
|
+
return { color: background, background: true };
|
|
15528
|
+
}
|
|
15529
|
+
if (background.isColor) {
|
|
15530
|
+
return { color: background, background: true };
|
|
15531
|
+
}
|
|
15532
|
+
return null;
|
|
15533
|
+
}, [background]);
|
|
15009
15534
|
const hasInitialSizeRef = React.useRef(false);
|
|
15010
15535
|
const measureConfig = React.useMemo(() => {
|
|
15011
15536
|
if (!hasInitialSizeRef.current) {
|
|
@@ -15022,7 +15547,21 @@ function CanvasImpl({
|
|
|
15022
15547
|
};
|
|
15023
15548
|
}, [resize, hasInitialSizeRef.current]);
|
|
15024
15549
|
const [containerRef, containerRect] = useMeasure(measureConfig);
|
|
15025
|
-
|
|
15550
|
+
const effectiveSize = React.useMemo(() => {
|
|
15551
|
+
let w = width ?? containerRect.width;
|
|
15552
|
+
let h = height ?? containerRect.height;
|
|
15553
|
+
if (forceEven) {
|
|
15554
|
+
w = Math.ceil(w / 2) * 2;
|
|
15555
|
+
h = Math.ceil(h / 2) * 2;
|
|
15556
|
+
}
|
|
15557
|
+
return {
|
|
15558
|
+
width: w,
|
|
15559
|
+
height: h,
|
|
15560
|
+
top: containerRect.top,
|
|
15561
|
+
left: containerRect.left
|
|
15562
|
+
};
|
|
15563
|
+
}, [width, height, containerRect, forceEven]);
|
|
15564
|
+
if (!hasInitialSizeRef.current && effectiveSize.width > 0 && effectiveSize.height > 0) {
|
|
15026
15565
|
hasInitialSizeRef.current = true;
|
|
15027
15566
|
}
|
|
15028
15567
|
const canvasRef = React.useRef(null);
|
|
@@ -15041,7 +15580,7 @@ function CanvasImpl({
|
|
|
15041
15580
|
useIsomorphicLayoutEffect(() => {
|
|
15042
15581
|
effectActiveRef.current = true;
|
|
15043
15582
|
const canvas = canvasRef.current;
|
|
15044
|
-
if (
|
|
15583
|
+
if (effectiveSize.width > 0 && effectiveSize.height > 0 && canvas) {
|
|
15045
15584
|
if (!root.current) {
|
|
15046
15585
|
root.current = createRoot(canvas);
|
|
15047
15586
|
notifyAlpha({
|
|
@@ -15061,21 +15600,24 @@ function CanvasImpl({
|
|
|
15061
15600
|
async function run() {
|
|
15062
15601
|
if (!effectActiveRef.current || !root.current) return;
|
|
15063
15602
|
await root.current.configure({
|
|
15603
|
+
id,
|
|
15604
|
+
primaryCanvas,
|
|
15605
|
+
scheduler,
|
|
15064
15606
|
gl,
|
|
15065
15607
|
renderer,
|
|
15066
15608
|
scene,
|
|
15067
15609
|
events,
|
|
15068
15610
|
shadows,
|
|
15069
|
-
linear,
|
|
15070
|
-
flat,
|
|
15071
|
-
legacy,
|
|
15072
15611
|
orthographic,
|
|
15073
15612
|
frameloop,
|
|
15074
15613
|
dpr,
|
|
15075
15614
|
performance,
|
|
15076
15615
|
raycaster,
|
|
15077
15616
|
camera,
|
|
15078
|
-
size:
|
|
15617
|
+
size: effectiveSize,
|
|
15618
|
+
// Store size props for reset functionality
|
|
15619
|
+
_sizeProps: width !== void 0 || height !== void 0 ? { width, height } : null,
|
|
15620
|
+
forceEven,
|
|
15079
15621
|
// Pass mutable reference to onPointerMissed so it's free to update
|
|
15080
15622
|
onPointerMissed: (...args) => handlePointerMissed.current?.(...args),
|
|
15081
15623
|
onDragOverMissed: (...args) => handleDragOverMissed.current?.(...args),
|
|
@@ -15099,7 +15641,10 @@ function CanvasImpl({
|
|
|
15099
15641
|
});
|
|
15100
15642
|
if (!effectActiveRef.current || !root.current) return;
|
|
15101
15643
|
root.current.render(
|
|
15102
|
-
/* @__PURE__ */ jsx(Bridge, { children: /* @__PURE__ */ jsx(ErrorBoundary, { set: setError, children: /* @__PURE__ */
|
|
15644
|
+
/* @__PURE__ */ jsx(Bridge, { children: /* @__PURE__ */ jsx(ErrorBoundary, { set: setError, children: /* @__PURE__ */ jsxs(React.Suspense, { fallback: /* @__PURE__ */ jsx(Block, { set: setBlock }), children: [
|
|
15645
|
+
backgroundProps && /* @__PURE__ */ jsx(Environment, { ...backgroundProps }),
|
|
15646
|
+
children ?? null
|
|
15647
|
+
] }) }) })
|
|
15103
15648
|
);
|
|
15104
15649
|
}
|
|
15105
15650
|
run();
|
|
@@ -15121,6 +15666,35 @@ function CanvasImpl({
|
|
|
15121
15666
|
};
|
|
15122
15667
|
}
|
|
15123
15668
|
}, []);
|
|
15669
|
+
React.useEffect(() => {
|
|
15670
|
+
if (hmr === false) return;
|
|
15671
|
+
const canvas = canvasRef.current;
|
|
15672
|
+
if (!canvas) return;
|
|
15673
|
+
const handleHMR = () => {
|
|
15674
|
+
queueMicrotask(() => {
|
|
15675
|
+
const rootEntry = _roots.get(canvas);
|
|
15676
|
+
if (rootEntry?.store) {
|
|
15677
|
+
rootEntry.store.setState((state) => ({
|
|
15678
|
+
nodes: {},
|
|
15679
|
+
uniforms: {},
|
|
15680
|
+
_hmrVersion: state._hmrVersion + 1
|
|
15681
|
+
}));
|
|
15682
|
+
}
|
|
15683
|
+
});
|
|
15684
|
+
};
|
|
15685
|
+
if (typeof import.meta !== "undefined" && import.meta.hot) {
|
|
15686
|
+
const hot = import.meta.hot;
|
|
15687
|
+
hot.on("vite:afterUpdate", handleHMR);
|
|
15688
|
+
return () => hot.dispose?.(() => {
|
|
15689
|
+
});
|
|
15690
|
+
}
|
|
15691
|
+
if (typeof module !== "undefined" && module.hot) {
|
|
15692
|
+
const hot = module.hot;
|
|
15693
|
+
hot.addStatusHandler((status) => {
|
|
15694
|
+
if (status === "idle") handleHMR();
|
|
15695
|
+
});
|
|
15696
|
+
}
|
|
15697
|
+
}, [hmr]);
|
|
15124
15698
|
const pointerEvents = eventSource ? "none" : "auto";
|
|
15125
15699
|
return /* @__PURE__ */ jsx(
|
|
15126
15700
|
"div",
|
|
@@ -15135,7 +15709,7 @@ function CanvasImpl({
|
|
|
15135
15709
|
...style
|
|
15136
15710
|
},
|
|
15137
15711
|
...props,
|
|
15138
|
-
children: /* @__PURE__ */ jsx("div", { ref: containerRef, className: "r3f-canvas-container", style: { width: "100%", height: "100%" }, children: /* @__PURE__ */ jsx("canvas", { ref: canvasRef, className: "r3f-canvas", style: { display: "block" }, children: fallback }) })
|
|
15712
|
+
children: /* @__PURE__ */ jsx("div", { ref: containerRef, className: "r3f-canvas-container", style: { width: "100%", height: "100%" }, children: /* @__PURE__ */ jsx("canvas", { ref: canvasRef, id, className: "r3f-canvas", style: { display: "block" }, children: fallback }) })
|
|
15139
15713
|
}
|
|
15140
15714
|
);
|
|
15141
15715
|
}
|
|
@@ -15145,4 +15719,4 @@ function Canvas(props) {
|
|
|
15145
15719
|
|
|
15146
15720
|
extend(THREE);
|
|
15147
15721
|
|
|
15148
|
-
export { Block, Canvas, ErrorBoundary, IsObject, R3F_BUILD_LEGACY, R3F_BUILD_WEBGPU, REACT_INTERNAL_PROPS, RESERVED_PROPS, Scheduler, Texture, _roots, act, addAfterEffect, addEffect, addTail, advance, applyProps, attach, buildGraph, calculateDpr, context, createEvents, createPointerEvents, createPortal, createRoot, createStore, detach, diffProps, dispose, createPointerEvents as events, extend, findInitialRoot, flushSync, getInstanceProps, getRootState, getScheduler, getUuidPrefix, hasConstructor, invalidate, invalidateInstance, is, isColorRepresentation, isCopyable, isObject3D, isOrthographicCamera, isRef, isRenderer, isTexture, isVectorLike, prepare, reconciler, removeInteractivity, resolve, unmountComponentAtNode, updateCamera, updateFrustum, useBridge, useFrame, useGraph, useInstanceHandle, useIsomorphicLayoutEffect, useLoader, useMutableCallback, useRenderTarget, useStore, useTexture, useTextures, useThree };
|
|
15722
|
+
export { Block, Canvas, Environment, EnvironmentCube, EnvironmentMap, EnvironmentPortal, ErrorBoundary, FROM_REF, IsObject, ONCE, Portal, R3F_BUILD_LEGACY, R3F_BUILD_WEBGPU, REACT_INTERNAL_PROPS, RESERVED_PROPS, Scheduler, Texture, _roots, act, addAfterEffect, addEffect, addTail, advance, applyProps, attach, buildGraph, calculateDpr, context, createEvents, createPointerEvents, createPortal, createRoot, createStore, detach, diffProps, dispose, createPointerEvents as events, extend, findInitialRoot, flushSync, fromRef, getInstanceProps, getPrimary, getPrimaryIds, getRootState, getScheduler, getUuidPrefix, hasConstructor, hasPrimary, invalidate, invalidateInstance, is, isColorRepresentation, isCopyable, isFromRef, isObject3D, isOnce, isOrthographicCamera, isRef, isRenderer, isTexture, isVectorLike, once, prepare, presetsObj, reconciler, registerPrimary, removeInteractivity, resolve, unmountComponentAtNode, unregisterPrimary, updateCamera, updateFrustum, useBridge, useEnvironment, useFrame, useGraph, useInstanceHandle, useIsomorphicLayoutEffect, useLoader, useMutableCallback, useRenderTarget, useStore, useTexture, useTextures, useThree, waitForPrimary };
|