@react-three/fiber 10.0.0-alpha.1 → 10.0.0-canary.2b511a5
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/index.mjs
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
import * as webgpu from 'three/webgpu';
|
|
2
|
-
import { RenderTarget, Frustum, Matrix4, Group, BoxGeometry, MeshBasicNodeMaterial, Mesh, Node, NodeUpdateType, Layers, RGBAFormat, UnsignedByteType, Vector3, Vector2, TextureLoader, Texture as Texture$1,
|
|
2
|
+
import { RenderTarget, 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, CanvasTarget, Raycaster, OrthographicCamera, PerspectiveCamera, PCFSoftShadowMap, VSMShadowMap, PCFShadowMap, BasicShadowMap, ACESFilmicToneMapping, WebGPURenderer } from 'three/webgpu';
|
|
3
3
|
import { WebGLRenderTarget, WebGLRenderer } from 'three';
|
|
4
4
|
import { Inspector } from 'three/addons/inspector/Inspector.js';
|
|
5
|
-
import { jsx, Fragment } from 'react/jsx-runtime';
|
|
5
|
+
import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
|
|
6
6
|
import * as React from 'react';
|
|
7
|
-
import React__default, {
|
|
7
|
+
import React__default, { useLayoutEffect, useRef, useMemo, useEffect, useContext, useImperativeHandle, useCallback, useState } from 'react';
|
|
8
8
|
import useMeasure from 'react-use-measure';
|
|
9
9
|
import { useFiber, useContextBridge, traverseFiber, FiberProvider } from 'its-fine';
|
|
10
|
+
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';
|
|
11
|
+
import { GroundedSkybox } from 'three/examples/jsm/objects/GroundedSkybox.js';
|
|
12
|
+
import { HDRLoader } from 'three/examples/jsm/loaders/HDRLoader.js';
|
|
13
|
+
import { EXRLoader } from 'three/examples/jsm/loaders/EXRLoader.js';
|
|
14
|
+
import { UltraHDRLoader } from 'three/examples/jsm/loaders/UltraHDRLoader.js';
|
|
15
|
+
import { GainMapLoader } from '@monogrid/gainmap-js';
|
|
10
16
|
import Tb, { unstable_scheduleCallback, unstable_IdlePriority } from 'scheduler';
|
|
11
17
|
import { createWithEqualityFn } from 'zustand/traditional';
|
|
12
18
|
import { suspend, preload, clear } from 'suspend-react';
|
|
@@ -36,6 +42,374 @@ const THREE = /*#__PURE__*/_mergeNamespaces({
|
|
|
36
42
|
WebGLRenderer: WebGLRenderer
|
|
37
43
|
}, [webgpu]);
|
|
38
44
|
|
|
45
|
+
const primaryRegistry = /* @__PURE__ */ new Map();
|
|
46
|
+
const pendingSubscribers = /* @__PURE__ */ new Map();
|
|
47
|
+
function registerPrimary(id, renderer, store) {
|
|
48
|
+
if (primaryRegistry.has(id)) {
|
|
49
|
+
console.warn(`Canvas with id="${id}" already registered. Overwriting.`);
|
|
50
|
+
}
|
|
51
|
+
const entry = { renderer, store };
|
|
52
|
+
primaryRegistry.set(id, entry);
|
|
53
|
+
const subscribers = pendingSubscribers.get(id);
|
|
54
|
+
if (subscribers) {
|
|
55
|
+
subscribers.forEach((callback) => callback(entry));
|
|
56
|
+
pendingSubscribers.delete(id);
|
|
57
|
+
}
|
|
58
|
+
return () => {
|
|
59
|
+
const currentEntry = primaryRegistry.get(id);
|
|
60
|
+
if (currentEntry?.renderer === renderer) {
|
|
61
|
+
primaryRegistry.delete(id);
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
function getPrimary(id) {
|
|
66
|
+
return primaryRegistry.get(id);
|
|
67
|
+
}
|
|
68
|
+
function waitForPrimary(id, timeout = 5e3) {
|
|
69
|
+
const existing = primaryRegistry.get(id);
|
|
70
|
+
if (existing) {
|
|
71
|
+
return Promise.resolve(existing);
|
|
72
|
+
}
|
|
73
|
+
return new Promise((resolve, reject) => {
|
|
74
|
+
const timeoutId = setTimeout(() => {
|
|
75
|
+
const subscribers = pendingSubscribers.get(id);
|
|
76
|
+
if (subscribers) {
|
|
77
|
+
const index = subscribers.indexOf(callback);
|
|
78
|
+
if (index !== -1) subscribers.splice(index, 1);
|
|
79
|
+
if (subscribers.length === 0) pendingSubscribers.delete(id);
|
|
80
|
+
}
|
|
81
|
+
reject(new Error(`Timeout waiting for canvas with id="${id}". Make sure a <Canvas id="${id}"> is mounted.`));
|
|
82
|
+
}, timeout);
|
|
83
|
+
const callback = (entry) => {
|
|
84
|
+
clearTimeout(timeoutId);
|
|
85
|
+
resolve(entry);
|
|
86
|
+
};
|
|
87
|
+
if (!pendingSubscribers.has(id)) {
|
|
88
|
+
pendingSubscribers.set(id, []);
|
|
89
|
+
}
|
|
90
|
+
pendingSubscribers.get(id).push(callback);
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
function hasPrimary(id) {
|
|
94
|
+
return primaryRegistry.has(id);
|
|
95
|
+
}
|
|
96
|
+
function unregisterPrimary(id) {
|
|
97
|
+
primaryRegistry.delete(id);
|
|
98
|
+
}
|
|
99
|
+
function getPrimaryIds() {
|
|
100
|
+
return Array.from(primaryRegistry.keys());
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const presetsObj = {
|
|
104
|
+
apartment: "lebombo_1k.hdr",
|
|
105
|
+
city: "potsdamer_platz_1k.hdr",
|
|
106
|
+
dawn: "kiara_1_dawn_1k.hdr",
|
|
107
|
+
forest: "forest_slope_1k.hdr",
|
|
108
|
+
lobby: "st_fagans_interior_1k.hdr",
|
|
109
|
+
night: "dikhololo_night_1k.hdr",
|
|
110
|
+
park: "rooitou_park_1k.hdr",
|
|
111
|
+
studio: "studio_small_03_1k.hdr",
|
|
112
|
+
sunset: "venice_sunset_1k.hdr",
|
|
113
|
+
warehouse: "empty_warehouse_01_1k.hdr"
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
const CUBEMAP_ROOT = "https://raw.githack.com/pmndrs/drei-assets/456060a26bbeb8fdf79326f224b6d99b8bcce736/hdri/";
|
|
117
|
+
const isArray = (arr) => Array.isArray(arr);
|
|
118
|
+
const defaultFiles = ["/px.png", "/nx.png", "/py.png", "/ny.png", "/pz.png", "/nz.png"];
|
|
119
|
+
function useEnvironment({
|
|
120
|
+
files = defaultFiles,
|
|
121
|
+
path = "",
|
|
122
|
+
preset = void 0,
|
|
123
|
+
colorSpace = void 0,
|
|
124
|
+
extensions
|
|
125
|
+
} = {}) {
|
|
126
|
+
if (preset) {
|
|
127
|
+
validatePreset(preset);
|
|
128
|
+
files = presetsObj[preset];
|
|
129
|
+
path = CUBEMAP_ROOT;
|
|
130
|
+
}
|
|
131
|
+
const multiFile = isArray(files);
|
|
132
|
+
const { extension, isCubemap } = getExtension(files);
|
|
133
|
+
const loader = getLoader$1(extension);
|
|
134
|
+
if (!loader) throw new Error("useEnvironment: Unrecognized file extension: " + files);
|
|
135
|
+
const renderer = useThree$1((state) => state.renderer);
|
|
136
|
+
useLayoutEffect(() => {
|
|
137
|
+
if (extension !== "webp" && extension !== "jpg" && extension !== "jpeg") return;
|
|
138
|
+
function clearGainmapTexture() {
|
|
139
|
+
useLoader$1.clear(loader, multiFile ? [files] : files);
|
|
140
|
+
}
|
|
141
|
+
renderer.domElement.addEventListener("webglcontextlost", clearGainmapTexture, { once: true });
|
|
142
|
+
}, [files, renderer.domElement]);
|
|
143
|
+
const loaderResult = useLoader$1(
|
|
144
|
+
loader,
|
|
145
|
+
multiFile ? [files] : files,
|
|
146
|
+
(loader2) => {
|
|
147
|
+
if (extension === "webp" || extension === "jpg" || extension === "jpeg") {
|
|
148
|
+
loader2.setRenderer?.(renderer);
|
|
149
|
+
}
|
|
150
|
+
loader2.setPath?.(path);
|
|
151
|
+
if (extensions) extensions(loader2);
|
|
152
|
+
}
|
|
153
|
+
);
|
|
154
|
+
let texture = multiFile ? (
|
|
155
|
+
// @ts-ignore
|
|
156
|
+
loaderResult[0]
|
|
157
|
+
) : loaderResult;
|
|
158
|
+
if (extension === "jpg" || extension === "jpeg" || extension === "webp") {
|
|
159
|
+
texture = texture.renderTarget?.texture;
|
|
160
|
+
}
|
|
161
|
+
texture.mapping = isCubemap ? CubeReflectionMapping : EquirectangularReflectionMapping;
|
|
162
|
+
texture.colorSpace = colorSpace ?? (isCubemap ? "srgb" : "srgb-linear");
|
|
163
|
+
return texture;
|
|
164
|
+
}
|
|
165
|
+
const preloadDefaultOptions = {
|
|
166
|
+
files: defaultFiles,
|
|
167
|
+
path: "",
|
|
168
|
+
preset: void 0,
|
|
169
|
+
extensions: void 0
|
|
170
|
+
};
|
|
171
|
+
useEnvironment.preload = (preloadOptions) => {
|
|
172
|
+
const options = { ...preloadDefaultOptions, ...preloadOptions };
|
|
173
|
+
let { files, path = "" } = options;
|
|
174
|
+
const { preset, extensions } = options;
|
|
175
|
+
if (preset) {
|
|
176
|
+
validatePreset(preset);
|
|
177
|
+
files = presetsObj[preset];
|
|
178
|
+
path = CUBEMAP_ROOT;
|
|
179
|
+
}
|
|
180
|
+
const { extension } = getExtension(files);
|
|
181
|
+
if (extension === "webp" || extension === "jpg" || extension === "jpeg") {
|
|
182
|
+
throw new Error("useEnvironment: Preloading gainmaps is not supported");
|
|
183
|
+
}
|
|
184
|
+
const loader = getLoader$1(extension);
|
|
185
|
+
if (!loader) throw new Error("useEnvironment: Unrecognized file extension: " + files);
|
|
186
|
+
useLoader$1.preload(loader, isArray(files) ? [files] : files, (loader2) => {
|
|
187
|
+
loader2.setPath?.(path);
|
|
188
|
+
if (extensions) extensions(loader2);
|
|
189
|
+
});
|
|
190
|
+
};
|
|
191
|
+
const clearDefaultOptins = {
|
|
192
|
+
files: defaultFiles,
|
|
193
|
+
preset: void 0
|
|
194
|
+
};
|
|
195
|
+
useEnvironment.clear = (clearOptions) => {
|
|
196
|
+
const options = { ...clearDefaultOptins, ...clearOptions };
|
|
197
|
+
let { files } = options;
|
|
198
|
+
const { preset } = options;
|
|
199
|
+
if (preset) {
|
|
200
|
+
validatePreset(preset);
|
|
201
|
+
files = presetsObj[preset];
|
|
202
|
+
}
|
|
203
|
+
const { extension } = getExtension(files);
|
|
204
|
+
const loader = getLoader$1(extension);
|
|
205
|
+
if (!loader) throw new Error("useEnvironment: Unrecognized file extension: " + files);
|
|
206
|
+
useLoader$1.clear(loader, isArray(files) ? [files] : files);
|
|
207
|
+
};
|
|
208
|
+
function validatePreset(preset) {
|
|
209
|
+
if (!(preset in presetsObj)) throw new Error("Preset must be one of: " + Object.keys(presetsObj).join(", "));
|
|
210
|
+
}
|
|
211
|
+
function getExtension(files) {
|
|
212
|
+
const isCubemap = isArray(files) && files.length === 6;
|
|
213
|
+
const isGainmap = isArray(files) && files.length === 3 && files.some((file) => file.endsWith("json"));
|
|
214
|
+
const firstEntry = isArray(files) ? files[0] : files;
|
|
215
|
+
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();
|
|
216
|
+
return { extension, isCubemap, isGainmap };
|
|
217
|
+
}
|
|
218
|
+
function getLoader$1(extension) {
|
|
219
|
+
const loader = extension === "cube" ? CubeTextureLoader : extension === "hdr" ? HDRLoader : extension === "exr" ? EXRLoader : extension === "jpg" || extension === "jpeg" ? UltraHDRLoader : extension === "webp" ? GainMapLoader : null;
|
|
220
|
+
return loader;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const isRef$1 = (obj) => obj.current && obj.current.isScene;
|
|
224
|
+
const resolveScene = (scene) => isRef$1(scene) ? scene.current : scene;
|
|
225
|
+
function setEnvProps(background, scene, defaultScene, texture, sceneProps = {}) {
|
|
226
|
+
sceneProps = {
|
|
227
|
+
backgroundBlurriness: 0,
|
|
228
|
+
backgroundIntensity: 1,
|
|
229
|
+
backgroundRotation: [0, 0, 0],
|
|
230
|
+
environmentIntensity: 1,
|
|
231
|
+
environmentRotation: [0, 0, 0],
|
|
232
|
+
...sceneProps
|
|
233
|
+
};
|
|
234
|
+
const target = resolveScene(scene || defaultScene);
|
|
235
|
+
const oldbg = target.background;
|
|
236
|
+
const oldenv = target.environment;
|
|
237
|
+
const oldSceneProps = {
|
|
238
|
+
// @ts-ignore
|
|
239
|
+
backgroundBlurriness: target.backgroundBlurriness,
|
|
240
|
+
// @ts-ignore
|
|
241
|
+
backgroundIntensity: target.backgroundIntensity,
|
|
242
|
+
// @ts-ignore
|
|
243
|
+
backgroundRotation: target.backgroundRotation?.clone?.() ?? [0, 0, 0],
|
|
244
|
+
// @ts-ignore
|
|
245
|
+
environmentIntensity: target.environmentIntensity,
|
|
246
|
+
// @ts-ignore
|
|
247
|
+
environmentRotation: target.environmentRotation?.clone?.() ?? [0, 0, 0]
|
|
248
|
+
};
|
|
249
|
+
if (background !== "only") target.environment = texture;
|
|
250
|
+
if (background) target.background = texture;
|
|
251
|
+
applyProps$1(target, sceneProps);
|
|
252
|
+
return () => {
|
|
253
|
+
if (background !== "only") target.environment = oldenv;
|
|
254
|
+
if (background) target.background = oldbg;
|
|
255
|
+
applyProps$1(target, oldSceneProps);
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
function EnvironmentMap({ scene, background = false, map, ...config }) {
|
|
259
|
+
const defaultScene = useThree$1((state) => state.scene);
|
|
260
|
+
React.useLayoutEffect(() => {
|
|
261
|
+
if (map) return setEnvProps(background, scene, defaultScene, map, config);
|
|
262
|
+
});
|
|
263
|
+
return null;
|
|
264
|
+
}
|
|
265
|
+
function EnvironmentCube({
|
|
266
|
+
background = false,
|
|
267
|
+
scene,
|
|
268
|
+
blur,
|
|
269
|
+
backgroundBlurriness,
|
|
270
|
+
backgroundIntensity,
|
|
271
|
+
backgroundRotation,
|
|
272
|
+
environmentIntensity,
|
|
273
|
+
environmentRotation,
|
|
274
|
+
...rest
|
|
275
|
+
}) {
|
|
276
|
+
const texture = useEnvironment(rest);
|
|
277
|
+
const defaultScene = useThree$1((state) => state.scene);
|
|
278
|
+
React.useLayoutEffect(() => {
|
|
279
|
+
return setEnvProps(background, scene, defaultScene, texture, {
|
|
280
|
+
backgroundBlurriness: blur ?? backgroundBlurriness,
|
|
281
|
+
backgroundIntensity,
|
|
282
|
+
backgroundRotation,
|
|
283
|
+
environmentIntensity,
|
|
284
|
+
environmentRotation
|
|
285
|
+
});
|
|
286
|
+
});
|
|
287
|
+
React.useEffect(() => {
|
|
288
|
+
return () => {
|
|
289
|
+
texture.dispose();
|
|
290
|
+
};
|
|
291
|
+
}, [texture]);
|
|
292
|
+
return null;
|
|
293
|
+
}
|
|
294
|
+
function EnvironmentPortal({
|
|
295
|
+
children,
|
|
296
|
+
near = 0.1,
|
|
297
|
+
far = 1e3,
|
|
298
|
+
resolution = 256,
|
|
299
|
+
frames = 1,
|
|
300
|
+
map,
|
|
301
|
+
background = false,
|
|
302
|
+
blur,
|
|
303
|
+
backgroundBlurriness,
|
|
304
|
+
backgroundIntensity,
|
|
305
|
+
backgroundRotation,
|
|
306
|
+
environmentIntensity,
|
|
307
|
+
environmentRotation,
|
|
308
|
+
scene,
|
|
309
|
+
files,
|
|
310
|
+
path,
|
|
311
|
+
preset = void 0,
|
|
312
|
+
extensions
|
|
313
|
+
}) {
|
|
314
|
+
const gl = useThree$1((state) => state.gl);
|
|
315
|
+
const defaultScene = useThree$1((state) => state.scene);
|
|
316
|
+
const camera = React.useRef(null);
|
|
317
|
+
const [virtualScene] = React.useState(() => new Scene());
|
|
318
|
+
const fbo = React.useMemo(() => {
|
|
319
|
+
const fbo2 = new WebGLCubeRenderTarget(resolution);
|
|
320
|
+
fbo2.texture.type = HalfFloatType;
|
|
321
|
+
return fbo2;
|
|
322
|
+
}, [resolution]);
|
|
323
|
+
React.useEffect(() => {
|
|
324
|
+
return () => {
|
|
325
|
+
fbo.dispose();
|
|
326
|
+
};
|
|
327
|
+
}, [fbo]);
|
|
328
|
+
React.useLayoutEffect(() => {
|
|
329
|
+
if (frames === 1) {
|
|
330
|
+
const autoClear = gl.autoClear;
|
|
331
|
+
gl.autoClear = true;
|
|
332
|
+
camera.current.update(gl, virtualScene);
|
|
333
|
+
gl.autoClear = autoClear;
|
|
334
|
+
}
|
|
335
|
+
return setEnvProps(background, scene, defaultScene, fbo.texture, {
|
|
336
|
+
backgroundBlurriness: blur ?? backgroundBlurriness,
|
|
337
|
+
backgroundIntensity,
|
|
338
|
+
backgroundRotation,
|
|
339
|
+
environmentIntensity,
|
|
340
|
+
environmentRotation
|
|
341
|
+
});
|
|
342
|
+
}, [children, virtualScene, fbo.texture, scene, defaultScene, background, frames, gl]);
|
|
343
|
+
let count = 1;
|
|
344
|
+
useFrame$1(() => {
|
|
345
|
+
if (frames === Infinity || count < frames) {
|
|
346
|
+
const autoClear = gl.autoClear;
|
|
347
|
+
gl.autoClear = true;
|
|
348
|
+
camera.current.update(gl, virtualScene);
|
|
349
|
+
gl.autoClear = autoClear;
|
|
350
|
+
count++;
|
|
351
|
+
}
|
|
352
|
+
});
|
|
353
|
+
return /* @__PURE__ */ jsx(Fragment, { children: createPortal$1(
|
|
354
|
+
/* @__PURE__ */ jsxs(Fragment, { children: [
|
|
355
|
+
children,
|
|
356
|
+
/* @__PURE__ */ jsx("cubeCamera", { ref: camera, args: [near, far, fbo] }),
|
|
357
|
+
files || preset ? /* @__PURE__ */ jsx(EnvironmentCube, { background: true, files, preset, path, extensions }) : map ? /* @__PURE__ */ jsx(EnvironmentMap, { background: true, map, extensions }) : null
|
|
358
|
+
] }),
|
|
359
|
+
virtualScene
|
|
360
|
+
) });
|
|
361
|
+
}
|
|
362
|
+
function EnvironmentGround(props) {
|
|
363
|
+
const textureDefault = useEnvironment(props);
|
|
364
|
+
const texture = props.map || textureDefault;
|
|
365
|
+
React.useMemo(() => extend$1({ GroundProjectedEnvImpl: GroundedSkybox }), []);
|
|
366
|
+
React.useEffect(() => {
|
|
367
|
+
return () => {
|
|
368
|
+
textureDefault.dispose();
|
|
369
|
+
};
|
|
370
|
+
}, [textureDefault]);
|
|
371
|
+
const height = props.ground?.height ?? 15;
|
|
372
|
+
const radius = props.ground?.radius ?? 60;
|
|
373
|
+
const scale = props.ground?.scale ?? 1e3;
|
|
374
|
+
const args = React.useMemo(
|
|
375
|
+
() => [texture, height, radius],
|
|
376
|
+
[texture, height, radius]
|
|
377
|
+
);
|
|
378
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
379
|
+
/* @__PURE__ */ jsx(EnvironmentMap, { ...props, map: texture }),
|
|
380
|
+
/* @__PURE__ */ jsx("groundProjectedEnvImpl", { args, scale })
|
|
381
|
+
] });
|
|
382
|
+
}
|
|
383
|
+
function EnvironmentColor({ color, scene }) {
|
|
384
|
+
const defaultScene = useThree$1((state) => state.scene);
|
|
385
|
+
React.useLayoutEffect(() => {
|
|
386
|
+
if (color === void 0) return;
|
|
387
|
+
const target = resolveScene(scene || defaultScene);
|
|
388
|
+
const oldBg = target.background;
|
|
389
|
+
target.background = new Color(color);
|
|
390
|
+
return () => {
|
|
391
|
+
target.background = oldBg;
|
|
392
|
+
};
|
|
393
|
+
});
|
|
394
|
+
return null;
|
|
395
|
+
}
|
|
396
|
+
function EnvironmentDualSource(props) {
|
|
397
|
+
const { backgroundFiles, ...envProps } = props;
|
|
398
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
399
|
+
/* @__PURE__ */ jsx(EnvironmentCube, { ...envProps, background: false }),
|
|
400
|
+
/* @__PURE__ */ jsx(EnvironmentCube, { ...props, files: backgroundFiles, background: "only" })
|
|
401
|
+
] });
|
|
402
|
+
}
|
|
403
|
+
function Environment(props) {
|
|
404
|
+
if (props.color && !props.files && !props.preset && !props.map) {
|
|
405
|
+
return /* @__PURE__ */ jsx(EnvironmentColor, { ...props });
|
|
406
|
+
}
|
|
407
|
+
if (props.backgroundFiles && props.backgroundFiles !== props.files) {
|
|
408
|
+
return /* @__PURE__ */ jsx(EnvironmentDualSource, { ...props });
|
|
409
|
+
}
|
|
410
|
+
return props.ground ? /* @__PURE__ */ jsx(EnvironmentGround, { ...props }) : props.map ? /* @__PURE__ */ jsx(EnvironmentMap, { ...props }) : props.children ? /* @__PURE__ */ jsx(EnvironmentPortal, { ...props }) : /* @__PURE__ */ jsx(EnvironmentCube, { ...props });
|
|
411
|
+
}
|
|
412
|
+
|
|
39
413
|
var __defProp$2 = Object.defineProperty;
|
|
40
414
|
var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
41
415
|
var __publicField$2 = (obj, key, value) => __defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
@@ -215,7 +589,8 @@ function prepare(target, root, type, props) {
|
|
|
215
589
|
object,
|
|
216
590
|
eventCount: 0,
|
|
217
591
|
handlers: {},
|
|
218
|
-
isHidden: false
|
|
592
|
+
isHidden: false,
|
|
593
|
+
deferredRefs: []
|
|
219
594
|
};
|
|
220
595
|
if (object) object.__r3f = instance;
|
|
221
596
|
}
|
|
@@ -264,7 +639,7 @@ function createOcclusionObserverNode(store, uniform) {
|
|
|
264
639
|
let occlusionSetupPromise = null;
|
|
265
640
|
function enableOcclusion(store) {
|
|
266
641
|
const state = store.getState();
|
|
267
|
-
const { internal, renderer
|
|
642
|
+
const { internal, renderer } = state;
|
|
268
643
|
if (internal.occlusionEnabled || occlusionSetupPromise) return;
|
|
269
644
|
const hasOcclusionSupport = typeof renderer?.isOccluded === "function";
|
|
270
645
|
if (!hasOcclusionSupport) {
|
|
@@ -427,6 +802,22 @@ function hasVisibilityHandlers(handlers) {
|
|
|
427
802
|
return !!(handlers.onFramed || handlers.onOccluded || handlers.onVisible);
|
|
428
803
|
}
|
|
429
804
|
|
|
805
|
+
const FROM_REF = Symbol.for("@react-three/fiber.fromRef");
|
|
806
|
+
function fromRef(ref) {
|
|
807
|
+
return { [FROM_REF]: ref };
|
|
808
|
+
}
|
|
809
|
+
function isFromRef(value) {
|
|
810
|
+
return value !== null && typeof value === "object" && FROM_REF in value;
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
const ONCE = Symbol.for("@react-three/fiber.once");
|
|
814
|
+
function once(...args) {
|
|
815
|
+
return { [ONCE]: args.length ? args : true };
|
|
816
|
+
}
|
|
817
|
+
function isOnce(value) {
|
|
818
|
+
return value !== null && typeof value === "object" && ONCE in value;
|
|
819
|
+
}
|
|
820
|
+
|
|
430
821
|
const RESERVED_PROPS = [
|
|
431
822
|
"children",
|
|
432
823
|
"key",
|
|
@@ -497,7 +888,7 @@ function getMemoizedPrototype(root) {
|
|
|
497
888
|
ctor = new root.constructor();
|
|
498
889
|
MEMOIZED_PROTOTYPES.set(root.constructor, ctor);
|
|
499
890
|
}
|
|
500
|
-
} catch
|
|
891
|
+
} catch {
|
|
501
892
|
}
|
|
502
893
|
return ctor;
|
|
503
894
|
}
|
|
@@ -528,7 +919,7 @@ function applyProps(object, props) {
|
|
|
528
919
|
const rootState = instance && findInitialRoot(instance).getState();
|
|
529
920
|
const prevHandlers = instance?.eventCount;
|
|
530
921
|
for (const prop in props) {
|
|
531
|
-
|
|
922
|
+
const value = props[prop];
|
|
532
923
|
if (RESERVED_PROPS.includes(prop)) continue;
|
|
533
924
|
if (instance && EVENT_REGEX.test(prop)) {
|
|
534
925
|
if (typeof value === "function") instance.handlers[prop] = value;
|
|
@@ -543,6 +934,25 @@ function applyProps(object, props) {
|
|
|
543
934
|
continue;
|
|
544
935
|
}
|
|
545
936
|
if (value === void 0) continue;
|
|
937
|
+
if (isFromRef(value)) {
|
|
938
|
+
instance?.deferredRefs?.push({ prop, ref: value[FROM_REF] });
|
|
939
|
+
continue;
|
|
940
|
+
}
|
|
941
|
+
if (isOnce(value)) {
|
|
942
|
+
if (instance?.appliedOnce?.has(prop)) continue;
|
|
943
|
+
if (instance) {
|
|
944
|
+
instance.appliedOnce ?? (instance.appliedOnce = /* @__PURE__ */ new Set());
|
|
945
|
+
instance.appliedOnce.add(prop);
|
|
946
|
+
}
|
|
947
|
+
const { root: targetRoot, key: targetKey } = resolve(object, prop);
|
|
948
|
+
const args = value[ONCE];
|
|
949
|
+
if (typeof targetRoot[targetKey] === "function") {
|
|
950
|
+
targetRoot[targetKey](...args === true ? [] : args);
|
|
951
|
+
} else if (args !== true && args.length > 0) {
|
|
952
|
+
targetRoot[targetKey] = args[0];
|
|
953
|
+
}
|
|
954
|
+
continue;
|
|
955
|
+
}
|
|
546
956
|
let { root, key, target } = resolve(object, prop);
|
|
547
957
|
if (target === void 0 && (typeof root !== "object" || root === null)) {
|
|
548
958
|
throw Error(`R3F: Cannot set "${prop}". Ensure it is an object before setting "${key}".`);
|
|
@@ -565,7 +975,7 @@ function applyProps(object, props) {
|
|
|
565
975
|
else target.set(value);
|
|
566
976
|
} else {
|
|
567
977
|
root[key] = value;
|
|
568
|
-
if (rootState &&
|
|
978
|
+
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
|
|
569
979
|
root[key].format === RGBAFormat && root[key].type === UnsignedByteType) {
|
|
570
980
|
root[key].colorSpace = rootState.textureColorSpace;
|
|
571
981
|
}
|
|
@@ -680,13 +1090,14 @@ function createEvents(store) {
|
|
|
680
1090
|
for (const hit of hits) {
|
|
681
1091
|
let eventObject = hit.object;
|
|
682
1092
|
while (eventObject) {
|
|
683
|
-
if (eventObject.__r3f?.eventCount)
|
|
1093
|
+
if (eventObject.__r3f?.eventCount) {
|
|
684
1094
|
intersections.push({ ...hit, eventObject });
|
|
1095
|
+
}
|
|
685
1096
|
eventObject = eventObject.parent;
|
|
686
1097
|
}
|
|
687
1098
|
}
|
|
688
1099
|
if ("pointerId" in event && state.internal.capturedMap.has(event.pointerId)) {
|
|
689
|
-
for (
|
|
1100
|
+
for (const captureData of state.internal.capturedMap.get(event.pointerId).values()) {
|
|
690
1101
|
if (!duplicates.has(makeId(captureData.intersection))) intersections.push(captureData.intersection);
|
|
691
1102
|
}
|
|
692
1103
|
}
|
|
@@ -716,12 +1127,12 @@ function createEvents(store) {
|
|
|
716
1127
|
releaseInternalPointerCapture(internal.capturedMap, hit.eventObject, captures, id);
|
|
717
1128
|
}
|
|
718
1129
|
};
|
|
719
|
-
|
|
720
|
-
for (
|
|
721
|
-
|
|
1130
|
+
const extractEventProps = {};
|
|
1131
|
+
for (const prop in event) {
|
|
1132
|
+
const property = event[prop];
|
|
722
1133
|
if (typeof property !== "function") extractEventProps[prop] = property;
|
|
723
1134
|
}
|
|
724
|
-
|
|
1135
|
+
const raycastEvent = {
|
|
725
1136
|
...hit,
|
|
726
1137
|
...extractEventProps,
|
|
727
1138
|
pointer,
|
|
@@ -921,7 +1332,7 @@ function createPointerEvents(store) {
|
|
|
921
1332
|
return {
|
|
922
1333
|
priority: 1,
|
|
923
1334
|
enabled: true,
|
|
924
|
-
compute(event, state
|
|
1335
|
+
compute(event, state) {
|
|
925
1336
|
state.pointer.set(event.offsetX / state.size.width * 2 - 1, -(event.offsetY / state.size.height) * 2 + 1);
|
|
926
1337
|
state.raycaster.setFromCamera(state.pointer, state.camera);
|
|
927
1338
|
},
|
|
@@ -1019,300 +1430,26 @@ function notifyAlpha({ message, link }) {
|
|
|
1019
1430
|
}
|
|
1020
1431
|
}
|
|
1021
1432
|
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
}
|
|
1043
|
-
}
|
|
1044
|
-
let performanceTimeout = void 0;
|
|
1045
|
-
const setPerformanceCurrent = (current) => set((state2) => ({ performance: { ...state2.performance, current } }));
|
|
1046
|
-
const pointer = new Vector2();
|
|
1047
|
-
const rootState = {
|
|
1048
|
-
set,
|
|
1049
|
-
get,
|
|
1050
|
-
// Mock objects that have to be configured
|
|
1051
|
-
gl: null,
|
|
1052
|
-
renderer: null,
|
|
1053
|
-
camera: null,
|
|
1054
|
-
frustum: new Frustum(),
|
|
1055
|
-
autoUpdateFrustum: true,
|
|
1056
|
-
raycaster: null,
|
|
1057
|
-
events: { priority: 1, enabled: true, connected: false },
|
|
1058
|
-
scene: null,
|
|
1059
|
-
rootScene: null,
|
|
1060
|
-
xr: null,
|
|
1061
|
-
inspector: null,
|
|
1062
|
-
invalidate: (frames = 1, stackFrames = false) => invalidate(get(), frames, stackFrames),
|
|
1063
|
-
advance: (timestamp, runGlobalEffects) => advance(timestamp, runGlobalEffects, get()),
|
|
1064
|
-
legacy: false,
|
|
1065
|
-
linear: false,
|
|
1066
|
-
flat: false,
|
|
1067
|
-
textureColorSpace: "srgb",
|
|
1068
|
-
isLegacy: false,
|
|
1069
|
-
webGPUSupported: false,
|
|
1070
|
-
isNative: false,
|
|
1071
|
-
controls: null,
|
|
1072
|
-
pointer,
|
|
1073
|
-
mouse: pointer,
|
|
1074
|
-
frameloop: "always",
|
|
1075
|
-
onPointerMissed: void 0,
|
|
1076
|
-
onDragOverMissed: void 0,
|
|
1077
|
-
onDropMissed: void 0,
|
|
1078
|
-
performance: {
|
|
1079
|
-
current: 1,
|
|
1080
|
-
min: 0.5,
|
|
1081
|
-
max: 1,
|
|
1082
|
-
debounce: 200,
|
|
1083
|
-
regress: () => {
|
|
1084
|
-
const state2 = get();
|
|
1085
|
-
if (performanceTimeout) clearTimeout(performanceTimeout);
|
|
1086
|
-
if (state2.performance.current !== state2.performance.min) setPerformanceCurrent(state2.performance.min);
|
|
1087
|
-
performanceTimeout = setTimeout(
|
|
1088
|
-
() => setPerformanceCurrent(get().performance.max),
|
|
1089
|
-
state2.performance.debounce
|
|
1090
|
-
);
|
|
1091
|
-
}
|
|
1092
|
-
},
|
|
1093
|
-
size: { width: 0, height: 0, top: 0, left: 0 },
|
|
1094
|
-
viewport: {
|
|
1095
|
-
initialDpr: 0,
|
|
1096
|
-
dpr: 0,
|
|
1097
|
-
width: 0,
|
|
1098
|
-
height: 0,
|
|
1099
|
-
top: 0,
|
|
1100
|
-
left: 0,
|
|
1101
|
-
aspect: 0,
|
|
1102
|
-
distance: 0,
|
|
1103
|
-
factor: 0,
|
|
1104
|
-
getCurrentViewport
|
|
1105
|
-
},
|
|
1106
|
-
setEvents: (events) => set((state2) => ({ ...state2, events: { ...state2.events, ...events } })),
|
|
1107
|
-
setSize: (width, height, top = 0, left = 0) => {
|
|
1108
|
-
const camera = get().camera;
|
|
1109
|
-
const size = { width, height, top, left };
|
|
1110
|
-
set((state2) => ({ size, viewport: { ...state2.viewport, ...getCurrentViewport(camera, defaultTarget, size) } }));
|
|
1111
|
-
},
|
|
1112
|
-
setDpr: (dpr) => set((state2) => {
|
|
1113
|
-
const resolved = calculateDpr(dpr);
|
|
1114
|
-
return { viewport: { ...state2.viewport, dpr: resolved, initialDpr: state2.viewport.initialDpr || resolved } };
|
|
1115
|
-
}),
|
|
1116
|
-
setFrameloop: (frameloop = "always") => {
|
|
1117
|
-
set(() => ({ frameloop }));
|
|
1118
|
-
},
|
|
1119
|
-
setError: (error) => set(() => ({ error })),
|
|
1120
|
-
error: null,
|
|
1121
|
-
//* TSL State (managed via hooks: useUniforms, useNodes, useTextures, usePostProcessing) ==============================
|
|
1122
|
-
uniforms: {},
|
|
1123
|
-
nodes: {},
|
|
1124
|
-
textures: /* @__PURE__ */ new Map(),
|
|
1125
|
-
postProcessing: null,
|
|
1126
|
-
passes: {},
|
|
1127
|
-
previousRoot: void 0,
|
|
1128
|
-
internal: {
|
|
1129
|
-
// Events
|
|
1130
|
-
interaction: [],
|
|
1131
|
-
hovered: /* @__PURE__ */ new Map(),
|
|
1132
|
-
subscribers: [],
|
|
1133
|
-
initialClick: [0, 0],
|
|
1134
|
-
initialHits: [],
|
|
1135
|
-
capturedMap: /* @__PURE__ */ new Map(),
|
|
1136
|
-
lastEvent: React.createRef(),
|
|
1137
|
-
// Visibility tracking (onFramed, onOccluded, onVisible)
|
|
1138
|
-
visibilityRegistry: /* @__PURE__ */ new Map(),
|
|
1139
|
-
// Occlusion system (WebGPU only)
|
|
1140
|
-
occlusionEnabled: false,
|
|
1141
|
-
occlusionObserver: null,
|
|
1142
|
-
occlusionCache: /* @__PURE__ */ new Map(),
|
|
1143
|
-
helperGroup: null,
|
|
1144
|
-
// Updates
|
|
1145
|
-
active: false,
|
|
1146
|
-
frames: 0,
|
|
1147
|
-
priority: 0,
|
|
1148
|
-
subscribe: (ref, priority, store) => {
|
|
1149
|
-
const internal = get().internal;
|
|
1150
|
-
internal.priority = internal.priority + (priority > 0 ? 1 : 0);
|
|
1151
|
-
internal.subscribers.push({ ref, priority, store });
|
|
1152
|
-
internal.subscribers = internal.subscribers.sort((a, b) => a.priority - b.priority);
|
|
1153
|
-
return () => {
|
|
1154
|
-
const internal2 = get().internal;
|
|
1155
|
-
if (internal2?.subscribers) {
|
|
1156
|
-
internal2.priority = internal2.priority - (priority > 0 ? 1 : 0);
|
|
1157
|
-
internal2.subscribers = internal2.subscribers.filter((s) => s.ref !== ref);
|
|
1158
|
-
}
|
|
1159
|
-
};
|
|
1160
|
-
},
|
|
1161
|
-
// Renderer Storage (single source of truth)
|
|
1162
|
-
actualRenderer: null,
|
|
1163
|
-
// Scheduler for useFrameNext (initialized in renderer.tsx)
|
|
1164
|
-
scheduler: null
|
|
1165
|
-
}
|
|
1166
|
-
};
|
|
1167
|
-
return rootState;
|
|
1168
|
-
});
|
|
1169
|
-
const state = rootStore.getState();
|
|
1170
|
-
Object.defineProperty(state, "gl", {
|
|
1171
|
-
get() {
|
|
1172
|
-
const currentState = rootStore.getState();
|
|
1173
|
-
if (!currentState.isLegacy && currentState.internal.actualRenderer) {
|
|
1174
|
-
const stack = new Error().stack || "";
|
|
1175
|
-
const isInternalAccess = stack.includes("zustand") || stack.includes("setState") || stack.includes("Object.assign") || stack.includes("react-three-fiber/packages/fiber/src/core");
|
|
1176
|
-
if (!isInternalAccess) {
|
|
1177
|
-
const cleanedStack = stack.split("\n").slice(2).join("\n") || "Stack trace unavailable";
|
|
1178
|
-
notifyDepreciated({
|
|
1179
|
-
heading: "Accessing state.gl in WebGPU mode",
|
|
1180
|
-
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
|
|
1181
|
-
});
|
|
1182
|
-
}
|
|
1183
|
-
}
|
|
1184
|
-
return currentState.internal.actualRenderer;
|
|
1185
|
-
},
|
|
1186
|
-
set(value) {
|
|
1187
|
-
rootStore.getState().internal.actualRenderer = value;
|
|
1188
|
-
},
|
|
1189
|
-
enumerable: true,
|
|
1190
|
-
configurable: true
|
|
1191
|
-
});
|
|
1192
|
-
Object.defineProperty(state, "renderer", {
|
|
1193
|
-
get() {
|
|
1194
|
-
return rootStore.getState().internal.actualRenderer;
|
|
1195
|
-
},
|
|
1196
|
-
set(value) {
|
|
1197
|
-
rootStore.getState().internal.actualRenderer = value;
|
|
1198
|
-
},
|
|
1199
|
-
enumerable: true,
|
|
1200
|
-
configurable: true
|
|
1201
|
-
});
|
|
1202
|
-
let oldScene = state.scene;
|
|
1203
|
-
rootStore.subscribe(() => {
|
|
1204
|
-
const currentState = rootStore.getState();
|
|
1205
|
-
const { scene, rootScene, set } = currentState;
|
|
1206
|
-
if (scene !== oldScene) {
|
|
1207
|
-
oldScene = scene;
|
|
1208
|
-
if (scene?.isScene && scene !== rootScene) {
|
|
1209
|
-
set({ rootScene: scene });
|
|
1210
|
-
}
|
|
1211
|
-
}
|
|
1212
|
-
});
|
|
1213
|
-
let oldSize = state.size;
|
|
1214
|
-
let oldDpr = state.viewport.dpr;
|
|
1215
|
-
let oldCamera = state.camera;
|
|
1216
|
-
rootStore.subscribe(() => {
|
|
1217
|
-
const { camera, size, viewport, set, internal } = rootStore.getState();
|
|
1218
|
-
const actualRenderer = internal.actualRenderer;
|
|
1219
|
-
if (size.width !== oldSize.width || size.height !== oldSize.height || viewport.dpr !== oldDpr) {
|
|
1220
|
-
oldSize = size;
|
|
1221
|
-
oldDpr = viewport.dpr;
|
|
1222
|
-
updateCamera(camera, size);
|
|
1223
|
-
if (viewport.dpr > 0) actualRenderer.setPixelRatio(viewport.dpr);
|
|
1224
|
-
const updateStyle = typeof HTMLCanvasElement !== "undefined" && actualRenderer.domElement instanceof HTMLCanvasElement;
|
|
1225
|
-
actualRenderer.setSize(size.width, size.height, updateStyle);
|
|
1226
|
-
}
|
|
1227
|
-
if (camera !== oldCamera) {
|
|
1228
|
-
oldCamera = camera;
|
|
1229
|
-
const { rootScene } = rootStore.getState();
|
|
1230
|
-
if (camera && rootScene && !camera.parent) {
|
|
1231
|
-
rootScene.add(camera);
|
|
1232
|
-
}
|
|
1233
|
-
set((state2) => ({ viewport: { ...state2.viewport, ...state2.viewport.getCurrentViewport(camera) } }));
|
|
1234
|
-
const currentState = rootStore.getState();
|
|
1235
|
-
if (currentState.autoUpdateFrustum && camera) {
|
|
1236
|
-
updateFrustum(camera, currentState.frustum);
|
|
1237
|
-
}
|
|
1238
|
-
}
|
|
1239
|
-
});
|
|
1240
|
-
rootStore.subscribe((state2) => invalidate(state2));
|
|
1241
|
-
return rootStore;
|
|
1242
|
-
};
|
|
1243
|
-
|
|
1244
|
-
const memoizedLoaders = /* @__PURE__ */ new WeakMap();
|
|
1245
|
-
const isConstructor$1 = (value) => typeof value === "function" && value?.prototype?.constructor === value;
|
|
1246
|
-
function getLoader(Proto) {
|
|
1247
|
-
if (isConstructor$1(Proto)) {
|
|
1248
|
-
let loader = memoizedLoaders.get(Proto);
|
|
1249
|
-
if (!loader) {
|
|
1250
|
-
loader = new Proto();
|
|
1251
|
-
memoizedLoaders.set(Proto, loader);
|
|
1252
|
-
}
|
|
1253
|
-
return loader;
|
|
1254
|
-
}
|
|
1255
|
-
return Proto;
|
|
1256
|
-
}
|
|
1257
|
-
function loadingFn(extensions, onProgress) {
|
|
1258
|
-
return function(Proto, input) {
|
|
1259
|
-
const loader = getLoader(Proto);
|
|
1260
|
-
if (extensions) extensions(loader);
|
|
1261
|
-
if ("loadAsync" in loader && typeof loader.loadAsync === "function") {
|
|
1262
|
-
return loader.loadAsync(input, onProgress).then((data) => {
|
|
1263
|
-
if (isObject3D(data?.scene)) Object.assign(data, buildGraph(data.scene));
|
|
1264
|
-
return data;
|
|
1265
|
-
});
|
|
1266
|
-
}
|
|
1267
|
-
return new Promise(
|
|
1268
|
-
(res, reject) => loader.load(
|
|
1269
|
-
input,
|
|
1270
|
-
(data) => {
|
|
1271
|
-
if (isObject3D(data?.scene)) Object.assign(data, buildGraph(data.scene));
|
|
1272
|
-
res(data);
|
|
1273
|
-
},
|
|
1274
|
-
onProgress,
|
|
1275
|
-
(error) => reject(new Error(`Could not load ${input}: ${error?.message}`))
|
|
1276
|
-
)
|
|
1277
|
-
);
|
|
1278
|
-
};
|
|
1279
|
-
}
|
|
1280
|
-
function useLoader(loader, input, extensions, onProgress) {
|
|
1281
|
-
const keys = Array.isArray(input) ? input : [input];
|
|
1282
|
-
const fn = loadingFn(extensions, onProgress);
|
|
1283
|
-
const results = keys.map((key) => suspend(fn, [loader, key], { equal: is.equ }));
|
|
1284
|
-
return Array.isArray(input) ? results : results[0];
|
|
1285
|
-
}
|
|
1286
|
-
useLoader.preload = function(loader, input, extensions, onProgress) {
|
|
1287
|
-
const keys = Array.isArray(input) ? input : [input];
|
|
1288
|
-
keys.forEach((key) => preload(loadingFn(extensions, onProgress), [loader, key]));
|
|
1289
|
-
};
|
|
1290
|
-
useLoader.clear = function(loader, input) {
|
|
1291
|
-
const keys = Array.isArray(input) ? input : [input];
|
|
1292
|
-
keys.forEach((key) => clear([loader, key]));
|
|
1293
|
-
};
|
|
1294
|
-
useLoader.loader = getLoader;
|
|
1295
|
-
|
|
1296
|
-
var __defProp$1 = Object.defineProperty;
|
|
1297
|
-
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1298
|
-
var __publicField$1 = (obj, key, value) => __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1299
|
-
const DEFAULT_PHASES = ["start", "input", "physics", "update", "render", "finish"];
|
|
1300
|
-
class PhaseGraph {
|
|
1301
|
-
constructor() {
|
|
1302
|
-
/** Ordered list of phase nodes */
|
|
1303
|
-
__publicField$1(this, "phases", []);
|
|
1304
|
-
/** Quick lookup by name */
|
|
1305
|
-
__publicField$1(this, "phaseMap", /* @__PURE__ */ new Map());
|
|
1306
|
-
/** Cached ordered names (invalidated on changes) */
|
|
1307
|
-
__publicField$1(this, "orderedNamesCache", null);
|
|
1308
|
-
this.initializeDefaultPhases();
|
|
1309
|
-
}
|
|
1310
|
-
//* Initialization --------------------------------
|
|
1311
|
-
initializeDefaultPhases() {
|
|
1312
|
-
for (const name of DEFAULT_PHASES) {
|
|
1313
|
-
const node = { name, isAutoGenerated: false };
|
|
1314
|
-
this.phases.push(node);
|
|
1315
|
-
this.phaseMap.set(name, node);
|
|
1433
|
+
var __defProp$1 = Object.defineProperty;
|
|
1434
|
+
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1435
|
+
var __publicField$1 = (obj, key, value) => __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1436
|
+
const DEFAULT_PHASES = ["start", "input", "physics", "update", "render", "finish"];
|
|
1437
|
+
class PhaseGraph {
|
|
1438
|
+
constructor() {
|
|
1439
|
+
/** Ordered list of phase nodes */
|
|
1440
|
+
__publicField$1(this, "phases", []);
|
|
1441
|
+
/** Quick lookup by name */
|
|
1442
|
+
__publicField$1(this, "phaseMap", /* @__PURE__ */ new Map());
|
|
1443
|
+
/** Cached ordered names (invalidated on changes) */
|
|
1444
|
+
__publicField$1(this, "orderedNamesCache", null);
|
|
1445
|
+
this.initializeDefaultPhases();
|
|
1446
|
+
}
|
|
1447
|
+
//* Initialization --------------------------------
|
|
1448
|
+
initializeDefaultPhases() {
|
|
1449
|
+
for (const name of DEFAULT_PHASES) {
|
|
1450
|
+
const node = { name, isAutoGenerated: false };
|
|
1451
|
+
this.phases.push(node);
|
|
1452
|
+
this.phaseMap.set(name, node);
|
|
1316
1453
|
}
|
|
1317
1454
|
this.invalidateCache();
|
|
1318
1455
|
}
|
|
@@ -1331,8 +1468,9 @@ class PhaseGraph {
|
|
|
1331
1468
|
const node = { name, isAutoGenerated: false };
|
|
1332
1469
|
let insertIndex = this.phases.length;
|
|
1333
1470
|
const targetIndex = this.getPhaseIndex(before ?? after);
|
|
1334
|
-
if (targetIndex !== -1)
|
|
1335
|
-
|
|
1471
|
+
if (targetIndex !== -1) {
|
|
1472
|
+
insertIndex = before ? targetIndex : targetIndex + 1;
|
|
1473
|
+
} else {
|
|
1336
1474
|
const constraintType = before ? "before" : "after";
|
|
1337
1475
|
console.warn(`[useFrame] Phase "${before ?? after}" not found for '${constraintType}' constraint`);
|
|
1338
1476
|
}
|
|
@@ -2213,116 +2351,429 @@ const _Scheduler = class _Scheduler {
|
|
|
2213
2351
|
root.sortedJobs = rebuildSortedJobs(root.jobs, this.phaseGraph);
|
|
2214
2352
|
root.needsRebuild = false;
|
|
2215
2353
|
}
|
|
2216
|
-
const providedState = root.getState?.() ?? {};
|
|
2217
|
-
const frameState = {
|
|
2218
|
-
...providedState,
|
|
2219
|
-
time: timestamp,
|
|
2220
|
-
delta,
|
|
2221
|
-
elapsed: this.loopState.elapsedTime / 1e3,
|
|
2222
|
-
// Convert ms to seconds
|
|
2223
|
-
frame: this.loopState.frameCount
|
|
2224
|
-
};
|
|
2225
|
-
for (const job of root.sortedJobs) {
|
|
2226
|
-
if (!shouldRun(job, timestamp)) continue;
|
|
2227
|
-
try {
|
|
2228
|
-
job.callback(frameState, delta);
|
|
2229
|
-
} catch (error) {
|
|
2230
|
-
console.error(`[Scheduler] Error in job "${job.id}":`, error);
|
|
2231
|
-
this.triggerError(error instanceof Error ? error : new Error(String(error)));
|
|
2354
|
+
const providedState = root.getState?.() ?? {};
|
|
2355
|
+
const frameState = {
|
|
2356
|
+
...providedState,
|
|
2357
|
+
time: timestamp,
|
|
2358
|
+
delta,
|
|
2359
|
+
elapsed: this.loopState.elapsedTime / 1e3,
|
|
2360
|
+
// Convert ms to seconds
|
|
2361
|
+
frame: this.loopState.frameCount
|
|
2362
|
+
};
|
|
2363
|
+
for (const job of root.sortedJobs) {
|
|
2364
|
+
if (!shouldRun(job, timestamp)) continue;
|
|
2365
|
+
try {
|
|
2366
|
+
job.callback(frameState, delta);
|
|
2367
|
+
} catch (error) {
|
|
2368
|
+
console.error(`[Scheduler] Error in job "${job.id}":`, error);
|
|
2369
|
+
this.triggerError(error instanceof Error ? error : new Error(String(error)));
|
|
2370
|
+
}
|
|
2371
|
+
}
|
|
2372
|
+
}
|
|
2373
|
+
//* Debug & Inspection Methods ================================
|
|
2374
|
+
/**
|
|
2375
|
+
* Get the total number of registered jobs across all roots.
|
|
2376
|
+
* Includes both per-root jobs and global before/after jobs.
|
|
2377
|
+
* @returns {number} Total job count
|
|
2378
|
+
*/
|
|
2379
|
+
getJobCount() {
|
|
2380
|
+
let count = 0;
|
|
2381
|
+
for (const root of this.roots.values()) {
|
|
2382
|
+
count += root.jobs.size;
|
|
2383
|
+
}
|
|
2384
|
+
return count + this.globalBeforeJobs.size + this.globalAfterJobs.size;
|
|
2385
|
+
}
|
|
2386
|
+
/**
|
|
2387
|
+
* Get all registered job IDs across all roots.
|
|
2388
|
+
* Includes both per-root jobs and global before/after jobs.
|
|
2389
|
+
* @returns {string[]} Array of all job IDs
|
|
2390
|
+
*/
|
|
2391
|
+
getJobIds() {
|
|
2392
|
+
const ids = [];
|
|
2393
|
+
for (const root of this.roots.values()) {
|
|
2394
|
+
ids.push(...root.jobs.keys());
|
|
2395
|
+
}
|
|
2396
|
+
ids.push(...this.globalBeforeJobs.keys());
|
|
2397
|
+
ids.push(...this.globalAfterJobs.keys());
|
|
2398
|
+
return ids;
|
|
2399
|
+
}
|
|
2400
|
+
/**
|
|
2401
|
+
* Get the number of registered roots (Canvas instances).
|
|
2402
|
+
* @returns {number} Number of registered roots
|
|
2403
|
+
*/
|
|
2404
|
+
getRootCount() {
|
|
2405
|
+
return this.roots.size;
|
|
2406
|
+
}
|
|
2407
|
+
/**
|
|
2408
|
+
* Check if any user (non-system) jobs are registered in a specific phase.
|
|
2409
|
+
* Used by the default render job to know if a user has taken over rendering.
|
|
2410
|
+
*
|
|
2411
|
+
* @param phase The phase to check
|
|
2412
|
+
* @param rootId Optional root ID to check (checks all roots if not provided)
|
|
2413
|
+
* @returns true if any user jobs exist in the phase
|
|
2414
|
+
*/
|
|
2415
|
+
hasUserJobsInPhase(phase, rootId) {
|
|
2416
|
+
const rootsToCheck = rootId ? [this.roots.get(rootId)].filter(Boolean) : Array.from(this.roots.values());
|
|
2417
|
+
return rootsToCheck.some((root) => {
|
|
2418
|
+
if (!root) return false;
|
|
2419
|
+
for (const job of root.jobs.values()) {
|
|
2420
|
+
if (job.phase === phase && !job.system && job.enabled) return true;
|
|
2421
|
+
}
|
|
2422
|
+
return false;
|
|
2423
|
+
});
|
|
2424
|
+
}
|
|
2425
|
+
//* Utility Methods ================================
|
|
2426
|
+
/**
|
|
2427
|
+
* Generate a unique root ID for automatic root registration.
|
|
2428
|
+
* @returns {string} A unique root ID in the format 'root_N'
|
|
2429
|
+
*/
|
|
2430
|
+
generateRootId() {
|
|
2431
|
+
return `root_${this.nextRootIndex++}`;
|
|
2432
|
+
}
|
|
2433
|
+
/**
|
|
2434
|
+
* Generate a unique job ID.
|
|
2435
|
+
* @returns {string} A unique job ID in the format 'job_N'
|
|
2436
|
+
* @private
|
|
2437
|
+
*/
|
|
2438
|
+
generateJobId() {
|
|
2439
|
+
return `job_${this.nextJobIndex}`;
|
|
2440
|
+
}
|
|
2441
|
+
/**
|
|
2442
|
+
* Normalize before/after constraints to a Set.
|
|
2443
|
+
* Handles undefined, single string, or array inputs.
|
|
2444
|
+
* @param {string | string[] | undefined} value - The constraint value(s)
|
|
2445
|
+
* @returns {Set<string>} Normalized Set of constraint strings
|
|
2446
|
+
* @private
|
|
2447
|
+
*/
|
|
2448
|
+
normalizeConstraints(value) {
|
|
2449
|
+
if (!value) return /* @__PURE__ */ new Set();
|
|
2450
|
+
if (Array.isArray(value)) return new Set(value);
|
|
2451
|
+
return /* @__PURE__ */ new Set([value]);
|
|
2452
|
+
}
|
|
2453
|
+
};
|
|
2454
|
+
//* Static State & Methods (Singleton Usage) ================================
|
|
2455
|
+
//* Cross-Bundle Singleton Key ==============================
|
|
2456
|
+
// Use Symbol.for() to ensure scheduler is shared across bundle boundaries
|
|
2457
|
+
// This prevents issues when mixing imports from @react-three/fiber and @react-three/fiber/webgpu
|
|
2458
|
+
__publicField(_Scheduler, "INSTANCE_KEY", Symbol.for("@react-three/fiber.scheduler"));
|
|
2459
|
+
let Scheduler = _Scheduler;
|
|
2460
|
+
const getScheduler = () => Scheduler.get();
|
|
2461
|
+
if (hmrData) {
|
|
2462
|
+
hmrData.accept?.();
|
|
2463
|
+
}
|
|
2464
|
+
|
|
2465
|
+
const R3F_CONTEXT = Symbol.for("@react-three/fiber.context");
|
|
2466
|
+
const context = globalThis[R3F_CONTEXT] ?? (globalThis[R3F_CONTEXT] = React.createContext(null));
|
|
2467
|
+
const createStore = (invalidate, advance) => {
|
|
2468
|
+
const rootStore = createWithEqualityFn((set, get) => {
|
|
2469
|
+
const position = new Vector3();
|
|
2470
|
+
const defaultTarget = new Vector3();
|
|
2471
|
+
const tempTarget = new Vector3();
|
|
2472
|
+
function getCurrentViewport(camera = get().camera, target = defaultTarget, size = get().size) {
|
|
2473
|
+
const { width, height, top, left } = size;
|
|
2474
|
+
const aspect = width / height;
|
|
2475
|
+
if (target.isVector3) tempTarget.copy(target);
|
|
2476
|
+
else tempTarget.set(...target);
|
|
2477
|
+
const distance = camera.getWorldPosition(position).distanceTo(tempTarget);
|
|
2478
|
+
if (isOrthographicCamera(camera)) {
|
|
2479
|
+
return { width: width / camera.zoom, height: height / camera.zoom, top, left, factor: 1, distance, aspect };
|
|
2480
|
+
} else {
|
|
2481
|
+
const fov = camera.fov * Math.PI / 180;
|
|
2482
|
+
const h = 2 * Math.tan(fov / 2) * distance;
|
|
2483
|
+
const w = h * (width / height);
|
|
2484
|
+
return { width: w, height: h, top, left, factor: width / w, distance, aspect };
|
|
2485
|
+
}
|
|
2486
|
+
}
|
|
2487
|
+
let performanceTimeout = void 0;
|
|
2488
|
+
const setPerformanceCurrent = (current) => set((state2) => ({ performance: { ...state2.performance, current } }));
|
|
2489
|
+
const pointer = new Vector2();
|
|
2490
|
+
const rootState = {
|
|
2491
|
+
set,
|
|
2492
|
+
get,
|
|
2493
|
+
// Mock objects that have to be configured
|
|
2494
|
+
// primaryStore is set after store creation (self-reference for primary, primary's store for secondary)
|
|
2495
|
+
primaryStore: null,
|
|
2496
|
+
gl: null,
|
|
2497
|
+
renderer: null,
|
|
2498
|
+
camera: null,
|
|
2499
|
+
frustum: new Frustum(),
|
|
2500
|
+
autoUpdateFrustum: true,
|
|
2501
|
+
raycaster: null,
|
|
2502
|
+
events: { priority: 1, enabled: true, connected: false },
|
|
2503
|
+
scene: null,
|
|
2504
|
+
rootScene: null,
|
|
2505
|
+
xr: null,
|
|
2506
|
+
inspector: null,
|
|
2507
|
+
invalidate: (frames = 1, stackFrames = false) => invalidate(get(), frames, stackFrames),
|
|
2508
|
+
advance: (timestamp, runGlobalEffects) => advance(timestamp, runGlobalEffects, get()),
|
|
2509
|
+
textureColorSpace: SRGBColorSpace,
|
|
2510
|
+
isLegacy: false,
|
|
2511
|
+
webGPUSupported: false,
|
|
2512
|
+
isNative: false,
|
|
2513
|
+
controls: null,
|
|
2514
|
+
pointer,
|
|
2515
|
+
mouse: pointer,
|
|
2516
|
+
frameloop: "always",
|
|
2517
|
+
onPointerMissed: void 0,
|
|
2518
|
+
onDragOverMissed: void 0,
|
|
2519
|
+
onDropMissed: void 0,
|
|
2520
|
+
performance: {
|
|
2521
|
+
current: 1,
|
|
2522
|
+
min: 0.5,
|
|
2523
|
+
max: 1,
|
|
2524
|
+
debounce: 200,
|
|
2525
|
+
regress: () => {
|
|
2526
|
+
const state2 = get();
|
|
2527
|
+
if (performanceTimeout) clearTimeout(performanceTimeout);
|
|
2528
|
+
if (state2.performance.current !== state2.performance.min) setPerformanceCurrent(state2.performance.min);
|
|
2529
|
+
performanceTimeout = setTimeout(
|
|
2530
|
+
() => setPerformanceCurrent(get().performance.max),
|
|
2531
|
+
state2.performance.debounce
|
|
2532
|
+
);
|
|
2533
|
+
}
|
|
2534
|
+
},
|
|
2535
|
+
size: { width: 0, height: 0, top: 0, left: 0 },
|
|
2536
|
+
viewport: {
|
|
2537
|
+
initialDpr: 0,
|
|
2538
|
+
dpr: 0,
|
|
2539
|
+
width: 0,
|
|
2540
|
+
height: 0,
|
|
2541
|
+
top: 0,
|
|
2542
|
+
left: 0,
|
|
2543
|
+
aspect: 0,
|
|
2544
|
+
distance: 0,
|
|
2545
|
+
factor: 0,
|
|
2546
|
+
getCurrentViewport
|
|
2547
|
+
},
|
|
2548
|
+
setEvents: (events) => set((state2) => ({ ...state2, events: { ...state2.events, ...events } })),
|
|
2549
|
+
setSize: (width, height, top, left) => {
|
|
2550
|
+
const state2 = get();
|
|
2551
|
+
if (width === void 0) {
|
|
2552
|
+
set({ _sizeImperative: false });
|
|
2553
|
+
if (state2._sizeProps) {
|
|
2554
|
+
const { width: propW, height: propH } = state2._sizeProps;
|
|
2555
|
+
if (propW !== void 0 || propH !== void 0) {
|
|
2556
|
+
const currentSize = state2.size;
|
|
2557
|
+
const newSize = {
|
|
2558
|
+
width: propW ?? currentSize.width,
|
|
2559
|
+
height: propH ?? currentSize.height,
|
|
2560
|
+
top: currentSize.top,
|
|
2561
|
+
left: currentSize.left
|
|
2562
|
+
};
|
|
2563
|
+
set((s) => ({
|
|
2564
|
+
size: newSize,
|
|
2565
|
+
viewport: { ...s.viewport, ...getCurrentViewport(state2.camera, defaultTarget, newSize) }
|
|
2566
|
+
}));
|
|
2567
|
+
getScheduler().invalidate();
|
|
2568
|
+
}
|
|
2569
|
+
}
|
|
2570
|
+
return;
|
|
2571
|
+
}
|
|
2572
|
+
const w = width;
|
|
2573
|
+
const h = height ?? width;
|
|
2574
|
+
const t = top ?? state2.size.top;
|
|
2575
|
+
const l = left ?? state2.size.left;
|
|
2576
|
+
const size = { width: w, height: h, top: t, left: l };
|
|
2577
|
+
set((s) => ({
|
|
2578
|
+
size,
|
|
2579
|
+
viewport: { ...s.viewport, ...getCurrentViewport(state2.camera, defaultTarget, size) },
|
|
2580
|
+
_sizeImperative: true
|
|
2581
|
+
}));
|
|
2582
|
+
getScheduler().invalidate();
|
|
2583
|
+
},
|
|
2584
|
+
setDpr: (dpr) => set((state2) => {
|
|
2585
|
+
const resolved = calculateDpr(dpr);
|
|
2586
|
+
return { viewport: { ...state2.viewport, dpr: resolved, initialDpr: state2.viewport.initialDpr || resolved } };
|
|
2587
|
+
}),
|
|
2588
|
+
setFrameloop: (frameloop = "always") => {
|
|
2589
|
+
set(() => ({ frameloop }));
|
|
2590
|
+
},
|
|
2591
|
+
setError: (error) => set(() => ({ error })),
|
|
2592
|
+
error: null,
|
|
2593
|
+
//* TSL State (managed via hooks: useUniforms, useNodes, useTextures, usePostProcessing) ==============================
|
|
2594
|
+
uniforms: {},
|
|
2595
|
+
nodes: {},
|
|
2596
|
+
textures: /* @__PURE__ */ new Map(),
|
|
2597
|
+
postProcessing: null,
|
|
2598
|
+
passes: {},
|
|
2599
|
+
_hmrVersion: 0,
|
|
2600
|
+
_sizeImperative: false,
|
|
2601
|
+
_sizeProps: null,
|
|
2602
|
+
previousRoot: void 0,
|
|
2603
|
+
internal: {
|
|
2604
|
+
// Events
|
|
2605
|
+
interaction: [],
|
|
2606
|
+
hovered: /* @__PURE__ */ new Map(),
|
|
2607
|
+
subscribers: [],
|
|
2608
|
+
initialClick: [0, 0],
|
|
2609
|
+
initialHits: [],
|
|
2610
|
+
capturedMap: /* @__PURE__ */ new Map(),
|
|
2611
|
+
lastEvent: React.createRef(),
|
|
2612
|
+
// Visibility tracking (onFramed, onOccluded, onVisible)
|
|
2613
|
+
visibilityRegistry: /* @__PURE__ */ new Map(),
|
|
2614
|
+
// Occlusion system (WebGPU only)
|
|
2615
|
+
occlusionEnabled: false,
|
|
2616
|
+
occlusionObserver: null,
|
|
2617
|
+
occlusionCache: /* @__PURE__ */ new Map(),
|
|
2618
|
+
helperGroup: null,
|
|
2619
|
+
// Updates
|
|
2620
|
+
active: false,
|
|
2621
|
+
frames: 0,
|
|
2622
|
+
priority: 0,
|
|
2623
|
+
subscribe: (ref, priority, store) => {
|
|
2624
|
+
const internal = get().internal;
|
|
2625
|
+
internal.priority = internal.priority + (priority > 0 ? 1 : 0);
|
|
2626
|
+
internal.subscribers.push({ ref, priority, store });
|
|
2627
|
+
internal.subscribers = internal.subscribers.sort((a, b) => a.priority - b.priority);
|
|
2628
|
+
return () => {
|
|
2629
|
+
const internal2 = get().internal;
|
|
2630
|
+
if (internal2?.subscribers) {
|
|
2631
|
+
internal2.priority = internal2.priority - (priority > 0 ? 1 : 0);
|
|
2632
|
+
internal2.subscribers = internal2.subscribers.filter((s) => s.ref !== ref);
|
|
2633
|
+
}
|
|
2634
|
+
};
|
|
2635
|
+
},
|
|
2636
|
+
// Renderer Storage (single source of truth)
|
|
2637
|
+
actualRenderer: null,
|
|
2638
|
+
// Scheduler for useFrameNext (initialized in renderer.tsx)
|
|
2639
|
+
scheduler: null
|
|
2640
|
+
}
|
|
2641
|
+
};
|
|
2642
|
+
return rootState;
|
|
2643
|
+
});
|
|
2644
|
+
const state = rootStore.getState();
|
|
2645
|
+
Object.defineProperty(state, "gl", {
|
|
2646
|
+
get() {
|
|
2647
|
+
const currentState = rootStore.getState();
|
|
2648
|
+
if (!currentState.isLegacy && currentState.internal.actualRenderer) {
|
|
2649
|
+
const stack = new Error().stack || "";
|
|
2650
|
+
const isInternalAccess = stack.includes("zustand") || stack.includes("setState") || stack.includes("Object.assign") || stack.includes("react-three-fiber/packages/fiber/src/core");
|
|
2651
|
+
if (!isInternalAccess) {
|
|
2652
|
+
const cleanedStack = stack.split("\n").slice(2).join("\n") || "Stack trace unavailable";
|
|
2653
|
+
notifyDepreciated({
|
|
2654
|
+
heading: "Accessing state.gl in WebGPU mode",
|
|
2655
|
+
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
|
|
2656
|
+
});
|
|
2657
|
+
}
|
|
2658
|
+
}
|
|
2659
|
+
return currentState.internal.actualRenderer;
|
|
2660
|
+
},
|
|
2661
|
+
set(value) {
|
|
2662
|
+
rootStore.getState().internal.actualRenderer = value;
|
|
2663
|
+
},
|
|
2664
|
+
enumerable: true,
|
|
2665
|
+
configurable: true
|
|
2666
|
+
});
|
|
2667
|
+
Object.defineProperty(state, "renderer", {
|
|
2668
|
+
get() {
|
|
2669
|
+
return rootStore.getState().internal.actualRenderer;
|
|
2670
|
+
},
|
|
2671
|
+
set(value) {
|
|
2672
|
+
rootStore.getState().internal.actualRenderer = value;
|
|
2673
|
+
},
|
|
2674
|
+
enumerable: true,
|
|
2675
|
+
configurable: true
|
|
2676
|
+
});
|
|
2677
|
+
let oldScene = state.scene;
|
|
2678
|
+
rootStore.subscribe(() => {
|
|
2679
|
+
const currentState = rootStore.getState();
|
|
2680
|
+
const { scene, rootScene, set } = currentState;
|
|
2681
|
+
if (scene !== oldScene) {
|
|
2682
|
+
oldScene = scene;
|
|
2683
|
+
if (scene?.isScene && scene !== rootScene) {
|
|
2684
|
+
set({ rootScene: scene });
|
|
2685
|
+
}
|
|
2686
|
+
}
|
|
2687
|
+
});
|
|
2688
|
+
let oldSize = state.size;
|
|
2689
|
+
let oldDpr = state.viewport.dpr;
|
|
2690
|
+
let oldCamera = state.camera;
|
|
2691
|
+
rootStore.subscribe(() => {
|
|
2692
|
+
const { camera, size, viewport, set, internal } = rootStore.getState();
|
|
2693
|
+
const actualRenderer = internal.actualRenderer;
|
|
2694
|
+
const canvasTarget = internal.canvasTarget;
|
|
2695
|
+
if (size.width !== oldSize.width || size.height !== oldSize.height || viewport.dpr !== oldDpr) {
|
|
2696
|
+
oldSize = size;
|
|
2697
|
+
oldDpr = viewport.dpr;
|
|
2698
|
+
updateCamera(camera, size);
|
|
2699
|
+
if (canvasTarget) {
|
|
2700
|
+
if (viewport.dpr > 0) canvasTarget.setPixelRatio(viewport.dpr);
|
|
2701
|
+
const updateStyle = typeof HTMLCanvasElement !== "undefined" && canvasTarget.domElement instanceof HTMLCanvasElement;
|
|
2702
|
+
canvasTarget.setSize(size.width, size.height, updateStyle);
|
|
2703
|
+
} else {
|
|
2704
|
+
if (viewport.dpr > 0) actualRenderer.setPixelRatio(viewport.dpr);
|
|
2705
|
+
const updateStyle = typeof HTMLCanvasElement !== "undefined" && actualRenderer.domElement instanceof HTMLCanvasElement;
|
|
2706
|
+
actualRenderer.setSize(size.width, size.height, updateStyle);
|
|
2707
|
+
}
|
|
2708
|
+
}
|
|
2709
|
+
if (camera !== oldCamera) {
|
|
2710
|
+
oldCamera = camera;
|
|
2711
|
+
const { rootScene } = rootStore.getState();
|
|
2712
|
+
if (camera && rootScene && !camera.parent) {
|
|
2713
|
+
rootScene.add(camera);
|
|
2714
|
+
}
|
|
2715
|
+
set((state2) => ({ viewport: { ...state2.viewport, ...state2.viewport.getCurrentViewport(camera) } }));
|
|
2716
|
+
const currentState = rootStore.getState();
|
|
2717
|
+
if (currentState.autoUpdateFrustum && camera) {
|
|
2718
|
+
updateFrustum(camera, currentState.frustum);
|
|
2232
2719
|
}
|
|
2233
2720
|
}
|
|
2234
|
-
}
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2721
|
+
});
|
|
2722
|
+
rootStore.subscribe((state2) => invalidate(state2));
|
|
2723
|
+
return rootStore;
|
|
2724
|
+
};
|
|
2725
|
+
|
|
2726
|
+
const memoizedLoaders = /* @__PURE__ */ new WeakMap();
|
|
2727
|
+
const isConstructor$1 = (value) => typeof value === "function" && value?.prototype?.constructor === value;
|
|
2728
|
+
function getLoader(Proto) {
|
|
2729
|
+
if (isConstructor$1(Proto)) {
|
|
2730
|
+
let loader = memoizedLoaders.get(Proto);
|
|
2731
|
+
if (!loader) {
|
|
2732
|
+
loader = new Proto();
|
|
2733
|
+
memoizedLoaders.set(Proto, loader);
|
|
2245
2734
|
}
|
|
2246
|
-
return
|
|
2735
|
+
return loader;
|
|
2247
2736
|
}
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2737
|
+
return Proto;
|
|
2738
|
+
}
|
|
2739
|
+
function loadingFn(extensions, onProgress) {
|
|
2740
|
+
return function(Proto, input) {
|
|
2741
|
+
const loader = getLoader(Proto);
|
|
2742
|
+
if (extensions) extensions(loader);
|
|
2743
|
+
if ("loadAsync" in loader && typeof loader.loadAsync === "function") {
|
|
2744
|
+
return loader.loadAsync(input, onProgress).then((data) => {
|
|
2745
|
+
if (isObject3D(data?.scene)) Object.assign(data, buildGraph(data.scene));
|
|
2746
|
+
return data;
|
|
2747
|
+
});
|
|
2257
2748
|
}
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
*/
|
|
2277
|
-
hasUserJobsInPhase(phase, rootId) {
|
|
2278
|
-
const rootsToCheck = rootId ? [this.roots.get(rootId)].filter(Boolean) : Array.from(this.roots.values());
|
|
2279
|
-
return rootsToCheck.some((root) => {
|
|
2280
|
-
if (!root) return false;
|
|
2281
|
-
for (const job of root.jobs.values()) {
|
|
2282
|
-
if (job.phase === phase && !job.system && job.enabled) return true;
|
|
2283
|
-
}
|
|
2284
|
-
return false;
|
|
2285
|
-
});
|
|
2286
|
-
}
|
|
2287
|
-
//* Utility Methods ================================
|
|
2288
|
-
/**
|
|
2289
|
-
* Generate a unique root ID for automatic root registration.
|
|
2290
|
-
* @returns {string} A unique root ID in the format 'root_N'
|
|
2291
|
-
*/
|
|
2292
|
-
generateRootId() {
|
|
2293
|
-
return `root_${this.nextRootIndex++}`;
|
|
2294
|
-
}
|
|
2295
|
-
/**
|
|
2296
|
-
* Generate a unique job ID.
|
|
2297
|
-
* @returns {string} A unique job ID in the format 'job_N'
|
|
2298
|
-
* @private
|
|
2299
|
-
*/
|
|
2300
|
-
generateJobId() {
|
|
2301
|
-
return `job_${this.nextJobIndex}`;
|
|
2302
|
-
}
|
|
2303
|
-
/**
|
|
2304
|
-
* Normalize before/after constraints to a Set.
|
|
2305
|
-
* Handles undefined, single string, or array inputs.
|
|
2306
|
-
* @param {string | string[] | undefined} value - The constraint value(s)
|
|
2307
|
-
* @returns {Set<string>} Normalized Set of constraint strings
|
|
2308
|
-
* @private
|
|
2309
|
-
*/
|
|
2310
|
-
normalizeConstraints(value) {
|
|
2311
|
-
if (!value) return /* @__PURE__ */ new Set();
|
|
2312
|
-
if (Array.isArray(value)) return new Set(value);
|
|
2313
|
-
return /* @__PURE__ */ new Set([value]);
|
|
2314
|
-
}
|
|
2315
|
-
};
|
|
2316
|
-
//* Static State & Methods (Singleton Usage) ================================
|
|
2317
|
-
//* Cross-Bundle Singleton Key ==============================
|
|
2318
|
-
// Use Symbol.for() to ensure scheduler is shared across bundle boundaries
|
|
2319
|
-
// This prevents issues when mixing imports from @react-three/fiber and @react-three/fiber/webgpu
|
|
2320
|
-
__publicField(_Scheduler, "INSTANCE_KEY", Symbol.for("@react-three/fiber.scheduler"));
|
|
2321
|
-
let Scheduler = _Scheduler;
|
|
2322
|
-
const getScheduler = () => Scheduler.get();
|
|
2323
|
-
if (hmrData) {
|
|
2324
|
-
hmrData.accept?.();
|
|
2749
|
+
return new Promise(
|
|
2750
|
+
(res, reject) => loader.load(
|
|
2751
|
+
input,
|
|
2752
|
+
(data) => {
|
|
2753
|
+
if (isObject3D(data?.scene)) Object.assign(data, buildGraph(data.scene));
|
|
2754
|
+
res(data);
|
|
2755
|
+
},
|
|
2756
|
+
onProgress,
|
|
2757
|
+
(error) => reject(new Error(`Could not load ${input}: ${error?.message}`))
|
|
2758
|
+
)
|
|
2759
|
+
);
|
|
2760
|
+
};
|
|
2761
|
+
}
|
|
2762
|
+
function useLoader(loader, input, extensions, onProgress) {
|
|
2763
|
+
const keys = Array.isArray(input) ? input : [input];
|
|
2764
|
+
const fn = loadingFn(extensions, onProgress);
|
|
2765
|
+
const results = keys.map((key) => suspend(fn, [loader, key], { equal: is.equ }));
|
|
2766
|
+
return Array.isArray(input) ? results : results[0];
|
|
2325
2767
|
}
|
|
2768
|
+
useLoader.preload = function(loader, input, extensions, onProgress) {
|
|
2769
|
+
const keys = Array.isArray(input) ? input : [input];
|
|
2770
|
+
keys.forEach((key) => preload(loadingFn(extensions, onProgress), [loader, key]));
|
|
2771
|
+
};
|
|
2772
|
+
useLoader.clear = function(loader, input) {
|
|
2773
|
+
const keys = Array.isArray(input) ? input : [input];
|
|
2774
|
+
keys.forEach((key) => clear([loader, key]));
|
|
2775
|
+
};
|
|
2776
|
+
useLoader.loader = getLoader;
|
|
2326
2777
|
|
|
2327
2778
|
function useFrame(callback, priorityOrOptions) {
|
|
2328
2779
|
const store = React.useContext(context);
|
|
@@ -2503,6 +2954,9 @@ function useTexture(input, optionsOrOnLoad) {
|
|
|
2503
2954
|
const textureCache = useThree((state) => state.textures);
|
|
2504
2955
|
const options = typeof optionsOrOnLoad === "function" ? { onLoad: optionsOrOnLoad } : optionsOrOnLoad ?? {};
|
|
2505
2956
|
const { onLoad, cache = false } = options;
|
|
2957
|
+
const onLoadRef = useRef(onLoad);
|
|
2958
|
+
onLoadRef.current = onLoad;
|
|
2959
|
+
const onLoadCalledForRef = useRef(null);
|
|
2506
2960
|
const urls = useMemo(() => getUrls(input), [input]);
|
|
2507
2961
|
const cachedResult = useMemo(() => {
|
|
2508
2962
|
if (!cache) return null;
|
|
@@ -2513,9 +2967,13 @@ function useTexture(input, optionsOrOnLoad) {
|
|
|
2513
2967
|
TextureLoader,
|
|
2514
2968
|
IsObject(input) ? Object.values(input) : input
|
|
2515
2969
|
);
|
|
2970
|
+
const inputKey = urls.join("\0");
|
|
2516
2971
|
useLayoutEffect(() => {
|
|
2517
|
-
if (
|
|
2518
|
-
|
|
2972
|
+
if (cachedResult) return;
|
|
2973
|
+
if (onLoadCalledForRef.current === inputKey) return;
|
|
2974
|
+
onLoadCalledForRef.current = inputKey;
|
|
2975
|
+
onLoadRef.current?.(loadedTextures);
|
|
2976
|
+
}, [cachedResult, loadedTextures, inputKey]);
|
|
2519
2977
|
useEffect(() => {
|
|
2520
2978
|
if (cachedResult) return;
|
|
2521
2979
|
if ("initTexture" in renderer) {
|
|
@@ -2682,16 +3140,33 @@ function useTextures() {
|
|
|
2682
3140
|
}, [store]);
|
|
2683
3141
|
}
|
|
2684
3142
|
|
|
2685
|
-
function useRenderTarget(
|
|
3143
|
+
function useRenderTarget(widthOrOptions, heightOrOptions, options) {
|
|
2686
3144
|
const isLegacy = useThree((s) => s.isLegacy);
|
|
2687
3145
|
const size = useThree((s) => s.size);
|
|
3146
|
+
let width;
|
|
3147
|
+
let height;
|
|
3148
|
+
let opts;
|
|
3149
|
+
if (typeof widthOrOptions === "object") {
|
|
3150
|
+
opts = widthOrOptions;
|
|
3151
|
+
} else if (typeof widthOrOptions === "number") {
|
|
3152
|
+
width = widthOrOptions;
|
|
3153
|
+
if (typeof heightOrOptions === "object") {
|
|
3154
|
+
height = widthOrOptions;
|
|
3155
|
+
opts = heightOrOptions;
|
|
3156
|
+
} else if (typeof heightOrOptions === "number") {
|
|
3157
|
+
height = heightOrOptions;
|
|
3158
|
+
opts = options;
|
|
3159
|
+
} else {
|
|
3160
|
+
height = widthOrOptions;
|
|
3161
|
+
}
|
|
3162
|
+
}
|
|
2688
3163
|
return useMemo(() => {
|
|
2689
3164
|
const w = width ?? size.width;
|
|
2690
3165
|
const h = height ?? size.height;
|
|
2691
3166
|
{
|
|
2692
|
-
return isLegacy ? new WebGLRenderTarget(w, h,
|
|
3167
|
+
return isLegacy ? new WebGLRenderTarget(w, h, opts) : new RenderTarget(w, h, opts);
|
|
2693
3168
|
}
|
|
2694
|
-
}, [width, height, size.width, size.height,
|
|
3169
|
+
}, [width, height, size.width, size.height, opts, isLegacy]);
|
|
2695
3170
|
}
|
|
2696
3171
|
|
|
2697
3172
|
function useStore() {
|
|
@@ -2741,28 +3216,18 @@ function addTail(callback) {
|
|
|
2741
3216
|
function invalidate(state, frames = 1, stackFrames = false) {
|
|
2742
3217
|
getScheduler().invalidate(frames, stackFrames);
|
|
2743
3218
|
}
|
|
2744
|
-
function advance(timestamp
|
|
3219
|
+
function advance(timestamp) {
|
|
2745
3220
|
getScheduler().step(timestamp);
|
|
2746
3221
|
}
|
|
2747
3222
|
|
|
2748
|
-
const version = "10.0.0-alpha.
|
|
3223
|
+
const version = "10.0.0-alpha.2";
|
|
2749
3224
|
const packageData = {
|
|
2750
3225
|
version: version};
|
|
2751
3226
|
|
|
2752
3227
|
function Xb(Tt) {
|
|
2753
3228
|
return Tt && Tt.__esModule && Object.prototype.hasOwnProperty.call(Tt, "default") ? Tt.default : Tt;
|
|
2754
3229
|
}
|
|
2755
|
-
var Rm = { exports: {} }, Og = { exports: {} };
|
|
2756
|
-
/**
|
|
2757
|
-
* @license React
|
|
2758
|
-
* react-reconciler.production.js
|
|
2759
|
-
*
|
|
2760
|
-
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2761
|
-
*
|
|
2762
|
-
* This source code is licensed under the MIT license found in the
|
|
2763
|
-
* LICENSE file in the root directory of this source tree.
|
|
2764
|
-
*/
|
|
2765
|
-
var _b;
|
|
3230
|
+
var Rm = { exports: {} }, Og = { exports: {} }, _b;
|
|
2766
3231
|
function Kb() {
|
|
2767
3232
|
return _b || (_b = 1, (function(Tt) {
|
|
2768
3233
|
Tt.exports = function(m) {
|
|
@@ -3834,7 +4299,6 @@ Error generating stack: ` + l.message + `
|
|
|
3834
4299
|
if (J === cl || J === jc) throw J;
|
|
3835
4300
|
var Ge = Yn(29, J, null, P.mode);
|
|
3836
4301
|
return Ge.lanes = H, Ge.return = P, Ge;
|
|
3837
|
-
} finally {
|
|
3838
4302
|
}
|
|
3839
4303
|
};
|
|
3840
4304
|
}
|
|
@@ -4488,7 +4952,6 @@ Error generating stack: ` + l.message + `
|
|
|
4488
4952
|
var h = r.lastRenderedState, y = d(h, a);
|
|
4489
4953
|
if (c.hasEagerState = true, c.eagerState = y, jn(y, h)) return go(t, r, c, 0), Ne === null && Bn(), false;
|
|
4490
4954
|
} catch {
|
|
4491
|
-
} finally {
|
|
4492
4955
|
}
|
|
4493
4956
|
if (a = yo(t, r, c, l), a !== null) return nt(a, t, l), ns(a, r, l), true;
|
|
4494
4957
|
}
|
|
@@ -6909,10 +7372,7 @@ Error generating stack: ` + l.message + `
|
|
|
6909
7372
|
function vr(t, r) {
|
|
6910
7373
|
Sf(t, r), (t = t.alternate) && Sf(t, r);
|
|
6911
7374
|
}
|
|
6912
|
-
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");
|
|
6913
|
-
var gc = Symbol.for("react.activity");
|
|
6914
|
-
var $r = Symbol.for("react.memo_cache_sentinel");
|
|
6915
|
-
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;
|
|
7375
|
+
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;
|
|
6916
7376
|
m.cloneMutableInstance;
|
|
6917
7377
|
var yc = m.appendInitialChild, Kp = m.finalizeInitialChildren, Rs = m.shouldSetTextContent, bc = m.createTextInstance;
|
|
6918
7378
|
m.cloneMutableTextInstance;
|
|
@@ -7281,17 +7741,7 @@ No matching component was found for:
|
|
|
7281
7741
|
}, Tt.exports.default = Tt.exports, Object.defineProperty(Tt.exports, "__esModule", { value: true });
|
|
7282
7742
|
})(Og)), Og.exports;
|
|
7283
7743
|
}
|
|
7284
|
-
var Mg = { exports: {} };
|
|
7285
|
-
/**
|
|
7286
|
-
* @license React
|
|
7287
|
-
* react-reconciler.development.js
|
|
7288
|
-
*
|
|
7289
|
-
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
7290
|
-
*
|
|
7291
|
-
* This source code is licensed under the MIT license found in the
|
|
7292
|
-
* LICENSE file in the root directory of this source tree.
|
|
7293
|
-
*/
|
|
7294
|
-
var Rb;
|
|
7744
|
+
var Mg = { exports: {} }, Rb;
|
|
7295
7745
|
function e0() {
|
|
7296
7746
|
return Rb || (Rb = 1, (function(Tt) {
|
|
7297
7747
|
process.env.NODE_ENV !== "production" && (Tt.exports = function(m) {
|
|
@@ -13058,10 +13508,7 @@ Check the render method of %s.`, G(di) || "Unknown")), i = zo(n), i.payload = {
|
|
|
13058
13508
|
function Ic() {
|
|
13059
13509
|
return di;
|
|
13060
13510
|
}
|
|
13061
|
-
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");
|
|
13062
|
-
var Ds = Symbol.for("react.activity");
|
|
13063
|
-
var Bh = Symbol.for("react.memo_cache_sentinel");
|
|
13064
|
-
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;
|
|
13511
|
+
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;
|
|
13065
13512
|
m.cloneMutableInstance;
|
|
13066
13513
|
var bn = m.appendInitialChild, Ue = m.finalizeInitialChildren, ue = m.shouldSetTextContent, Do = m.createTextInstance;
|
|
13067
13514
|
m.cloneMutableTextInstance;
|
|
@@ -14029,15 +14476,6 @@ function n0() {
|
|
|
14029
14476
|
var t0 = n0();
|
|
14030
14477
|
const r0 = Xb(t0);
|
|
14031
14478
|
|
|
14032
|
-
/**
|
|
14033
|
-
* @license React
|
|
14034
|
-
* react-reconciler-constants.production.js
|
|
14035
|
-
*
|
|
14036
|
-
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
14037
|
-
*
|
|
14038
|
-
* This source code is licensed under the MIT license found in the
|
|
14039
|
-
* LICENSE file in the root directory of this source tree.
|
|
14040
|
-
*/
|
|
14041
14479
|
const t = 1, o = 8, r = 32, e = 2;
|
|
14042
14480
|
|
|
14043
14481
|
function createReconciler(config) {
|
|
@@ -14064,10 +14502,11 @@ function extend(objects) {
|
|
|
14064
14502
|
function validateInstance(type, props) {
|
|
14065
14503
|
const name = toPascalCase(type);
|
|
14066
14504
|
const target = catalogue[name];
|
|
14067
|
-
if (type !== "primitive" && !target)
|
|
14505
|
+
if (type !== "primitive" && !target) {
|
|
14068
14506
|
throw new Error(
|
|
14069
14507
|
`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`
|
|
14070
14508
|
);
|
|
14509
|
+
}
|
|
14071
14510
|
if (type === "primitive" && !props.object) throw new Error(`R3F: Primitives without 'object' are invalid!`);
|
|
14072
14511
|
if (props.args !== void 0 && !Array.isArray(props.args)) throw new Error("R3F: The args prop must be an array!");
|
|
14073
14512
|
}
|
|
@@ -14231,6 +14670,7 @@ function swapInstances() {
|
|
|
14231
14670
|
instance.object = instance.props.object ?? new target(...instance.props.args ?? []);
|
|
14232
14671
|
instance.object.__r3f = instance;
|
|
14233
14672
|
setFiberRef(fiber, instance.object);
|
|
14673
|
+
delete instance.appliedOnce;
|
|
14234
14674
|
applyProps(instance.object, instance.props);
|
|
14235
14675
|
if (instance.props.attach) {
|
|
14236
14676
|
attach(parent, instance);
|
|
@@ -14304,8 +14744,22 @@ const reconciler = /* @__PURE__ */ createReconciler({
|
|
|
14304
14744
|
const isTailSibling = fiber.sibling === null || (fiber.flags & Update) === NoFlags;
|
|
14305
14745
|
if (isTailSibling) swapInstances();
|
|
14306
14746
|
},
|
|
14307
|
-
finalizeInitialChildren: () =>
|
|
14308
|
-
|
|
14747
|
+
finalizeInitialChildren: (instance) => {
|
|
14748
|
+
for (const prop in instance.props) {
|
|
14749
|
+
if (isFromRef(instance.props[prop])) return true;
|
|
14750
|
+
}
|
|
14751
|
+
return false;
|
|
14752
|
+
},
|
|
14753
|
+
commitMount(instance) {
|
|
14754
|
+
const resolved = {};
|
|
14755
|
+
for (const prop in instance.props) {
|
|
14756
|
+
const value = instance.props[prop];
|
|
14757
|
+
if (isFromRef(value)) {
|
|
14758
|
+
const ref = value[FROM_REF];
|
|
14759
|
+
if (ref.current != null) resolved[prop] = ref.current;
|
|
14760
|
+
}
|
|
14761
|
+
}
|
|
14762
|
+
if (Object.keys(resolved).length) applyProps(instance.object, resolved);
|
|
14309
14763
|
},
|
|
14310
14764
|
getPublicInstance: (instance) => instance?.object,
|
|
14311
14765
|
prepareForCommit: () => null,
|
|
@@ -14518,14 +14972,17 @@ function createRoot(canvas) {
|
|
|
14518
14972
|
if (!prevRoot) _roots.set(canvas, { fiber, store });
|
|
14519
14973
|
let onCreated;
|
|
14520
14974
|
let lastCamera;
|
|
14521
|
-
|
|
14975
|
+
const lastConfiguredProps = {};
|
|
14522
14976
|
let configured = false;
|
|
14523
14977
|
let pending = null;
|
|
14524
14978
|
return {
|
|
14525
14979
|
async configure(props = {}) {
|
|
14526
14980
|
let resolve;
|
|
14527
14981
|
pending = new Promise((_resolve) => resolve = _resolve);
|
|
14528
|
-
|
|
14982
|
+
const {
|
|
14983
|
+
id: canvasId,
|
|
14984
|
+
primaryCanvas,
|
|
14985
|
+
scheduler: schedulerConfig,
|
|
14529
14986
|
gl: glConfig,
|
|
14530
14987
|
renderer: rendererConfig,
|
|
14531
14988
|
size: propsSize,
|
|
@@ -14533,10 +14990,7 @@ function createRoot(canvas) {
|
|
|
14533
14990
|
events,
|
|
14534
14991
|
onCreated: onCreatedCallback,
|
|
14535
14992
|
shadows = false,
|
|
14536
|
-
linear = false,
|
|
14537
|
-
flat = false,
|
|
14538
14993
|
textureColorSpace = SRGBColorSpace,
|
|
14539
|
-
legacy = false,
|
|
14540
14994
|
orthographic = false,
|
|
14541
14995
|
frameloop = "always",
|
|
14542
14996
|
dpr = [1, 2],
|
|
@@ -14547,9 +15001,11 @@ function createRoot(canvas) {
|
|
|
14547
15001
|
onDragOverMissed,
|
|
14548
15002
|
onDropMissed,
|
|
14549
15003
|
autoUpdateFrustum = true,
|
|
14550
|
-
occlusion = false
|
|
15004
|
+
occlusion = false,
|
|
15005
|
+
_sizeProps,
|
|
15006
|
+
forceEven
|
|
14551
15007
|
} = props;
|
|
14552
|
-
|
|
15008
|
+
const state = store.getState();
|
|
14553
15009
|
const defaultGLProps = {
|
|
14554
15010
|
canvas,
|
|
14555
15011
|
powerPreference: "high-performance",
|
|
@@ -14557,7 +15013,8 @@ function createRoot(canvas) {
|
|
|
14557
15013
|
alpha: true
|
|
14558
15014
|
};
|
|
14559
15015
|
const defaultGPUProps = {
|
|
14560
|
-
canvas
|
|
15016
|
+
canvas,
|
|
15017
|
+
antialias: true
|
|
14561
15018
|
};
|
|
14562
15019
|
const wantsGL = (state.isLegacy || glConfig || !R3F_BUILD_WEBGPU || !rendererConfig);
|
|
14563
15020
|
if (glConfig && rendererConfig) {
|
|
@@ -14571,10 +15028,35 @@ function createRoot(canvas) {
|
|
|
14571
15028
|
});
|
|
14572
15029
|
}
|
|
14573
15030
|
let renderer = state.internal.actualRenderer;
|
|
15031
|
+
if (primaryCanvas && wantsGL) {
|
|
15032
|
+
throw new Error(
|
|
15033
|
+
"The `primaryCanvas` prop for multi-canvas rendering cannot be used with WebGL. Remove the `gl` prop or use WebGPU."
|
|
15034
|
+
);
|
|
15035
|
+
}
|
|
14574
15036
|
if (wantsGL && !state.internal.actualRenderer) {
|
|
14575
15037
|
renderer = await resolveRenderer(glConfig, defaultGLProps, WebGLRenderer);
|
|
14576
15038
|
state.internal.actualRenderer = renderer;
|
|
14577
|
-
state.set({ isLegacy: true, gl: renderer, renderer });
|
|
15039
|
+
state.set({ isLegacy: true, gl: renderer, renderer, primaryStore: store });
|
|
15040
|
+
} else if (!wantsGL && primaryCanvas && !state.internal.actualRenderer) {
|
|
15041
|
+
const primary = await waitForPrimary(primaryCanvas);
|
|
15042
|
+
renderer = primary.renderer;
|
|
15043
|
+
state.internal.actualRenderer = renderer;
|
|
15044
|
+
const canvasTarget = new CanvasTarget(canvas);
|
|
15045
|
+
primary.store.setState((prev) => ({
|
|
15046
|
+
internal: { ...prev.internal, isMultiCanvas: true }
|
|
15047
|
+
}));
|
|
15048
|
+
state.set((prev) => ({
|
|
15049
|
+
webGPUSupported: primary.store.getState().webGPUSupported,
|
|
15050
|
+
renderer,
|
|
15051
|
+
primaryStore: primary.store,
|
|
15052
|
+
internal: {
|
|
15053
|
+
...prev.internal,
|
|
15054
|
+
canvasTarget,
|
|
15055
|
+
isMultiCanvas: true,
|
|
15056
|
+
isSecondary: true,
|
|
15057
|
+
targetId: primaryCanvas
|
|
15058
|
+
}
|
|
15059
|
+
}));
|
|
14578
15060
|
} else if (!wantsGL && !state.internal.actualRenderer) {
|
|
14579
15061
|
renderer = await resolveRenderer(rendererConfig, defaultGPUProps, WebGPURenderer);
|
|
14580
15062
|
if (!renderer.hasInitialized?.()) {
|
|
@@ -14583,14 +15065,27 @@ function createRoot(canvas) {
|
|
|
14583
15065
|
const backend = renderer.backend;
|
|
14584
15066
|
const isWebGPUBackend = backend && "isWebGPUBackend" in backend;
|
|
14585
15067
|
state.internal.actualRenderer = renderer;
|
|
14586
|
-
state.set({ webGPUSupported: isWebGPUBackend, renderer });
|
|
15068
|
+
state.set({ webGPUSupported: isWebGPUBackend, renderer, primaryStore: store });
|
|
15069
|
+
if (canvasId && !state.internal.isSecondary) {
|
|
15070
|
+
const canvasTarget = new CanvasTarget(canvas);
|
|
15071
|
+
const unregisterPrimary = registerPrimary(canvasId, renderer, store);
|
|
15072
|
+
state.set((prev) => ({
|
|
15073
|
+
internal: {
|
|
15074
|
+
...prev.internal,
|
|
15075
|
+
canvasTarget,
|
|
15076
|
+
unregisterPrimary
|
|
15077
|
+
}
|
|
15078
|
+
}));
|
|
15079
|
+
}
|
|
14587
15080
|
}
|
|
14588
15081
|
let raycaster = state.raycaster;
|
|
14589
15082
|
if (!raycaster) state.set({ raycaster: raycaster = new Raycaster() });
|
|
14590
15083
|
const { params, ...options } = raycastOptions || {};
|
|
14591
15084
|
if (!is.equ(options, raycaster, shallowLoose)) applyProps(raycaster, { ...options });
|
|
14592
|
-
if (!is.equ(params, raycaster.params, shallowLoose))
|
|
15085
|
+
if (!is.equ(params, raycaster.params, shallowLoose)) {
|
|
14593
15086
|
applyProps(raycaster, { params: { ...raycaster.params, ...params } });
|
|
15087
|
+
}
|
|
15088
|
+
let tempCamera = state.camera;
|
|
14594
15089
|
if (!state.camera || state.camera === lastCamera && !is.equ(lastCamera, cameraOptions, shallowLoose)) {
|
|
14595
15090
|
lastCamera = cameraOptions;
|
|
14596
15091
|
const isCamera = cameraOptions?.isCamera;
|
|
@@ -14610,6 +15105,7 @@ function createRoot(canvas) {
|
|
|
14610
15105
|
if (!state.camera && !cameraOptions?.rotation) camera.lookAt(0, 0, 0);
|
|
14611
15106
|
}
|
|
14612
15107
|
state.set({ camera });
|
|
15108
|
+
tempCamera = camera;
|
|
14613
15109
|
raycaster.camera = camera;
|
|
14614
15110
|
}
|
|
14615
15111
|
if (!state.scene) {
|
|
@@ -14627,7 +15123,7 @@ function createRoot(canvas) {
|
|
|
14627
15123
|
rootScene: scene,
|
|
14628
15124
|
internal: { ...prev.internal, container: scene }
|
|
14629
15125
|
}));
|
|
14630
|
-
const camera =
|
|
15126
|
+
const camera = tempCamera;
|
|
14631
15127
|
if (camera && !camera.parent) scene.add(camera);
|
|
14632
15128
|
}
|
|
14633
15129
|
if (events && !state.events.handlers) {
|
|
@@ -14641,9 +15137,17 @@ function createRoot(canvas) {
|
|
|
14641
15137
|
wasEnabled = enabled;
|
|
14642
15138
|
});
|
|
14643
15139
|
}
|
|
15140
|
+
if (_sizeProps !== void 0) {
|
|
15141
|
+
state.set({ _sizeProps });
|
|
15142
|
+
}
|
|
15143
|
+
if (forceEven !== void 0 && state.internal.forceEven !== forceEven) {
|
|
15144
|
+
state.set((prev) => ({ internal: { ...prev.internal, forceEven } }));
|
|
15145
|
+
}
|
|
14644
15146
|
const size = computeInitialSize(canvas, propsSize);
|
|
14645
|
-
if (!is.equ(size, state.size, shallowLoose)) {
|
|
15147
|
+
if (!state._sizeImperative && !is.equ(size, state.size, shallowLoose)) {
|
|
15148
|
+
const wasImperative = state._sizeImperative;
|
|
14646
15149
|
state.setSize(size.width, size.height, size.top, size.left);
|
|
15150
|
+
if (!wasImperative) state.set({ _sizeImperative: false });
|
|
14647
15151
|
}
|
|
14648
15152
|
if (dpr !== void 0 && !is.equ(dpr, lastConfiguredProps.dpr, shallowLoose)) {
|
|
14649
15153
|
state.setDpr(dpr);
|
|
@@ -14668,7 +15172,7 @@ function createRoot(canvas) {
|
|
|
14668
15172
|
const handleXRFrame = (timestamp, frame) => {
|
|
14669
15173
|
const state2 = store.getState();
|
|
14670
15174
|
if (state2.frameloop === "never") return;
|
|
14671
|
-
advance(timestamp
|
|
15175
|
+
advance(timestamp);
|
|
14672
15176
|
};
|
|
14673
15177
|
const actualRenderer = state.internal.actualRenderer;
|
|
14674
15178
|
const handleSessionChange = () => {
|
|
@@ -14680,16 +15184,16 @@ function createRoot(canvas) {
|
|
|
14680
15184
|
};
|
|
14681
15185
|
const xr = {
|
|
14682
15186
|
connect() {
|
|
14683
|
-
const { gl, renderer: renderer2
|
|
14684
|
-
const
|
|
14685
|
-
|
|
14686
|
-
|
|
15187
|
+
const { gl, renderer: renderer2 } = store.getState();
|
|
15188
|
+
const xrManager = (renderer2 || gl).xr;
|
|
15189
|
+
xrManager.addEventListener("sessionstart", handleSessionChange);
|
|
15190
|
+
xrManager.addEventListener("sessionend", handleSessionChange);
|
|
14687
15191
|
},
|
|
14688
15192
|
disconnect() {
|
|
14689
|
-
const { gl, renderer: renderer2
|
|
14690
|
-
const
|
|
14691
|
-
|
|
14692
|
-
|
|
15193
|
+
const { gl, renderer: renderer2 } = store.getState();
|
|
15194
|
+
const xrManager = (renderer2 || gl).xr;
|
|
15195
|
+
xrManager.removeEventListener("sessionstart", handleSessionChange);
|
|
15196
|
+
xrManager.removeEventListener("sessionend", handleSessionChange);
|
|
14693
15197
|
}
|
|
14694
15198
|
};
|
|
14695
15199
|
if (typeof renderer.xr?.addEventListener === "function") xr.connect();
|
|
@@ -14713,43 +15217,21 @@ function createRoot(canvas) {
|
|
|
14713
15217
|
} else if (is.obj(shadows)) {
|
|
14714
15218
|
Object.assign(renderer.shadowMap, shadows);
|
|
14715
15219
|
}
|
|
14716
|
-
if (oldEnabled !== renderer.shadowMap.enabled || oldType !== renderer.shadowMap.type)
|
|
15220
|
+
if (oldEnabled !== renderer.shadowMap.enabled || oldType !== renderer.shadowMap.type) {
|
|
14717
15221
|
renderer.shadowMap.needsUpdate = true;
|
|
14718
|
-
}
|
|
14719
|
-
{
|
|
14720
|
-
const legacyChanged = legacy !== lastConfiguredProps.legacy;
|
|
14721
|
-
const linearChanged = linear !== lastConfiguredProps.linear;
|
|
14722
|
-
const flatChanged = flat !== lastConfiguredProps.flat;
|
|
14723
|
-
if (legacyChanged) {
|
|
14724
|
-
if (legacy)
|
|
14725
|
-
notifyDepreciated({
|
|
14726
|
-
heading: "Legacy Color Management",
|
|
14727
|
-
body: "Legacy color management is deprecated and will be removed in a future version.",
|
|
14728
|
-
link: "https://docs.pmnd.rs/react-three-fiber/api/hooks#useframe"
|
|
14729
|
-
});
|
|
14730
|
-
}
|
|
14731
|
-
if (legacyChanged) {
|
|
14732
|
-
ColorManagement.enabled = !legacy;
|
|
14733
|
-
lastConfiguredProps.legacy = legacy;
|
|
14734
15222
|
}
|
|
14735
|
-
|
|
14736
|
-
|
|
14737
|
-
|
|
14738
|
-
|
|
14739
|
-
if (!configured || flatChanged) {
|
|
14740
|
-
renderer.toneMapping = flat ? NoToneMapping : ACESFilmicToneMapping;
|
|
14741
|
-
lastConfiguredProps.flat = flat;
|
|
14742
|
-
}
|
|
14743
|
-
if (legacyChanged && state.legacy !== legacy) state.set(() => ({ legacy }));
|
|
14744
|
-
if (linearChanged && state.linear !== linear) state.set(() => ({ linear }));
|
|
14745
|
-
if (flatChanged && state.flat !== flat) state.set(() => ({ flat }));
|
|
15223
|
+
}
|
|
15224
|
+
if (!configured) {
|
|
15225
|
+
renderer.outputColorSpace = SRGBColorSpace;
|
|
15226
|
+
renderer.toneMapping = ACESFilmicToneMapping;
|
|
14746
15227
|
}
|
|
14747
15228
|
if (textureColorSpace !== lastConfiguredProps.textureColorSpace) {
|
|
14748
15229
|
if (state.textureColorSpace !== textureColorSpace) state.set(() => ({ textureColorSpace }));
|
|
14749
15230
|
lastConfiguredProps.textureColorSpace = textureColorSpace;
|
|
14750
15231
|
}
|
|
14751
|
-
if (glConfig && !is.fun(glConfig) && !isRenderer(glConfig) && !is.equ(glConfig, renderer, shallowLoose))
|
|
15232
|
+
if (glConfig && !is.fun(glConfig) && !isRenderer(glConfig) && !is.equ(glConfig, renderer, shallowLoose)) {
|
|
14752
15233
|
applyProps(renderer, glConfig);
|
|
15234
|
+
}
|
|
14753
15235
|
if (rendererConfig && !is.fun(rendererConfig) && !isRenderer(rendererConfig) && state.renderer) {
|
|
14754
15236
|
const currentRenderer = state.renderer;
|
|
14755
15237
|
if (!is.equ(rendererConfig, currentRenderer, shallowLoose)) {
|
|
@@ -14759,11 +15241,26 @@ function createRoot(canvas) {
|
|
|
14759
15241
|
const scheduler = getScheduler();
|
|
14760
15242
|
const rootId = state.internal.rootId;
|
|
14761
15243
|
if (!rootId) {
|
|
14762
|
-
const newRootId = scheduler.generateRootId();
|
|
15244
|
+
const newRootId = canvasId || scheduler.generateRootId();
|
|
14763
15245
|
const unregisterRoot = scheduler.registerRoot(newRootId, {
|
|
14764
15246
|
getState: () => store.getState(),
|
|
14765
15247
|
onError: (err) => store.getState().setError(err)
|
|
14766
15248
|
});
|
|
15249
|
+
const unregisterCanvasTarget = scheduler.register(
|
|
15250
|
+
() => {
|
|
15251
|
+
const state2 = store.getState();
|
|
15252
|
+
if (state2.internal.isMultiCanvas && state2.internal.canvasTarget) {
|
|
15253
|
+
const renderer2 = state2.internal.actualRenderer;
|
|
15254
|
+
renderer2.setCanvasTarget(state2.internal.canvasTarget);
|
|
15255
|
+
}
|
|
15256
|
+
},
|
|
15257
|
+
{
|
|
15258
|
+
id: `${newRootId}_canvasTarget`,
|
|
15259
|
+
rootId: newRootId,
|
|
15260
|
+
phase: "start",
|
|
15261
|
+
system: true
|
|
15262
|
+
}
|
|
15263
|
+
);
|
|
14767
15264
|
const unregisterFrustum = scheduler.register(
|
|
14768
15265
|
() => {
|
|
14769
15266
|
const state2 = store.getState();
|
|
@@ -14805,11 +15302,15 @@ function createRoot(canvas) {
|
|
|
14805
15302
|
}
|
|
14806
15303
|
},
|
|
14807
15304
|
{
|
|
14808
|
-
|
|
15305
|
+
// Use canvas ID directly as job ID if available, otherwise use generated rootId
|
|
15306
|
+
id: canvasId || `${newRootId}_render`,
|
|
14809
15307
|
rootId: newRootId,
|
|
14810
15308
|
phase: "render",
|
|
14811
|
-
system: true
|
|
15309
|
+
system: true,
|
|
14812
15310
|
// Internal flag: this is a system job, not user-controlled
|
|
15311
|
+
// Apply scheduler config for render ordering and rate limiting
|
|
15312
|
+
...schedulerConfig?.after && { after: schedulerConfig.after },
|
|
15313
|
+
...schedulerConfig?.fps && { fps: schedulerConfig.fps }
|
|
14813
15314
|
}
|
|
14814
15315
|
);
|
|
14815
15316
|
state.set((state2) => ({
|
|
@@ -14818,6 +15319,7 @@ function createRoot(canvas) {
|
|
|
14818
15319
|
rootId: newRootId,
|
|
14819
15320
|
unregisterRoot: () => {
|
|
14820
15321
|
unregisterRoot();
|
|
15322
|
+
unregisterCanvasTarget();
|
|
14821
15323
|
unregisterFrustum();
|
|
14822
15324
|
unregisterVisibility();
|
|
14823
15325
|
unregisterRender();
|
|
@@ -14876,15 +15378,24 @@ function unmountComponentAtNode(canvas, callback) {
|
|
|
14876
15378
|
const renderer = state.internal.actualRenderer;
|
|
14877
15379
|
const unregisterRoot = state.internal.unregisterRoot;
|
|
14878
15380
|
if (unregisterRoot) unregisterRoot();
|
|
15381
|
+
const unregisterPrimary = state.internal.unregisterPrimary;
|
|
15382
|
+
if (unregisterPrimary) unregisterPrimary();
|
|
15383
|
+
const canvasTarget = state.internal.canvasTarget;
|
|
15384
|
+
if (canvasTarget?.dispose) canvasTarget.dispose();
|
|
14879
15385
|
state.events.disconnect?.();
|
|
14880
15386
|
cleanupHelperGroup(root.store);
|
|
14881
|
-
renderer
|
|
14882
|
-
|
|
14883
|
-
|
|
15387
|
+
if (state.isLegacy && renderer) {
|
|
15388
|
+
;
|
|
15389
|
+
renderer.renderLists?.dispose?.();
|
|
15390
|
+
renderer.forceContextLoss?.();
|
|
15391
|
+
}
|
|
15392
|
+
if (!state.internal.isSecondary) {
|
|
15393
|
+
if (renderer?.xr) state.xr.disconnect();
|
|
15394
|
+
}
|
|
14884
15395
|
dispose(state.scene);
|
|
14885
15396
|
_roots.delete(canvas);
|
|
14886
15397
|
if (callback) callback(canvas);
|
|
14887
|
-
} catch
|
|
15398
|
+
} catch {
|
|
14888
15399
|
}
|
|
14889
15400
|
}, 500);
|
|
14890
15401
|
}
|
|
@@ -14892,36 +15403,34 @@ function unmountComponentAtNode(canvas, callback) {
|
|
|
14892
15403
|
}
|
|
14893
15404
|
}
|
|
14894
15405
|
function createPortal(children, container, state) {
|
|
14895
|
-
return /* @__PURE__ */ jsx(
|
|
15406
|
+
return /* @__PURE__ */ jsx(Portal, { children, container, state });
|
|
14896
15407
|
}
|
|
14897
|
-
function
|
|
15408
|
+
function Portal({ children, container, state }) {
|
|
14898
15409
|
const isRef = useCallback((obj) => obj && "current" in obj, []);
|
|
14899
|
-
const [resolvedContainer,
|
|
15410
|
+
const [resolvedContainer, _setResolvedContainer] = useState(() => {
|
|
14900
15411
|
if (isRef(container)) return container.current ?? null;
|
|
14901
15412
|
return container;
|
|
14902
15413
|
});
|
|
15414
|
+
const setResolvedContainer = useCallback(
|
|
15415
|
+
(newContainer) => {
|
|
15416
|
+
if (!newContainer || newContainer === resolvedContainer) return;
|
|
15417
|
+
_setResolvedContainer(isRef(newContainer) ? newContainer.current : newContainer);
|
|
15418
|
+
},
|
|
15419
|
+
[resolvedContainer, _setResolvedContainer, isRef]
|
|
15420
|
+
);
|
|
14903
15421
|
useMemo(() => {
|
|
14904
|
-
if (isRef(container)) {
|
|
14905
|
-
|
|
14906
|
-
|
|
14907
|
-
|
|
14908
|
-
const updated = container.current;
|
|
14909
|
-
if (updated && updated !== resolvedContainer) {
|
|
14910
|
-
setResolvedContainer(updated);
|
|
14911
|
-
}
|
|
14912
|
-
});
|
|
14913
|
-
} else if (current !== resolvedContainer) {
|
|
14914
|
-
setResolvedContainer(current);
|
|
14915
|
-
}
|
|
14916
|
-
} else if (container !== resolvedContainer) {
|
|
14917
|
-
setResolvedContainer(container);
|
|
15422
|
+
if (isRef(container) && !container.current) {
|
|
15423
|
+
return queueMicrotask(() => {
|
|
15424
|
+
setResolvedContainer(container.current);
|
|
15425
|
+
});
|
|
14918
15426
|
}
|
|
14919
|
-
|
|
15427
|
+
setResolvedContainer(container);
|
|
15428
|
+
}, [container, isRef, setResolvedContainer]);
|
|
14920
15429
|
if (!resolvedContainer) return /* @__PURE__ */ jsx(Fragment, {});
|
|
14921
15430
|
const portalKey = resolvedContainer.uuid ?? `portal-${resolvedContainer.id ?? "unknown"}`;
|
|
14922
|
-
return /* @__PURE__ */ jsx(
|
|
15431
|
+
return /* @__PURE__ */ jsx(PortalInner, { children, container: resolvedContainer, state }, portalKey);
|
|
14923
15432
|
}
|
|
14924
|
-
function
|
|
15433
|
+
function PortalInner({ state = {}, children, container }) {
|
|
14925
15434
|
const { events, size, injectScene = true, ...rest } = state;
|
|
14926
15435
|
const previousRoot = useStore();
|
|
14927
15436
|
const [raycaster] = useState(() => new Raycaster());
|
|
@@ -14942,11 +15451,12 @@ function Portal({ state = {}, children, container }) {
|
|
|
14942
15451
|
};
|
|
14943
15452
|
}, [portalScene, container, injectScene]);
|
|
14944
15453
|
const inject = useMutableCallback((rootState, injectState) => {
|
|
15454
|
+
const resolvedSize = { ...rootState.size, ...injectState.size, ...size };
|
|
14945
15455
|
let viewport = void 0;
|
|
14946
|
-
if (injectState.camera && size) {
|
|
15456
|
+
if (injectState.camera && (size || injectState.size)) {
|
|
14947
15457
|
const camera = injectState.camera;
|
|
14948
|
-
viewport = rootState.viewport.getCurrentViewport(camera, new Vector3(),
|
|
14949
|
-
if (camera !== rootState.camera) updateCamera(camera,
|
|
15458
|
+
viewport = rootState.viewport.getCurrentViewport(camera, new Vector3(), resolvedSize);
|
|
15459
|
+
if (camera !== rootState.camera) updateCamera(camera, resolvedSize);
|
|
14950
15460
|
}
|
|
14951
15461
|
return {
|
|
14952
15462
|
// The intersect consists of the previous root state
|
|
@@ -14963,7 +15473,7 @@ function Portal({ state = {}, children, container }) {
|
|
|
14963
15473
|
previousRoot,
|
|
14964
15474
|
// Events, size and viewport can be overridden by the inject layer
|
|
14965
15475
|
events: { ...rootState.events, ...injectState.events, ...events },
|
|
14966
|
-
size:
|
|
15476
|
+
size: resolvedSize,
|
|
14967
15477
|
viewport: { ...rootState.viewport, ...viewport },
|
|
14968
15478
|
// Layers are allowed to override events
|
|
14969
15479
|
setEvents: (events2) => injectState.set((state2) => ({ ...state2, events: { ...state2.events, ...events2 } })),
|
|
@@ -14997,15 +15507,13 @@ function CanvasImpl({
|
|
|
14997
15507
|
fallback,
|
|
14998
15508
|
resize,
|
|
14999
15509
|
style,
|
|
15510
|
+
id,
|
|
15000
15511
|
gl,
|
|
15001
|
-
renderer,
|
|
15512
|
+
renderer: rendererProp,
|
|
15002
15513
|
events = createPointerEvents,
|
|
15003
15514
|
eventSource,
|
|
15004
15515
|
eventPrefix,
|
|
15005
15516
|
shadows,
|
|
15006
|
-
linear,
|
|
15007
|
-
flat,
|
|
15008
|
-
legacy,
|
|
15009
15517
|
orthographic,
|
|
15010
15518
|
frameloop,
|
|
15011
15519
|
dpr,
|
|
@@ -15017,10 +15525,46 @@ function CanvasImpl({
|
|
|
15017
15525
|
onDragOverMissed,
|
|
15018
15526
|
onDropMissed,
|
|
15019
15527
|
onCreated,
|
|
15528
|
+
hmr,
|
|
15529
|
+
width,
|
|
15530
|
+
height,
|
|
15531
|
+
background,
|
|
15532
|
+
forceEven,
|
|
15020
15533
|
...props
|
|
15021
15534
|
}) {
|
|
15535
|
+
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 };
|
|
15536
|
+
const renderer = Object.keys(rendererConfig).length > 0 ? rendererConfig : rendererProp;
|
|
15022
15537
|
React.useMemo(() => extend(THREE), []);
|
|
15023
15538
|
const Bridge = useBridge();
|
|
15539
|
+
const backgroundProps = React.useMemo(() => {
|
|
15540
|
+
if (!background) return null;
|
|
15541
|
+
if (typeof background === "object" && !background.isColor) {
|
|
15542
|
+
const { backgroundMap, envMap, files, preset, ...rest } = background;
|
|
15543
|
+
return {
|
|
15544
|
+
...rest,
|
|
15545
|
+
preset,
|
|
15546
|
+
files: envMap || files,
|
|
15547
|
+
backgroundFiles: backgroundMap,
|
|
15548
|
+
background: true
|
|
15549
|
+
};
|
|
15550
|
+
}
|
|
15551
|
+
if (typeof background === "number") {
|
|
15552
|
+
return { color: background, background: true };
|
|
15553
|
+
}
|
|
15554
|
+
if (typeof background === "string") {
|
|
15555
|
+
if (background in presetsObj) {
|
|
15556
|
+
return { preset: background, background: true };
|
|
15557
|
+
}
|
|
15558
|
+
if (/^(https?:\/\/|\/|\.\/|\.\.\/)|\\.(hdr|exr|jpg|jpeg|png|webp|gif)$/i.test(background)) {
|
|
15559
|
+
return { files: background, background: true };
|
|
15560
|
+
}
|
|
15561
|
+
return { color: background, background: true };
|
|
15562
|
+
}
|
|
15563
|
+
if (background.isColor) {
|
|
15564
|
+
return { color: background, background: true };
|
|
15565
|
+
}
|
|
15566
|
+
return null;
|
|
15567
|
+
}, [background]);
|
|
15024
15568
|
const hasInitialSizeRef = React.useRef(false);
|
|
15025
15569
|
const measureConfig = React.useMemo(() => {
|
|
15026
15570
|
if (!hasInitialSizeRef.current) {
|
|
@@ -15037,7 +15581,21 @@ function CanvasImpl({
|
|
|
15037
15581
|
};
|
|
15038
15582
|
}, [resize, hasInitialSizeRef.current]);
|
|
15039
15583
|
const [containerRef, containerRect] = useMeasure(measureConfig);
|
|
15040
|
-
|
|
15584
|
+
const effectiveSize = React.useMemo(() => {
|
|
15585
|
+
let w = width ?? containerRect.width;
|
|
15586
|
+
let h = height ?? containerRect.height;
|
|
15587
|
+
if (forceEven) {
|
|
15588
|
+
w = Math.ceil(w / 2) * 2;
|
|
15589
|
+
h = Math.ceil(h / 2) * 2;
|
|
15590
|
+
}
|
|
15591
|
+
return {
|
|
15592
|
+
width: w,
|
|
15593
|
+
height: h,
|
|
15594
|
+
top: containerRect.top,
|
|
15595
|
+
left: containerRect.left
|
|
15596
|
+
};
|
|
15597
|
+
}, [width, height, containerRect, forceEven]);
|
|
15598
|
+
if (!hasInitialSizeRef.current && effectiveSize.width > 0 && effectiveSize.height > 0) {
|
|
15041
15599
|
hasInitialSizeRef.current = true;
|
|
15042
15600
|
}
|
|
15043
15601
|
const canvasRef = React.useRef(null);
|
|
@@ -15056,7 +15614,7 @@ function CanvasImpl({
|
|
|
15056
15614
|
useIsomorphicLayoutEffect(() => {
|
|
15057
15615
|
effectActiveRef.current = true;
|
|
15058
15616
|
const canvas = canvasRef.current;
|
|
15059
|
-
if (
|
|
15617
|
+
if (effectiveSize.width > 0 && effectiveSize.height > 0 && canvas) {
|
|
15060
15618
|
if (!root.current) {
|
|
15061
15619
|
root.current = createRoot(canvas);
|
|
15062
15620
|
notifyAlpha({
|
|
@@ -15076,21 +15634,24 @@ function CanvasImpl({
|
|
|
15076
15634
|
async function run() {
|
|
15077
15635
|
if (!effectActiveRef.current || !root.current) return;
|
|
15078
15636
|
await root.current.configure({
|
|
15637
|
+
id,
|
|
15638
|
+
primaryCanvas,
|
|
15639
|
+
scheduler,
|
|
15079
15640
|
gl,
|
|
15080
15641
|
renderer,
|
|
15081
15642
|
scene,
|
|
15082
15643
|
events,
|
|
15083
15644
|
shadows,
|
|
15084
|
-
linear,
|
|
15085
|
-
flat,
|
|
15086
|
-
legacy,
|
|
15087
15645
|
orthographic,
|
|
15088
15646
|
frameloop,
|
|
15089
15647
|
dpr,
|
|
15090
15648
|
performance,
|
|
15091
15649
|
raycaster,
|
|
15092
15650
|
camera,
|
|
15093
|
-
size:
|
|
15651
|
+
size: effectiveSize,
|
|
15652
|
+
// Store size props for reset functionality
|
|
15653
|
+
_sizeProps: width !== void 0 || height !== void 0 ? { width, height } : null,
|
|
15654
|
+
forceEven,
|
|
15094
15655
|
// Pass mutable reference to onPointerMissed so it's free to update
|
|
15095
15656
|
onPointerMissed: (...args) => handlePointerMissed.current?.(...args),
|
|
15096
15657
|
onDragOverMissed: (...args) => handleDragOverMissed.current?.(...args),
|
|
@@ -15114,7 +15675,10 @@ function CanvasImpl({
|
|
|
15114
15675
|
});
|
|
15115
15676
|
if (!effectActiveRef.current || !root.current) return;
|
|
15116
15677
|
root.current.render(
|
|
15117
|
-
/* @__PURE__ */ jsx(Bridge, { children: /* @__PURE__ */ jsx(ErrorBoundary, { set: setError, children: /* @__PURE__ */
|
|
15678
|
+
/* @__PURE__ */ jsx(Bridge, { children: /* @__PURE__ */ jsx(ErrorBoundary, { set: setError, children: /* @__PURE__ */ jsxs(React.Suspense, { fallback: /* @__PURE__ */ jsx(Block, { set: setBlock }), children: [
|
|
15679
|
+
backgroundProps && /* @__PURE__ */ jsx(Environment, { ...backgroundProps }),
|
|
15680
|
+
children ?? null
|
|
15681
|
+
] }) }) })
|
|
15118
15682
|
);
|
|
15119
15683
|
}
|
|
15120
15684
|
run();
|
|
@@ -15136,6 +15700,35 @@ function CanvasImpl({
|
|
|
15136
15700
|
};
|
|
15137
15701
|
}
|
|
15138
15702
|
}, []);
|
|
15703
|
+
React.useEffect(() => {
|
|
15704
|
+
if (hmr === false) return;
|
|
15705
|
+
const canvas = canvasRef.current;
|
|
15706
|
+
if (!canvas) return;
|
|
15707
|
+
const handleHMR = () => {
|
|
15708
|
+
queueMicrotask(() => {
|
|
15709
|
+
const rootEntry = _roots.get(canvas);
|
|
15710
|
+
if (rootEntry?.store) {
|
|
15711
|
+
rootEntry.store.setState((state) => ({
|
|
15712
|
+
nodes: {},
|
|
15713
|
+
uniforms: {},
|
|
15714
|
+
_hmrVersion: state._hmrVersion + 1
|
|
15715
|
+
}));
|
|
15716
|
+
}
|
|
15717
|
+
});
|
|
15718
|
+
};
|
|
15719
|
+
if (typeof import.meta !== "undefined" && import.meta.hot) {
|
|
15720
|
+
const hot = import.meta.hot;
|
|
15721
|
+
hot.on("vite:afterUpdate", handleHMR);
|
|
15722
|
+
return () => hot.dispose?.(() => {
|
|
15723
|
+
});
|
|
15724
|
+
}
|
|
15725
|
+
if (typeof module !== "undefined" && module.hot) {
|
|
15726
|
+
const hot = module.hot;
|
|
15727
|
+
hot.addStatusHandler((status) => {
|
|
15728
|
+
if (status === "idle") handleHMR();
|
|
15729
|
+
});
|
|
15730
|
+
}
|
|
15731
|
+
}, [hmr]);
|
|
15139
15732
|
const pointerEvents = eventSource ? "none" : "auto";
|
|
15140
15733
|
return /* @__PURE__ */ jsx(
|
|
15141
15734
|
"div",
|
|
@@ -15150,7 +15743,7 @@ function CanvasImpl({
|
|
|
15150
15743
|
...style
|
|
15151
15744
|
},
|
|
15152
15745
|
...props,
|
|
15153
|
-
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 }) })
|
|
15746
|
+
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 }) })
|
|
15154
15747
|
}
|
|
15155
15748
|
);
|
|
15156
15749
|
}
|
|
@@ -15160,4 +15753,4 @@ function Canvas(props) {
|
|
|
15160
15753
|
|
|
15161
15754
|
extend(THREE);
|
|
15162
15755
|
|
|
15163
|
-
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 };
|
|
15756
|
+
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 };
|