@react-three/fiber 10.0.0-alpha.2 → 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 +1122 -558
- package/dist/index.d.cts +2001 -1285
- package/dist/index.d.mts +2001 -1285
- package/dist/index.d.ts +2001 -1285
- package/dist/index.mjs +1107 -562
- package/dist/legacy.cjs +1093 -547
- package/dist/legacy.d.cts +2002 -1286
- package/dist/legacy.d.mts +2002 -1286
- package/dist/legacy.d.ts +2002 -1286
- package/dist/legacy.mjs +1078 -551
- package/dist/webgpu/index.cjs +1176 -548
- package/dist/webgpu/index.d.cts +2097 -1300
- package/dist/webgpu/index.d.mts +2097 -1300
- package/dist/webgpu/index.d.ts +2097 -1300
- package/dist/webgpu/index.mjs +1161 -552
- package/package.json +3 -1
- package/readme.md +244 -318
package/dist/index.cjs
CHANGED
|
@@ -7,6 +7,12 @@ const jsxRuntime = require('react/jsx-runtime');
|
|
|
7
7
|
const React = require('react');
|
|
8
8
|
const useMeasure = require('react-use-measure');
|
|
9
9
|
const itsFine = require('its-fine');
|
|
10
|
+
const fiber = require('@react-three/fiber');
|
|
11
|
+
const GroundedSkybox_js = require('three/examples/jsm/objects/GroundedSkybox.js');
|
|
12
|
+
const HDRLoader_js = require('three/examples/jsm/loaders/HDRLoader.js');
|
|
13
|
+
const EXRLoader_js = require('three/examples/jsm/loaders/EXRLoader.js');
|
|
14
|
+
const UltraHDRLoader_js = require('three/examples/jsm/loaders/UltraHDRLoader.js');
|
|
15
|
+
const gainmapJs = require('@monogrid/gainmap-js');
|
|
10
16
|
const Tb = require('scheduler');
|
|
11
17
|
const traditional = require('zustand/traditional');
|
|
12
18
|
const suspendReact = require('suspend-react');
|
|
@@ -57,6 +63,374 @@ const THREE = /*#__PURE__*/_mergeNamespaces({
|
|
|
57
63
|
WebGLRenderer: three.WebGLRenderer
|
|
58
64
|
}, [webgpu__namespace]);
|
|
59
65
|
|
|
66
|
+
const primaryRegistry = /* @__PURE__ */ new Map();
|
|
67
|
+
const pendingSubscribers = /* @__PURE__ */ new Map();
|
|
68
|
+
function registerPrimary(id, renderer, store) {
|
|
69
|
+
if (primaryRegistry.has(id)) {
|
|
70
|
+
console.warn(`Canvas with id="${id}" already registered. Overwriting.`);
|
|
71
|
+
}
|
|
72
|
+
const entry = { renderer, store };
|
|
73
|
+
primaryRegistry.set(id, entry);
|
|
74
|
+
const subscribers = pendingSubscribers.get(id);
|
|
75
|
+
if (subscribers) {
|
|
76
|
+
subscribers.forEach((callback) => callback(entry));
|
|
77
|
+
pendingSubscribers.delete(id);
|
|
78
|
+
}
|
|
79
|
+
return () => {
|
|
80
|
+
const currentEntry = primaryRegistry.get(id);
|
|
81
|
+
if (currentEntry?.renderer === renderer) {
|
|
82
|
+
primaryRegistry.delete(id);
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
function getPrimary(id) {
|
|
87
|
+
return primaryRegistry.get(id);
|
|
88
|
+
}
|
|
89
|
+
function waitForPrimary(id, timeout = 5e3) {
|
|
90
|
+
const existing = primaryRegistry.get(id);
|
|
91
|
+
if (existing) {
|
|
92
|
+
return Promise.resolve(existing);
|
|
93
|
+
}
|
|
94
|
+
return new Promise((resolve, reject) => {
|
|
95
|
+
const timeoutId = setTimeout(() => {
|
|
96
|
+
const subscribers = pendingSubscribers.get(id);
|
|
97
|
+
if (subscribers) {
|
|
98
|
+
const index = subscribers.indexOf(callback);
|
|
99
|
+
if (index !== -1) subscribers.splice(index, 1);
|
|
100
|
+
if (subscribers.length === 0) pendingSubscribers.delete(id);
|
|
101
|
+
}
|
|
102
|
+
reject(new Error(`Timeout waiting for canvas with id="${id}". Make sure a <Canvas id="${id}"> is mounted.`));
|
|
103
|
+
}, timeout);
|
|
104
|
+
const callback = (entry) => {
|
|
105
|
+
clearTimeout(timeoutId);
|
|
106
|
+
resolve(entry);
|
|
107
|
+
};
|
|
108
|
+
if (!pendingSubscribers.has(id)) {
|
|
109
|
+
pendingSubscribers.set(id, []);
|
|
110
|
+
}
|
|
111
|
+
pendingSubscribers.get(id).push(callback);
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
function hasPrimary(id) {
|
|
115
|
+
return primaryRegistry.has(id);
|
|
116
|
+
}
|
|
117
|
+
function unregisterPrimary(id) {
|
|
118
|
+
primaryRegistry.delete(id);
|
|
119
|
+
}
|
|
120
|
+
function getPrimaryIds() {
|
|
121
|
+
return Array.from(primaryRegistry.keys());
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const presetsObj = {
|
|
125
|
+
apartment: "lebombo_1k.hdr",
|
|
126
|
+
city: "potsdamer_platz_1k.hdr",
|
|
127
|
+
dawn: "kiara_1_dawn_1k.hdr",
|
|
128
|
+
forest: "forest_slope_1k.hdr",
|
|
129
|
+
lobby: "st_fagans_interior_1k.hdr",
|
|
130
|
+
night: "dikhololo_night_1k.hdr",
|
|
131
|
+
park: "rooitou_park_1k.hdr",
|
|
132
|
+
studio: "studio_small_03_1k.hdr",
|
|
133
|
+
sunset: "venice_sunset_1k.hdr",
|
|
134
|
+
warehouse: "empty_warehouse_01_1k.hdr"
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
const CUBEMAP_ROOT = "https://raw.githack.com/pmndrs/drei-assets/456060a26bbeb8fdf79326f224b6d99b8bcce736/hdri/";
|
|
138
|
+
const isArray = (arr) => Array.isArray(arr);
|
|
139
|
+
const defaultFiles = ["/px.png", "/nx.png", "/py.png", "/ny.png", "/pz.png", "/nz.png"];
|
|
140
|
+
function useEnvironment({
|
|
141
|
+
files = defaultFiles,
|
|
142
|
+
path = "",
|
|
143
|
+
preset = void 0,
|
|
144
|
+
colorSpace = void 0,
|
|
145
|
+
extensions
|
|
146
|
+
} = {}) {
|
|
147
|
+
if (preset) {
|
|
148
|
+
validatePreset(preset);
|
|
149
|
+
files = presetsObj[preset];
|
|
150
|
+
path = CUBEMAP_ROOT;
|
|
151
|
+
}
|
|
152
|
+
const multiFile = isArray(files);
|
|
153
|
+
const { extension, isCubemap } = getExtension(files);
|
|
154
|
+
const loader = getLoader$1(extension);
|
|
155
|
+
if (!loader) throw new Error("useEnvironment: Unrecognized file extension: " + files);
|
|
156
|
+
const renderer = fiber.useThree((state) => state.renderer);
|
|
157
|
+
React.useLayoutEffect(() => {
|
|
158
|
+
if (extension !== "webp" && extension !== "jpg" && extension !== "jpeg") return;
|
|
159
|
+
function clearGainmapTexture() {
|
|
160
|
+
fiber.useLoader.clear(loader, multiFile ? [files] : files);
|
|
161
|
+
}
|
|
162
|
+
renderer.domElement.addEventListener("webglcontextlost", clearGainmapTexture, { once: true });
|
|
163
|
+
}, [files, renderer.domElement]);
|
|
164
|
+
const loaderResult = fiber.useLoader(
|
|
165
|
+
loader,
|
|
166
|
+
multiFile ? [files] : files,
|
|
167
|
+
(loader2) => {
|
|
168
|
+
if (extension === "webp" || extension === "jpg" || extension === "jpeg") {
|
|
169
|
+
loader2.setRenderer?.(renderer);
|
|
170
|
+
}
|
|
171
|
+
loader2.setPath?.(path);
|
|
172
|
+
if (extensions) extensions(loader2);
|
|
173
|
+
}
|
|
174
|
+
);
|
|
175
|
+
let texture = multiFile ? (
|
|
176
|
+
// @ts-ignore
|
|
177
|
+
loaderResult[0]
|
|
178
|
+
) : loaderResult;
|
|
179
|
+
if (extension === "jpg" || extension === "jpeg" || extension === "webp") {
|
|
180
|
+
texture = texture.renderTarget?.texture;
|
|
181
|
+
}
|
|
182
|
+
texture.mapping = isCubemap ? webgpu.CubeReflectionMapping : webgpu.EquirectangularReflectionMapping;
|
|
183
|
+
texture.colorSpace = colorSpace ?? (isCubemap ? "srgb" : "srgb-linear");
|
|
184
|
+
return texture;
|
|
185
|
+
}
|
|
186
|
+
const preloadDefaultOptions = {
|
|
187
|
+
files: defaultFiles,
|
|
188
|
+
path: "",
|
|
189
|
+
preset: void 0,
|
|
190
|
+
extensions: void 0
|
|
191
|
+
};
|
|
192
|
+
useEnvironment.preload = (preloadOptions) => {
|
|
193
|
+
const options = { ...preloadDefaultOptions, ...preloadOptions };
|
|
194
|
+
let { files, path = "" } = options;
|
|
195
|
+
const { preset, extensions } = options;
|
|
196
|
+
if (preset) {
|
|
197
|
+
validatePreset(preset);
|
|
198
|
+
files = presetsObj[preset];
|
|
199
|
+
path = CUBEMAP_ROOT;
|
|
200
|
+
}
|
|
201
|
+
const { extension } = getExtension(files);
|
|
202
|
+
if (extension === "webp" || extension === "jpg" || extension === "jpeg") {
|
|
203
|
+
throw new Error("useEnvironment: Preloading gainmaps is not supported");
|
|
204
|
+
}
|
|
205
|
+
const loader = getLoader$1(extension);
|
|
206
|
+
if (!loader) throw new Error("useEnvironment: Unrecognized file extension: " + files);
|
|
207
|
+
fiber.useLoader.preload(loader, isArray(files) ? [files] : files, (loader2) => {
|
|
208
|
+
loader2.setPath?.(path);
|
|
209
|
+
if (extensions) extensions(loader2);
|
|
210
|
+
});
|
|
211
|
+
};
|
|
212
|
+
const clearDefaultOptins = {
|
|
213
|
+
files: defaultFiles,
|
|
214
|
+
preset: void 0
|
|
215
|
+
};
|
|
216
|
+
useEnvironment.clear = (clearOptions) => {
|
|
217
|
+
const options = { ...clearDefaultOptins, ...clearOptions };
|
|
218
|
+
let { files } = options;
|
|
219
|
+
const { preset } = options;
|
|
220
|
+
if (preset) {
|
|
221
|
+
validatePreset(preset);
|
|
222
|
+
files = presetsObj[preset];
|
|
223
|
+
}
|
|
224
|
+
const { extension } = getExtension(files);
|
|
225
|
+
const loader = getLoader$1(extension);
|
|
226
|
+
if (!loader) throw new Error("useEnvironment: Unrecognized file extension: " + files);
|
|
227
|
+
fiber.useLoader.clear(loader, isArray(files) ? [files] : files);
|
|
228
|
+
};
|
|
229
|
+
function validatePreset(preset) {
|
|
230
|
+
if (!(preset in presetsObj)) throw new Error("Preset must be one of: " + Object.keys(presetsObj).join(", "));
|
|
231
|
+
}
|
|
232
|
+
function getExtension(files) {
|
|
233
|
+
const isCubemap = isArray(files) && files.length === 6;
|
|
234
|
+
const isGainmap = isArray(files) && files.length === 3 && files.some((file) => file.endsWith("json"));
|
|
235
|
+
const firstEntry = isArray(files) ? files[0] : files;
|
|
236
|
+
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();
|
|
237
|
+
return { extension, isCubemap, isGainmap };
|
|
238
|
+
}
|
|
239
|
+
function getLoader$1(extension) {
|
|
240
|
+
const loader = extension === "cube" ? webgpu.CubeTextureLoader : extension === "hdr" ? HDRLoader_js.HDRLoader : extension === "exr" ? EXRLoader_js.EXRLoader : extension === "jpg" || extension === "jpeg" ? UltraHDRLoader_js.UltraHDRLoader : extension === "webp" ? gainmapJs.GainMapLoader : null;
|
|
241
|
+
return loader;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
const isRef$1 = (obj) => obj.current && obj.current.isScene;
|
|
245
|
+
const resolveScene = (scene) => isRef$1(scene) ? scene.current : scene;
|
|
246
|
+
function setEnvProps(background, scene, defaultScene, texture, sceneProps = {}) {
|
|
247
|
+
sceneProps = {
|
|
248
|
+
backgroundBlurriness: 0,
|
|
249
|
+
backgroundIntensity: 1,
|
|
250
|
+
backgroundRotation: [0, 0, 0],
|
|
251
|
+
environmentIntensity: 1,
|
|
252
|
+
environmentRotation: [0, 0, 0],
|
|
253
|
+
...sceneProps
|
|
254
|
+
};
|
|
255
|
+
const target = resolveScene(scene || defaultScene);
|
|
256
|
+
const oldbg = target.background;
|
|
257
|
+
const oldenv = target.environment;
|
|
258
|
+
const oldSceneProps = {
|
|
259
|
+
// @ts-ignore
|
|
260
|
+
backgroundBlurriness: target.backgroundBlurriness,
|
|
261
|
+
// @ts-ignore
|
|
262
|
+
backgroundIntensity: target.backgroundIntensity,
|
|
263
|
+
// @ts-ignore
|
|
264
|
+
backgroundRotation: target.backgroundRotation?.clone?.() ?? [0, 0, 0],
|
|
265
|
+
// @ts-ignore
|
|
266
|
+
environmentIntensity: target.environmentIntensity,
|
|
267
|
+
// @ts-ignore
|
|
268
|
+
environmentRotation: target.environmentRotation?.clone?.() ?? [0, 0, 0]
|
|
269
|
+
};
|
|
270
|
+
if (background !== "only") target.environment = texture;
|
|
271
|
+
if (background) target.background = texture;
|
|
272
|
+
fiber.applyProps(target, sceneProps);
|
|
273
|
+
return () => {
|
|
274
|
+
if (background !== "only") target.environment = oldenv;
|
|
275
|
+
if (background) target.background = oldbg;
|
|
276
|
+
fiber.applyProps(target, oldSceneProps);
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
function EnvironmentMap({ scene, background = false, map, ...config }) {
|
|
280
|
+
const defaultScene = fiber.useThree((state) => state.scene);
|
|
281
|
+
React__namespace.useLayoutEffect(() => {
|
|
282
|
+
if (map) return setEnvProps(background, scene, defaultScene, map, config);
|
|
283
|
+
});
|
|
284
|
+
return null;
|
|
285
|
+
}
|
|
286
|
+
function EnvironmentCube({
|
|
287
|
+
background = false,
|
|
288
|
+
scene,
|
|
289
|
+
blur,
|
|
290
|
+
backgroundBlurriness,
|
|
291
|
+
backgroundIntensity,
|
|
292
|
+
backgroundRotation,
|
|
293
|
+
environmentIntensity,
|
|
294
|
+
environmentRotation,
|
|
295
|
+
...rest
|
|
296
|
+
}) {
|
|
297
|
+
const texture = useEnvironment(rest);
|
|
298
|
+
const defaultScene = fiber.useThree((state) => state.scene);
|
|
299
|
+
React__namespace.useLayoutEffect(() => {
|
|
300
|
+
return setEnvProps(background, scene, defaultScene, texture, {
|
|
301
|
+
backgroundBlurriness: blur ?? backgroundBlurriness,
|
|
302
|
+
backgroundIntensity,
|
|
303
|
+
backgroundRotation,
|
|
304
|
+
environmentIntensity,
|
|
305
|
+
environmentRotation
|
|
306
|
+
});
|
|
307
|
+
});
|
|
308
|
+
React__namespace.useEffect(() => {
|
|
309
|
+
return () => {
|
|
310
|
+
texture.dispose();
|
|
311
|
+
};
|
|
312
|
+
}, [texture]);
|
|
313
|
+
return null;
|
|
314
|
+
}
|
|
315
|
+
function EnvironmentPortal({
|
|
316
|
+
children,
|
|
317
|
+
near = 0.1,
|
|
318
|
+
far = 1e3,
|
|
319
|
+
resolution = 256,
|
|
320
|
+
frames = 1,
|
|
321
|
+
map,
|
|
322
|
+
background = false,
|
|
323
|
+
blur,
|
|
324
|
+
backgroundBlurriness,
|
|
325
|
+
backgroundIntensity,
|
|
326
|
+
backgroundRotation,
|
|
327
|
+
environmentIntensity,
|
|
328
|
+
environmentRotation,
|
|
329
|
+
scene,
|
|
330
|
+
files,
|
|
331
|
+
path,
|
|
332
|
+
preset = void 0,
|
|
333
|
+
extensions
|
|
334
|
+
}) {
|
|
335
|
+
const gl = fiber.useThree((state) => state.gl);
|
|
336
|
+
const defaultScene = fiber.useThree((state) => state.scene);
|
|
337
|
+
const camera = React__namespace.useRef(null);
|
|
338
|
+
const [virtualScene] = React__namespace.useState(() => new webgpu.Scene());
|
|
339
|
+
const fbo = React__namespace.useMemo(() => {
|
|
340
|
+
const fbo2 = new webgpu.WebGLCubeRenderTarget(resolution);
|
|
341
|
+
fbo2.texture.type = webgpu.HalfFloatType;
|
|
342
|
+
return fbo2;
|
|
343
|
+
}, [resolution]);
|
|
344
|
+
React__namespace.useEffect(() => {
|
|
345
|
+
return () => {
|
|
346
|
+
fbo.dispose();
|
|
347
|
+
};
|
|
348
|
+
}, [fbo]);
|
|
349
|
+
React__namespace.useLayoutEffect(() => {
|
|
350
|
+
if (frames === 1) {
|
|
351
|
+
const autoClear = gl.autoClear;
|
|
352
|
+
gl.autoClear = true;
|
|
353
|
+
camera.current.update(gl, virtualScene);
|
|
354
|
+
gl.autoClear = autoClear;
|
|
355
|
+
}
|
|
356
|
+
return setEnvProps(background, scene, defaultScene, fbo.texture, {
|
|
357
|
+
backgroundBlurriness: blur ?? backgroundBlurriness,
|
|
358
|
+
backgroundIntensity,
|
|
359
|
+
backgroundRotation,
|
|
360
|
+
environmentIntensity,
|
|
361
|
+
environmentRotation
|
|
362
|
+
});
|
|
363
|
+
}, [children, virtualScene, fbo.texture, scene, defaultScene, background, frames, gl]);
|
|
364
|
+
let count = 1;
|
|
365
|
+
fiber.useFrame(() => {
|
|
366
|
+
if (frames === Infinity || count < frames) {
|
|
367
|
+
const autoClear = gl.autoClear;
|
|
368
|
+
gl.autoClear = true;
|
|
369
|
+
camera.current.update(gl, virtualScene);
|
|
370
|
+
gl.autoClear = autoClear;
|
|
371
|
+
count++;
|
|
372
|
+
}
|
|
373
|
+
});
|
|
374
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: fiber.createPortal(
|
|
375
|
+
/* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
376
|
+
children,
|
|
377
|
+
/* @__PURE__ */ jsxRuntime.jsx("cubeCamera", { ref: camera, args: [near, far, fbo] }),
|
|
378
|
+
files || preset ? /* @__PURE__ */ jsxRuntime.jsx(EnvironmentCube, { background: true, files, preset, path, extensions }) : map ? /* @__PURE__ */ jsxRuntime.jsx(EnvironmentMap, { background: true, map, extensions }) : null
|
|
379
|
+
] }),
|
|
380
|
+
virtualScene
|
|
381
|
+
) });
|
|
382
|
+
}
|
|
383
|
+
function EnvironmentGround(props) {
|
|
384
|
+
const textureDefault = useEnvironment(props);
|
|
385
|
+
const texture = props.map || textureDefault;
|
|
386
|
+
React__namespace.useMemo(() => fiber.extend({ GroundProjectedEnvImpl: GroundedSkybox_js.GroundedSkybox }), []);
|
|
387
|
+
React__namespace.useEffect(() => {
|
|
388
|
+
return () => {
|
|
389
|
+
textureDefault.dispose();
|
|
390
|
+
};
|
|
391
|
+
}, [textureDefault]);
|
|
392
|
+
const height = props.ground?.height ?? 15;
|
|
393
|
+
const radius = props.ground?.radius ?? 60;
|
|
394
|
+
const scale = props.ground?.scale ?? 1e3;
|
|
395
|
+
const args = React__namespace.useMemo(
|
|
396
|
+
() => [texture, height, radius],
|
|
397
|
+
[texture, height, radius]
|
|
398
|
+
);
|
|
399
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
400
|
+
/* @__PURE__ */ jsxRuntime.jsx(EnvironmentMap, { ...props, map: texture }),
|
|
401
|
+
/* @__PURE__ */ jsxRuntime.jsx("groundProjectedEnvImpl", { args, scale })
|
|
402
|
+
] });
|
|
403
|
+
}
|
|
404
|
+
function EnvironmentColor({ color, scene }) {
|
|
405
|
+
const defaultScene = fiber.useThree((state) => state.scene);
|
|
406
|
+
React__namespace.useLayoutEffect(() => {
|
|
407
|
+
if (color === void 0) return;
|
|
408
|
+
const target = resolveScene(scene || defaultScene);
|
|
409
|
+
const oldBg = target.background;
|
|
410
|
+
target.background = new webgpu.Color(color);
|
|
411
|
+
return () => {
|
|
412
|
+
target.background = oldBg;
|
|
413
|
+
};
|
|
414
|
+
});
|
|
415
|
+
return null;
|
|
416
|
+
}
|
|
417
|
+
function EnvironmentDualSource(props) {
|
|
418
|
+
const { backgroundFiles, ...envProps } = props;
|
|
419
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
420
|
+
/* @__PURE__ */ jsxRuntime.jsx(EnvironmentCube, { ...envProps, background: false }),
|
|
421
|
+
/* @__PURE__ */ jsxRuntime.jsx(EnvironmentCube, { ...props, files: backgroundFiles, background: "only" })
|
|
422
|
+
] });
|
|
423
|
+
}
|
|
424
|
+
function Environment(props) {
|
|
425
|
+
if (props.color && !props.files && !props.preset && !props.map) {
|
|
426
|
+
return /* @__PURE__ */ jsxRuntime.jsx(EnvironmentColor, { ...props });
|
|
427
|
+
}
|
|
428
|
+
if (props.backgroundFiles && props.backgroundFiles !== props.files) {
|
|
429
|
+
return /* @__PURE__ */ jsxRuntime.jsx(EnvironmentDualSource, { ...props });
|
|
430
|
+
}
|
|
431
|
+
return props.ground ? /* @__PURE__ */ jsxRuntime.jsx(EnvironmentGround, { ...props }) : props.map ? /* @__PURE__ */ jsxRuntime.jsx(EnvironmentMap, { ...props }) : props.children ? /* @__PURE__ */ jsxRuntime.jsx(EnvironmentPortal, { ...props }) : /* @__PURE__ */ jsxRuntime.jsx(EnvironmentCube, { ...props });
|
|
432
|
+
}
|
|
433
|
+
|
|
60
434
|
var __defProp$2 = Object.defineProperty;
|
|
61
435
|
var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
62
436
|
var __publicField$2 = (obj, key, value) => __defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
@@ -236,7 +610,8 @@ function prepare(target, root, type, props) {
|
|
|
236
610
|
object,
|
|
237
611
|
eventCount: 0,
|
|
238
612
|
handlers: {},
|
|
239
|
-
isHidden: false
|
|
613
|
+
isHidden: false,
|
|
614
|
+
deferredRefs: []
|
|
240
615
|
};
|
|
241
616
|
if (object) object.__r3f = instance;
|
|
242
617
|
}
|
|
@@ -285,7 +660,7 @@ function createOcclusionObserverNode(store, uniform) {
|
|
|
285
660
|
let occlusionSetupPromise = null;
|
|
286
661
|
function enableOcclusion(store) {
|
|
287
662
|
const state = store.getState();
|
|
288
|
-
const { internal, renderer
|
|
663
|
+
const { internal, renderer } = state;
|
|
289
664
|
if (internal.occlusionEnabled || occlusionSetupPromise) return;
|
|
290
665
|
const hasOcclusionSupport = typeof renderer?.isOccluded === "function";
|
|
291
666
|
if (!hasOcclusionSupport) {
|
|
@@ -448,6 +823,22 @@ function hasVisibilityHandlers(handlers) {
|
|
|
448
823
|
return !!(handlers.onFramed || handlers.onOccluded || handlers.onVisible);
|
|
449
824
|
}
|
|
450
825
|
|
|
826
|
+
const FROM_REF = Symbol.for("@react-three/fiber.fromRef");
|
|
827
|
+
function fromRef(ref) {
|
|
828
|
+
return { [FROM_REF]: ref };
|
|
829
|
+
}
|
|
830
|
+
function isFromRef(value) {
|
|
831
|
+
return value !== null && typeof value === "object" && FROM_REF in value;
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
const ONCE = Symbol.for("@react-three/fiber.once");
|
|
835
|
+
function once(...args) {
|
|
836
|
+
return { [ONCE]: args.length ? args : true };
|
|
837
|
+
}
|
|
838
|
+
function isOnce(value) {
|
|
839
|
+
return value !== null && typeof value === "object" && ONCE in value;
|
|
840
|
+
}
|
|
841
|
+
|
|
451
842
|
const RESERVED_PROPS = [
|
|
452
843
|
"children",
|
|
453
844
|
"key",
|
|
@@ -518,7 +909,7 @@ function getMemoizedPrototype(root) {
|
|
|
518
909
|
ctor = new root.constructor();
|
|
519
910
|
MEMOIZED_PROTOTYPES.set(root.constructor, ctor);
|
|
520
911
|
}
|
|
521
|
-
} catch
|
|
912
|
+
} catch {
|
|
522
913
|
}
|
|
523
914
|
return ctor;
|
|
524
915
|
}
|
|
@@ -564,6 +955,25 @@ function applyProps(object, props) {
|
|
|
564
955
|
continue;
|
|
565
956
|
}
|
|
566
957
|
if (value === void 0) continue;
|
|
958
|
+
if (isFromRef(value)) {
|
|
959
|
+
instance?.deferredRefs?.push({ prop, ref: value[FROM_REF] });
|
|
960
|
+
continue;
|
|
961
|
+
}
|
|
962
|
+
if (isOnce(value)) {
|
|
963
|
+
if (instance?.appliedOnce?.has(prop)) continue;
|
|
964
|
+
if (instance) {
|
|
965
|
+
instance.appliedOnce ?? (instance.appliedOnce = /* @__PURE__ */ new Set());
|
|
966
|
+
instance.appliedOnce.add(prop);
|
|
967
|
+
}
|
|
968
|
+
const { root: targetRoot, key: targetKey } = resolve(object, prop);
|
|
969
|
+
const args = value[ONCE];
|
|
970
|
+
if (typeof targetRoot[targetKey] === "function") {
|
|
971
|
+
targetRoot[targetKey](...args === true ? [] : args);
|
|
972
|
+
} else if (args !== true && args.length > 0) {
|
|
973
|
+
targetRoot[targetKey] = args[0];
|
|
974
|
+
}
|
|
975
|
+
continue;
|
|
976
|
+
}
|
|
567
977
|
let { root, key, target } = resolve(object, prop);
|
|
568
978
|
if (target === void 0 && (typeof root !== "object" || root === null)) {
|
|
569
979
|
throw Error(`R3F: Cannot set "${prop}". Ensure it is an object before setting "${key}".`);
|
|
@@ -586,7 +996,7 @@ function applyProps(object, props) {
|
|
|
586
996
|
else target.set(value);
|
|
587
997
|
} else {
|
|
588
998
|
root[key] = value;
|
|
589
|
-
if (rootState &&
|
|
999
|
+
if (rootState && rootState.renderer?.outputColorSpace === webgpu.SRGBColorSpace && colorMaps.includes(key) && isTexture(value) && root[key]?.isTexture && // sRGB textures must be RGBA8 since r137 https://github.com/mrdoob/three.js/pull/23129
|
|
590
1000
|
root[key].format === webgpu.RGBAFormat && root[key].type === webgpu.UnsignedByteType) {
|
|
591
1001
|
root[key].colorSpace = rootState.textureColorSpace;
|
|
592
1002
|
}
|
|
@@ -943,7 +1353,7 @@ function createPointerEvents(store) {
|
|
|
943
1353
|
return {
|
|
944
1354
|
priority: 1,
|
|
945
1355
|
enabled: true,
|
|
946
|
-
compute(event, state
|
|
1356
|
+
compute(event, state) {
|
|
947
1357
|
state.pointer.set(event.offsetX / state.size.width * 2 - 1, -(event.offsetY / state.size.height) * 2 + 1);
|
|
948
1358
|
state.raycaster.setFromCamera(state.pointer, state.camera);
|
|
949
1359
|
},
|
|
@@ -1041,331 +1451,26 @@ function notifyAlpha({ message, link }) {
|
|
|
1041
1451
|
}
|
|
1042
1452
|
}
|
|
1043
1453
|
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
}
|
|
1065
|
-
}
|
|
1066
|
-
let performanceTimeout = void 0;
|
|
1067
|
-
const setPerformanceCurrent = (current) => set((state2) => ({ performance: { ...state2.performance, current } }));
|
|
1068
|
-
const pointer = new webgpu.Vector2();
|
|
1069
|
-
const rootState = {
|
|
1070
|
-
set,
|
|
1071
|
-
get,
|
|
1072
|
-
// Mock objects that have to be configured
|
|
1073
|
-
gl: null,
|
|
1074
|
-
renderer: null,
|
|
1075
|
-
camera: null,
|
|
1076
|
-
frustum: new webgpu.Frustum(),
|
|
1077
|
-
autoUpdateFrustum: true,
|
|
1078
|
-
raycaster: null,
|
|
1079
|
-
events: { priority: 1, enabled: true, connected: false },
|
|
1080
|
-
scene: null,
|
|
1081
|
-
rootScene: null,
|
|
1082
|
-
xr: null,
|
|
1083
|
-
inspector: null,
|
|
1084
|
-
invalidate: (frames = 1, stackFrames = false) => invalidate(get(), frames, stackFrames),
|
|
1085
|
-
advance: (timestamp, runGlobalEffects) => advance(timestamp, runGlobalEffects, get()),
|
|
1086
|
-
legacy: false,
|
|
1087
|
-
linear: false,
|
|
1088
|
-
flat: false,
|
|
1089
|
-
textureColorSpace: "srgb",
|
|
1090
|
-
isLegacy: false,
|
|
1091
|
-
webGPUSupported: false,
|
|
1092
|
-
isNative: false,
|
|
1093
|
-
controls: null,
|
|
1094
|
-
pointer,
|
|
1095
|
-
mouse: pointer,
|
|
1096
|
-
frameloop: "always",
|
|
1097
|
-
onPointerMissed: void 0,
|
|
1098
|
-
onDragOverMissed: void 0,
|
|
1099
|
-
onDropMissed: void 0,
|
|
1100
|
-
performance: {
|
|
1101
|
-
current: 1,
|
|
1102
|
-
min: 0.5,
|
|
1103
|
-
max: 1,
|
|
1104
|
-
debounce: 200,
|
|
1105
|
-
regress: () => {
|
|
1106
|
-
const state2 = get();
|
|
1107
|
-
if (performanceTimeout) clearTimeout(performanceTimeout);
|
|
1108
|
-
if (state2.performance.current !== state2.performance.min) setPerformanceCurrent(state2.performance.min);
|
|
1109
|
-
performanceTimeout = setTimeout(
|
|
1110
|
-
() => setPerformanceCurrent(get().performance.max),
|
|
1111
|
-
state2.performance.debounce
|
|
1112
|
-
);
|
|
1113
|
-
}
|
|
1114
|
-
},
|
|
1115
|
-
size: { width: 0, height: 0, top: 0, left: 0 },
|
|
1116
|
-
viewport: {
|
|
1117
|
-
initialDpr: 0,
|
|
1118
|
-
dpr: 0,
|
|
1119
|
-
width: 0,
|
|
1120
|
-
height: 0,
|
|
1121
|
-
top: 0,
|
|
1122
|
-
left: 0,
|
|
1123
|
-
aspect: 0,
|
|
1124
|
-
distance: 0,
|
|
1125
|
-
factor: 0,
|
|
1126
|
-
getCurrentViewport
|
|
1127
|
-
},
|
|
1128
|
-
setEvents: (events) => set((state2) => ({ ...state2, events: { ...state2.events, ...events } })),
|
|
1129
|
-
setSize: (width, height, top, left) => {
|
|
1130
|
-
const state2 = get();
|
|
1131
|
-
if (width === void 0) {
|
|
1132
|
-
set({ _sizeImperative: false });
|
|
1133
|
-
if (state2._sizeProps) {
|
|
1134
|
-
const { width: propW, height: propH } = state2._sizeProps;
|
|
1135
|
-
if (propW !== void 0 || propH !== void 0) {
|
|
1136
|
-
const currentSize = state2.size;
|
|
1137
|
-
const newSize = {
|
|
1138
|
-
width: propW ?? currentSize.width,
|
|
1139
|
-
height: propH ?? currentSize.height,
|
|
1140
|
-
top: currentSize.top,
|
|
1141
|
-
left: currentSize.left
|
|
1142
|
-
};
|
|
1143
|
-
set((s) => ({
|
|
1144
|
-
size: newSize,
|
|
1145
|
-
viewport: { ...s.viewport, ...getCurrentViewport(state2.camera, defaultTarget, newSize) }
|
|
1146
|
-
}));
|
|
1147
|
-
}
|
|
1148
|
-
}
|
|
1149
|
-
return;
|
|
1150
|
-
}
|
|
1151
|
-
const w = width;
|
|
1152
|
-
const h = height ?? width;
|
|
1153
|
-
const t = top ?? state2.size.top;
|
|
1154
|
-
const l = left ?? state2.size.left;
|
|
1155
|
-
const size = { width: w, height: h, top: t, left: l };
|
|
1156
|
-
set((s) => ({
|
|
1157
|
-
size,
|
|
1158
|
-
viewport: { ...s.viewport, ...getCurrentViewport(state2.camera, defaultTarget, size) },
|
|
1159
|
-
_sizeImperative: true
|
|
1160
|
-
}));
|
|
1161
|
-
},
|
|
1162
|
-
setDpr: (dpr) => set((state2) => {
|
|
1163
|
-
const resolved = calculateDpr(dpr);
|
|
1164
|
-
return { viewport: { ...state2.viewport, dpr: resolved, initialDpr: state2.viewport.initialDpr || resolved } };
|
|
1165
|
-
}),
|
|
1166
|
-
setFrameloop: (frameloop = "always") => {
|
|
1167
|
-
set(() => ({ frameloop }));
|
|
1168
|
-
},
|
|
1169
|
-
setError: (error) => set(() => ({ error })),
|
|
1170
|
-
error: null,
|
|
1171
|
-
//* TSL State (managed via hooks: useUniforms, useNodes, useTextures, usePostProcessing) ==============================
|
|
1172
|
-
uniforms: {},
|
|
1173
|
-
nodes: {},
|
|
1174
|
-
textures: /* @__PURE__ */ new Map(),
|
|
1175
|
-
postProcessing: null,
|
|
1176
|
-
passes: {},
|
|
1177
|
-
_hmrVersion: 0,
|
|
1178
|
-
_sizeImperative: false,
|
|
1179
|
-
_sizeProps: null,
|
|
1180
|
-
previousRoot: void 0,
|
|
1181
|
-
internal: {
|
|
1182
|
-
// Events
|
|
1183
|
-
interaction: [],
|
|
1184
|
-
hovered: /* @__PURE__ */ new Map(),
|
|
1185
|
-
subscribers: [],
|
|
1186
|
-
initialClick: [0, 0],
|
|
1187
|
-
initialHits: [],
|
|
1188
|
-
capturedMap: /* @__PURE__ */ new Map(),
|
|
1189
|
-
lastEvent: React__namespace.createRef(),
|
|
1190
|
-
// Visibility tracking (onFramed, onOccluded, onVisible)
|
|
1191
|
-
visibilityRegistry: /* @__PURE__ */ new Map(),
|
|
1192
|
-
// Occlusion system (WebGPU only)
|
|
1193
|
-
occlusionEnabled: false,
|
|
1194
|
-
occlusionObserver: null,
|
|
1195
|
-
occlusionCache: /* @__PURE__ */ new Map(),
|
|
1196
|
-
helperGroup: null,
|
|
1197
|
-
// Updates
|
|
1198
|
-
active: false,
|
|
1199
|
-
frames: 0,
|
|
1200
|
-
priority: 0,
|
|
1201
|
-
subscribe: (ref, priority, store) => {
|
|
1202
|
-
const internal = get().internal;
|
|
1203
|
-
internal.priority = internal.priority + (priority > 0 ? 1 : 0);
|
|
1204
|
-
internal.subscribers.push({ ref, priority, store });
|
|
1205
|
-
internal.subscribers = internal.subscribers.sort((a, b) => a.priority - b.priority);
|
|
1206
|
-
return () => {
|
|
1207
|
-
const internal2 = get().internal;
|
|
1208
|
-
if (internal2?.subscribers) {
|
|
1209
|
-
internal2.priority = internal2.priority - (priority > 0 ? 1 : 0);
|
|
1210
|
-
internal2.subscribers = internal2.subscribers.filter((s) => s.ref !== ref);
|
|
1211
|
-
}
|
|
1212
|
-
};
|
|
1213
|
-
},
|
|
1214
|
-
// Renderer Storage (single source of truth)
|
|
1215
|
-
actualRenderer: null,
|
|
1216
|
-
// Scheduler for useFrameNext (initialized in renderer.tsx)
|
|
1217
|
-
scheduler: null
|
|
1218
|
-
}
|
|
1219
|
-
};
|
|
1220
|
-
return rootState;
|
|
1221
|
-
});
|
|
1222
|
-
const state = rootStore.getState();
|
|
1223
|
-
Object.defineProperty(state, "gl", {
|
|
1224
|
-
get() {
|
|
1225
|
-
const currentState = rootStore.getState();
|
|
1226
|
-
if (!currentState.isLegacy && currentState.internal.actualRenderer) {
|
|
1227
|
-
const stack = new Error().stack || "";
|
|
1228
|
-
const isInternalAccess = stack.includes("zustand") || stack.includes("setState") || stack.includes("Object.assign") || stack.includes("react-three-fiber/packages/fiber/src/core");
|
|
1229
|
-
if (!isInternalAccess) {
|
|
1230
|
-
const cleanedStack = stack.split("\n").slice(2).join("\n") || "Stack trace unavailable";
|
|
1231
|
-
notifyDepreciated({
|
|
1232
|
-
heading: "Accessing state.gl in WebGPU mode",
|
|
1233
|
-
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
|
|
1234
|
-
});
|
|
1235
|
-
}
|
|
1236
|
-
}
|
|
1237
|
-
return currentState.internal.actualRenderer;
|
|
1238
|
-
},
|
|
1239
|
-
set(value) {
|
|
1240
|
-
rootStore.getState().internal.actualRenderer = value;
|
|
1241
|
-
},
|
|
1242
|
-
enumerable: true,
|
|
1243
|
-
configurable: true
|
|
1244
|
-
});
|
|
1245
|
-
Object.defineProperty(state, "renderer", {
|
|
1246
|
-
get() {
|
|
1247
|
-
return rootStore.getState().internal.actualRenderer;
|
|
1248
|
-
},
|
|
1249
|
-
set(value) {
|
|
1250
|
-
rootStore.getState().internal.actualRenderer = value;
|
|
1251
|
-
},
|
|
1252
|
-
enumerable: true,
|
|
1253
|
-
configurable: true
|
|
1254
|
-
});
|
|
1255
|
-
let oldScene = state.scene;
|
|
1256
|
-
rootStore.subscribe(() => {
|
|
1257
|
-
const currentState = rootStore.getState();
|
|
1258
|
-
const { scene, rootScene, set } = currentState;
|
|
1259
|
-
if (scene !== oldScene) {
|
|
1260
|
-
oldScene = scene;
|
|
1261
|
-
if (scene?.isScene && scene !== rootScene) {
|
|
1262
|
-
set({ rootScene: scene });
|
|
1263
|
-
}
|
|
1264
|
-
}
|
|
1265
|
-
});
|
|
1266
|
-
let oldSize = state.size;
|
|
1267
|
-
let oldDpr = state.viewport.dpr;
|
|
1268
|
-
let oldCamera = state.camera;
|
|
1269
|
-
rootStore.subscribe(() => {
|
|
1270
|
-
const { camera, size, viewport, set, internal } = rootStore.getState();
|
|
1271
|
-
const actualRenderer = internal.actualRenderer;
|
|
1272
|
-
if (size.width !== oldSize.width || size.height !== oldSize.height || viewport.dpr !== oldDpr) {
|
|
1273
|
-
oldSize = size;
|
|
1274
|
-
oldDpr = viewport.dpr;
|
|
1275
|
-
updateCamera(camera, size);
|
|
1276
|
-
if (viewport.dpr > 0) actualRenderer.setPixelRatio(viewport.dpr);
|
|
1277
|
-
const updateStyle = typeof HTMLCanvasElement !== "undefined" && actualRenderer.domElement instanceof HTMLCanvasElement;
|
|
1278
|
-
actualRenderer.setSize(size.width, size.height, updateStyle);
|
|
1279
|
-
}
|
|
1280
|
-
if (camera !== oldCamera) {
|
|
1281
|
-
oldCamera = camera;
|
|
1282
|
-
const { rootScene } = rootStore.getState();
|
|
1283
|
-
if (camera && rootScene && !camera.parent) {
|
|
1284
|
-
rootScene.add(camera);
|
|
1285
|
-
}
|
|
1286
|
-
set((state2) => ({ viewport: { ...state2.viewport, ...state2.viewport.getCurrentViewport(camera) } }));
|
|
1287
|
-
const currentState = rootStore.getState();
|
|
1288
|
-
if (currentState.autoUpdateFrustum && camera) {
|
|
1289
|
-
updateFrustum(camera, currentState.frustum);
|
|
1290
|
-
}
|
|
1291
|
-
}
|
|
1292
|
-
});
|
|
1293
|
-
rootStore.subscribe((state2) => invalidate(state2));
|
|
1294
|
-
return rootStore;
|
|
1295
|
-
};
|
|
1296
|
-
|
|
1297
|
-
const memoizedLoaders = /* @__PURE__ */ new WeakMap();
|
|
1298
|
-
const isConstructor$1 = (value) => typeof value === "function" && value?.prototype?.constructor === value;
|
|
1299
|
-
function getLoader(Proto) {
|
|
1300
|
-
if (isConstructor$1(Proto)) {
|
|
1301
|
-
let loader = memoizedLoaders.get(Proto);
|
|
1302
|
-
if (!loader) {
|
|
1303
|
-
loader = new Proto();
|
|
1304
|
-
memoizedLoaders.set(Proto, loader);
|
|
1305
|
-
}
|
|
1306
|
-
return loader;
|
|
1307
|
-
}
|
|
1308
|
-
return Proto;
|
|
1309
|
-
}
|
|
1310
|
-
function loadingFn(extensions, onProgress) {
|
|
1311
|
-
return function(Proto, input) {
|
|
1312
|
-
const loader = getLoader(Proto);
|
|
1313
|
-
if (extensions) extensions(loader);
|
|
1314
|
-
if ("loadAsync" in loader && typeof loader.loadAsync === "function") {
|
|
1315
|
-
return loader.loadAsync(input, onProgress).then((data) => {
|
|
1316
|
-
if (isObject3D(data?.scene)) Object.assign(data, buildGraph(data.scene));
|
|
1317
|
-
return data;
|
|
1318
|
-
});
|
|
1319
|
-
}
|
|
1320
|
-
return new Promise(
|
|
1321
|
-
(res, reject) => loader.load(
|
|
1322
|
-
input,
|
|
1323
|
-
(data) => {
|
|
1324
|
-
if (isObject3D(data?.scene)) Object.assign(data, buildGraph(data.scene));
|
|
1325
|
-
res(data);
|
|
1326
|
-
},
|
|
1327
|
-
onProgress,
|
|
1328
|
-
(error) => reject(new Error(`Could not load ${input}: ${error?.message}`))
|
|
1329
|
-
)
|
|
1330
|
-
);
|
|
1331
|
-
};
|
|
1332
|
-
}
|
|
1333
|
-
function useLoader(loader, input, extensions, onProgress) {
|
|
1334
|
-
const keys = Array.isArray(input) ? input : [input];
|
|
1335
|
-
const fn = loadingFn(extensions, onProgress);
|
|
1336
|
-
const results = keys.map((key) => suspendReact.suspend(fn, [loader, key], { equal: is.equ }));
|
|
1337
|
-
return Array.isArray(input) ? results : results[0];
|
|
1338
|
-
}
|
|
1339
|
-
useLoader.preload = function(loader, input, extensions, onProgress) {
|
|
1340
|
-
const keys = Array.isArray(input) ? input : [input];
|
|
1341
|
-
keys.forEach((key) => suspendReact.preload(loadingFn(extensions, onProgress), [loader, key]));
|
|
1342
|
-
};
|
|
1343
|
-
useLoader.clear = function(loader, input) {
|
|
1344
|
-
const keys = Array.isArray(input) ? input : [input];
|
|
1345
|
-
keys.forEach((key) => suspendReact.clear([loader, key]));
|
|
1346
|
-
};
|
|
1347
|
-
useLoader.loader = getLoader;
|
|
1348
|
-
|
|
1349
|
-
var __defProp$1 = Object.defineProperty;
|
|
1350
|
-
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1351
|
-
var __publicField$1 = (obj, key, value) => __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1352
|
-
const DEFAULT_PHASES = ["start", "input", "physics", "update", "render", "finish"];
|
|
1353
|
-
class PhaseGraph {
|
|
1354
|
-
constructor() {
|
|
1355
|
-
/** Ordered list of phase nodes */
|
|
1356
|
-
__publicField$1(this, "phases", []);
|
|
1357
|
-
/** Quick lookup by name */
|
|
1358
|
-
__publicField$1(this, "phaseMap", /* @__PURE__ */ new Map());
|
|
1359
|
-
/** Cached ordered names (invalidated on changes) */
|
|
1360
|
-
__publicField$1(this, "orderedNamesCache", null);
|
|
1361
|
-
this.initializeDefaultPhases();
|
|
1362
|
-
}
|
|
1363
|
-
//* Initialization --------------------------------
|
|
1364
|
-
initializeDefaultPhases() {
|
|
1365
|
-
for (const name of DEFAULT_PHASES) {
|
|
1366
|
-
const node = { name, isAutoGenerated: false };
|
|
1367
|
-
this.phases.push(node);
|
|
1368
|
-
this.phaseMap.set(name, node);
|
|
1454
|
+
var __defProp$1 = Object.defineProperty;
|
|
1455
|
+
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1456
|
+
var __publicField$1 = (obj, key, value) => __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1457
|
+
const DEFAULT_PHASES = ["start", "input", "physics", "update", "render", "finish"];
|
|
1458
|
+
class PhaseGraph {
|
|
1459
|
+
constructor() {
|
|
1460
|
+
/** Ordered list of phase nodes */
|
|
1461
|
+
__publicField$1(this, "phases", []);
|
|
1462
|
+
/** Quick lookup by name */
|
|
1463
|
+
__publicField$1(this, "phaseMap", /* @__PURE__ */ new Map());
|
|
1464
|
+
/** Cached ordered names (invalidated on changes) */
|
|
1465
|
+
__publicField$1(this, "orderedNamesCache", null);
|
|
1466
|
+
this.initializeDefaultPhases();
|
|
1467
|
+
}
|
|
1468
|
+
//* Initialization --------------------------------
|
|
1469
|
+
initializeDefaultPhases() {
|
|
1470
|
+
for (const name of DEFAULT_PHASES) {
|
|
1471
|
+
const node = { name, isAutoGenerated: false };
|
|
1472
|
+
this.phases.push(node);
|
|
1473
|
+
this.phaseMap.set(name, node);
|
|
1369
1474
|
}
|
|
1370
1475
|
this.invalidateCache();
|
|
1371
1476
|
}
|
|
@@ -2251,132 +2356,445 @@ const _Scheduler = class _Scheduler {
|
|
|
2251
2356
|
console.error(`[Scheduler] Error in global job "${job.id}":`, error);
|
|
2252
2357
|
}
|
|
2253
2358
|
}
|
|
2254
|
-
}
|
|
2255
|
-
/**
|
|
2256
|
-
* Execute all jobs for a single root in sorted order.
|
|
2257
|
-
* Rebuilds sorted job list if needed, then dispatches each job.
|
|
2258
|
-
* Errors are caught and propagated via triggerError.
|
|
2259
|
-
* @param {RootEntry} root - The root entry to tick
|
|
2260
|
-
* @param {number} timestamp - RAF timestamp in milliseconds
|
|
2261
|
-
* @param {number} delta - Time since last frame in seconds
|
|
2262
|
-
* @returns {void}
|
|
2263
|
-
* @private
|
|
2264
|
-
*/
|
|
2265
|
-
tickRoot(root, timestamp, delta) {
|
|
2266
|
-
if (root.needsRebuild) {
|
|
2267
|
-
root.sortedJobs = rebuildSortedJobs(root.jobs, this.phaseGraph);
|
|
2268
|
-
root.needsRebuild = false;
|
|
2269
|
-
}
|
|
2270
|
-
const providedState = root.getState?.() ?? {};
|
|
2271
|
-
const frameState = {
|
|
2272
|
-
...providedState,
|
|
2273
|
-
time: timestamp,
|
|
2274
|
-
delta,
|
|
2275
|
-
elapsed: this.loopState.elapsedTime / 1e3,
|
|
2276
|
-
// Convert ms to seconds
|
|
2277
|
-
frame: this.loopState.frameCount
|
|
2278
|
-
};
|
|
2279
|
-
for (const job of root.sortedJobs) {
|
|
2280
|
-
if (!shouldRun(job, timestamp)) continue;
|
|
2281
|
-
try {
|
|
2282
|
-
job.callback(frameState, delta);
|
|
2283
|
-
} catch (error) {
|
|
2284
|
-
console.error(`[Scheduler] Error in job "${job.id}":`, error);
|
|
2285
|
-
this.triggerError(error instanceof Error ? error : new Error(String(error)));
|
|
2359
|
+
}
|
|
2360
|
+
/**
|
|
2361
|
+
* Execute all jobs for a single root in sorted order.
|
|
2362
|
+
* Rebuilds sorted job list if needed, then dispatches each job.
|
|
2363
|
+
* Errors are caught and propagated via triggerError.
|
|
2364
|
+
* @param {RootEntry} root - The root entry to tick
|
|
2365
|
+
* @param {number} timestamp - RAF timestamp in milliseconds
|
|
2366
|
+
* @param {number} delta - Time since last frame in seconds
|
|
2367
|
+
* @returns {void}
|
|
2368
|
+
* @private
|
|
2369
|
+
*/
|
|
2370
|
+
tickRoot(root, timestamp, delta) {
|
|
2371
|
+
if (root.needsRebuild) {
|
|
2372
|
+
root.sortedJobs = rebuildSortedJobs(root.jobs, this.phaseGraph);
|
|
2373
|
+
root.needsRebuild = false;
|
|
2374
|
+
}
|
|
2375
|
+
const providedState = root.getState?.() ?? {};
|
|
2376
|
+
const frameState = {
|
|
2377
|
+
...providedState,
|
|
2378
|
+
time: timestamp,
|
|
2379
|
+
delta,
|
|
2380
|
+
elapsed: this.loopState.elapsedTime / 1e3,
|
|
2381
|
+
// Convert ms to seconds
|
|
2382
|
+
frame: this.loopState.frameCount
|
|
2383
|
+
};
|
|
2384
|
+
for (const job of root.sortedJobs) {
|
|
2385
|
+
if (!shouldRun(job, timestamp)) continue;
|
|
2386
|
+
try {
|
|
2387
|
+
job.callback(frameState, delta);
|
|
2388
|
+
} catch (error) {
|
|
2389
|
+
console.error(`[Scheduler] Error in job "${job.id}":`, error);
|
|
2390
|
+
this.triggerError(error instanceof Error ? error : new Error(String(error)));
|
|
2391
|
+
}
|
|
2392
|
+
}
|
|
2393
|
+
}
|
|
2394
|
+
//* Debug & Inspection Methods ================================
|
|
2395
|
+
/**
|
|
2396
|
+
* Get the total number of registered jobs across all roots.
|
|
2397
|
+
* Includes both per-root jobs and global before/after jobs.
|
|
2398
|
+
* @returns {number} Total job count
|
|
2399
|
+
*/
|
|
2400
|
+
getJobCount() {
|
|
2401
|
+
let count = 0;
|
|
2402
|
+
for (const root of this.roots.values()) {
|
|
2403
|
+
count += root.jobs.size;
|
|
2404
|
+
}
|
|
2405
|
+
return count + this.globalBeforeJobs.size + this.globalAfterJobs.size;
|
|
2406
|
+
}
|
|
2407
|
+
/**
|
|
2408
|
+
* Get all registered job IDs across all roots.
|
|
2409
|
+
* Includes both per-root jobs and global before/after jobs.
|
|
2410
|
+
* @returns {string[]} Array of all job IDs
|
|
2411
|
+
*/
|
|
2412
|
+
getJobIds() {
|
|
2413
|
+
const ids = [];
|
|
2414
|
+
for (const root of this.roots.values()) {
|
|
2415
|
+
ids.push(...root.jobs.keys());
|
|
2416
|
+
}
|
|
2417
|
+
ids.push(...this.globalBeforeJobs.keys());
|
|
2418
|
+
ids.push(...this.globalAfterJobs.keys());
|
|
2419
|
+
return ids;
|
|
2420
|
+
}
|
|
2421
|
+
/**
|
|
2422
|
+
* Get the number of registered roots (Canvas instances).
|
|
2423
|
+
* @returns {number} Number of registered roots
|
|
2424
|
+
*/
|
|
2425
|
+
getRootCount() {
|
|
2426
|
+
return this.roots.size;
|
|
2427
|
+
}
|
|
2428
|
+
/**
|
|
2429
|
+
* Check if any user (non-system) jobs are registered in a specific phase.
|
|
2430
|
+
* Used by the default render job to know if a user has taken over rendering.
|
|
2431
|
+
*
|
|
2432
|
+
* @param phase The phase to check
|
|
2433
|
+
* @param rootId Optional root ID to check (checks all roots if not provided)
|
|
2434
|
+
* @returns true if any user jobs exist in the phase
|
|
2435
|
+
*/
|
|
2436
|
+
hasUserJobsInPhase(phase, rootId) {
|
|
2437
|
+
const rootsToCheck = rootId ? [this.roots.get(rootId)].filter(Boolean) : Array.from(this.roots.values());
|
|
2438
|
+
return rootsToCheck.some((root) => {
|
|
2439
|
+
if (!root) return false;
|
|
2440
|
+
for (const job of root.jobs.values()) {
|
|
2441
|
+
if (job.phase === phase && !job.system && job.enabled) return true;
|
|
2442
|
+
}
|
|
2443
|
+
return false;
|
|
2444
|
+
});
|
|
2445
|
+
}
|
|
2446
|
+
//* Utility Methods ================================
|
|
2447
|
+
/**
|
|
2448
|
+
* Generate a unique root ID for automatic root registration.
|
|
2449
|
+
* @returns {string} A unique root ID in the format 'root_N'
|
|
2450
|
+
*/
|
|
2451
|
+
generateRootId() {
|
|
2452
|
+
return `root_${this.nextRootIndex++}`;
|
|
2453
|
+
}
|
|
2454
|
+
/**
|
|
2455
|
+
* Generate a unique job ID.
|
|
2456
|
+
* @returns {string} A unique job ID in the format 'job_N'
|
|
2457
|
+
* @private
|
|
2458
|
+
*/
|
|
2459
|
+
generateJobId() {
|
|
2460
|
+
return `job_${this.nextJobIndex}`;
|
|
2461
|
+
}
|
|
2462
|
+
/**
|
|
2463
|
+
* Normalize before/after constraints to a Set.
|
|
2464
|
+
* Handles undefined, single string, or array inputs.
|
|
2465
|
+
* @param {string | string[] | undefined} value - The constraint value(s)
|
|
2466
|
+
* @returns {Set<string>} Normalized Set of constraint strings
|
|
2467
|
+
* @private
|
|
2468
|
+
*/
|
|
2469
|
+
normalizeConstraints(value) {
|
|
2470
|
+
if (!value) return /* @__PURE__ */ new Set();
|
|
2471
|
+
if (Array.isArray(value)) return new Set(value);
|
|
2472
|
+
return /* @__PURE__ */ new Set([value]);
|
|
2473
|
+
}
|
|
2474
|
+
};
|
|
2475
|
+
//* Static State & Methods (Singleton Usage) ================================
|
|
2476
|
+
//* Cross-Bundle Singleton Key ==============================
|
|
2477
|
+
// Use Symbol.for() to ensure scheduler is shared across bundle boundaries
|
|
2478
|
+
// This prevents issues when mixing imports from @react-three/fiber and @react-three/fiber/webgpu
|
|
2479
|
+
__publicField(_Scheduler, "INSTANCE_KEY", Symbol.for("@react-three/fiber.scheduler"));
|
|
2480
|
+
let Scheduler = _Scheduler;
|
|
2481
|
+
const getScheduler = () => Scheduler.get();
|
|
2482
|
+
if (hmrData) {
|
|
2483
|
+
hmrData.accept?.();
|
|
2484
|
+
}
|
|
2485
|
+
|
|
2486
|
+
const R3F_CONTEXT = Symbol.for("@react-three/fiber.context");
|
|
2487
|
+
const context = globalThis[R3F_CONTEXT] ?? (globalThis[R3F_CONTEXT] = React__namespace.createContext(null));
|
|
2488
|
+
const createStore = (invalidate, advance) => {
|
|
2489
|
+
const rootStore = traditional.createWithEqualityFn((set, get) => {
|
|
2490
|
+
const position = new webgpu.Vector3();
|
|
2491
|
+
const defaultTarget = new webgpu.Vector3();
|
|
2492
|
+
const tempTarget = new webgpu.Vector3();
|
|
2493
|
+
function getCurrentViewport(camera = get().camera, target = defaultTarget, size = get().size) {
|
|
2494
|
+
const { width, height, top, left } = size;
|
|
2495
|
+
const aspect = width / height;
|
|
2496
|
+
if (target.isVector3) tempTarget.copy(target);
|
|
2497
|
+
else tempTarget.set(...target);
|
|
2498
|
+
const distance = camera.getWorldPosition(position).distanceTo(tempTarget);
|
|
2499
|
+
if (isOrthographicCamera(camera)) {
|
|
2500
|
+
return { width: width / camera.zoom, height: height / camera.zoom, top, left, factor: 1, distance, aspect };
|
|
2501
|
+
} else {
|
|
2502
|
+
const fov = camera.fov * Math.PI / 180;
|
|
2503
|
+
const h = 2 * Math.tan(fov / 2) * distance;
|
|
2504
|
+
const w = h * (width / height);
|
|
2505
|
+
return { width: w, height: h, top, left, factor: width / w, distance, aspect };
|
|
2506
|
+
}
|
|
2507
|
+
}
|
|
2508
|
+
let performanceTimeout = void 0;
|
|
2509
|
+
const setPerformanceCurrent = (current) => set((state2) => ({ performance: { ...state2.performance, current } }));
|
|
2510
|
+
const pointer = new webgpu.Vector2();
|
|
2511
|
+
const rootState = {
|
|
2512
|
+
set,
|
|
2513
|
+
get,
|
|
2514
|
+
// Mock objects that have to be configured
|
|
2515
|
+
// primaryStore is set after store creation (self-reference for primary, primary's store for secondary)
|
|
2516
|
+
primaryStore: null,
|
|
2517
|
+
gl: null,
|
|
2518
|
+
renderer: null,
|
|
2519
|
+
camera: null,
|
|
2520
|
+
frustum: new webgpu.Frustum(),
|
|
2521
|
+
autoUpdateFrustum: true,
|
|
2522
|
+
raycaster: null,
|
|
2523
|
+
events: { priority: 1, enabled: true, connected: false },
|
|
2524
|
+
scene: null,
|
|
2525
|
+
rootScene: null,
|
|
2526
|
+
xr: null,
|
|
2527
|
+
inspector: null,
|
|
2528
|
+
invalidate: (frames = 1, stackFrames = false) => invalidate(get(), frames, stackFrames),
|
|
2529
|
+
advance: (timestamp, runGlobalEffects) => advance(timestamp, runGlobalEffects, get()),
|
|
2530
|
+
textureColorSpace: webgpu.SRGBColorSpace,
|
|
2531
|
+
isLegacy: false,
|
|
2532
|
+
webGPUSupported: false,
|
|
2533
|
+
isNative: false,
|
|
2534
|
+
controls: null,
|
|
2535
|
+
pointer,
|
|
2536
|
+
mouse: pointer,
|
|
2537
|
+
frameloop: "always",
|
|
2538
|
+
onPointerMissed: void 0,
|
|
2539
|
+
onDragOverMissed: void 0,
|
|
2540
|
+
onDropMissed: void 0,
|
|
2541
|
+
performance: {
|
|
2542
|
+
current: 1,
|
|
2543
|
+
min: 0.5,
|
|
2544
|
+
max: 1,
|
|
2545
|
+
debounce: 200,
|
|
2546
|
+
regress: () => {
|
|
2547
|
+
const state2 = get();
|
|
2548
|
+
if (performanceTimeout) clearTimeout(performanceTimeout);
|
|
2549
|
+
if (state2.performance.current !== state2.performance.min) setPerformanceCurrent(state2.performance.min);
|
|
2550
|
+
performanceTimeout = setTimeout(
|
|
2551
|
+
() => setPerformanceCurrent(get().performance.max),
|
|
2552
|
+
state2.performance.debounce
|
|
2553
|
+
);
|
|
2554
|
+
}
|
|
2555
|
+
},
|
|
2556
|
+
size: { width: 0, height: 0, top: 0, left: 0 },
|
|
2557
|
+
viewport: {
|
|
2558
|
+
initialDpr: 0,
|
|
2559
|
+
dpr: 0,
|
|
2560
|
+
width: 0,
|
|
2561
|
+
height: 0,
|
|
2562
|
+
top: 0,
|
|
2563
|
+
left: 0,
|
|
2564
|
+
aspect: 0,
|
|
2565
|
+
distance: 0,
|
|
2566
|
+
factor: 0,
|
|
2567
|
+
getCurrentViewport
|
|
2568
|
+
},
|
|
2569
|
+
setEvents: (events) => set((state2) => ({ ...state2, events: { ...state2.events, ...events } })),
|
|
2570
|
+
setSize: (width, height, top, left) => {
|
|
2571
|
+
const state2 = get();
|
|
2572
|
+
if (width === void 0) {
|
|
2573
|
+
set({ _sizeImperative: false });
|
|
2574
|
+
if (state2._sizeProps) {
|
|
2575
|
+
const { width: propW, height: propH } = state2._sizeProps;
|
|
2576
|
+
if (propW !== void 0 || propH !== void 0) {
|
|
2577
|
+
const currentSize = state2.size;
|
|
2578
|
+
const newSize = {
|
|
2579
|
+
width: propW ?? currentSize.width,
|
|
2580
|
+
height: propH ?? currentSize.height,
|
|
2581
|
+
top: currentSize.top,
|
|
2582
|
+
left: currentSize.left
|
|
2583
|
+
};
|
|
2584
|
+
set((s) => ({
|
|
2585
|
+
size: newSize,
|
|
2586
|
+
viewport: { ...s.viewport, ...getCurrentViewport(state2.camera, defaultTarget, newSize) }
|
|
2587
|
+
}));
|
|
2588
|
+
getScheduler().invalidate();
|
|
2589
|
+
}
|
|
2590
|
+
}
|
|
2591
|
+
return;
|
|
2592
|
+
}
|
|
2593
|
+
const w = width;
|
|
2594
|
+
const h = height ?? width;
|
|
2595
|
+
const t = top ?? state2.size.top;
|
|
2596
|
+
const l = left ?? state2.size.left;
|
|
2597
|
+
const size = { width: w, height: h, top: t, left: l };
|
|
2598
|
+
set((s) => ({
|
|
2599
|
+
size,
|
|
2600
|
+
viewport: { ...s.viewport, ...getCurrentViewport(state2.camera, defaultTarget, size) },
|
|
2601
|
+
_sizeImperative: true
|
|
2602
|
+
}));
|
|
2603
|
+
getScheduler().invalidate();
|
|
2604
|
+
},
|
|
2605
|
+
setDpr: (dpr) => set((state2) => {
|
|
2606
|
+
const resolved = calculateDpr(dpr);
|
|
2607
|
+
return { viewport: { ...state2.viewport, dpr: resolved, initialDpr: state2.viewport.initialDpr || resolved } };
|
|
2608
|
+
}),
|
|
2609
|
+
setFrameloop: (frameloop = "always") => {
|
|
2610
|
+
set(() => ({ frameloop }));
|
|
2611
|
+
},
|
|
2612
|
+
setError: (error) => set(() => ({ error })),
|
|
2613
|
+
error: null,
|
|
2614
|
+
//* TSL State (managed via hooks: useUniforms, useNodes, useTextures, usePostProcessing) ==============================
|
|
2615
|
+
uniforms: {},
|
|
2616
|
+
nodes: {},
|
|
2617
|
+
textures: /* @__PURE__ */ new Map(),
|
|
2618
|
+
postProcessing: null,
|
|
2619
|
+
passes: {},
|
|
2620
|
+
_hmrVersion: 0,
|
|
2621
|
+
_sizeImperative: false,
|
|
2622
|
+
_sizeProps: null,
|
|
2623
|
+
previousRoot: void 0,
|
|
2624
|
+
internal: {
|
|
2625
|
+
// Events
|
|
2626
|
+
interaction: [],
|
|
2627
|
+
hovered: /* @__PURE__ */ new Map(),
|
|
2628
|
+
subscribers: [],
|
|
2629
|
+
initialClick: [0, 0],
|
|
2630
|
+
initialHits: [],
|
|
2631
|
+
capturedMap: /* @__PURE__ */ new Map(),
|
|
2632
|
+
lastEvent: React__namespace.createRef(),
|
|
2633
|
+
// Visibility tracking (onFramed, onOccluded, onVisible)
|
|
2634
|
+
visibilityRegistry: /* @__PURE__ */ new Map(),
|
|
2635
|
+
// Occlusion system (WebGPU only)
|
|
2636
|
+
occlusionEnabled: false,
|
|
2637
|
+
occlusionObserver: null,
|
|
2638
|
+
occlusionCache: /* @__PURE__ */ new Map(),
|
|
2639
|
+
helperGroup: null,
|
|
2640
|
+
// Updates
|
|
2641
|
+
active: false,
|
|
2642
|
+
frames: 0,
|
|
2643
|
+
priority: 0,
|
|
2644
|
+
subscribe: (ref, priority, store) => {
|
|
2645
|
+
const internal = get().internal;
|
|
2646
|
+
internal.priority = internal.priority + (priority > 0 ? 1 : 0);
|
|
2647
|
+
internal.subscribers.push({ ref, priority, store });
|
|
2648
|
+
internal.subscribers = internal.subscribers.sort((a, b) => a.priority - b.priority);
|
|
2649
|
+
return () => {
|
|
2650
|
+
const internal2 = get().internal;
|
|
2651
|
+
if (internal2?.subscribers) {
|
|
2652
|
+
internal2.priority = internal2.priority - (priority > 0 ? 1 : 0);
|
|
2653
|
+
internal2.subscribers = internal2.subscribers.filter((s) => s.ref !== ref);
|
|
2654
|
+
}
|
|
2655
|
+
};
|
|
2656
|
+
},
|
|
2657
|
+
// Renderer Storage (single source of truth)
|
|
2658
|
+
actualRenderer: null,
|
|
2659
|
+
// Scheduler for useFrameNext (initialized in renderer.tsx)
|
|
2660
|
+
scheduler: null
|
|
2661
|
+
}
|
|
2662
|
+
};
|
|
2663
|
+
return rootState;
|
|
2664
|
+
});
|
|
2665
|
+
const state = rootStore.getState();
|
|
2666
|
+
Object.defineProperty(state, "gl", {
|
|
2667
|
+
get() {
|
|
2668
|
+
const currentState = rootStore.getState();
|
|
2669
|
+
if (!currentState.isLegacy && currentState.internal.actualRenderer) {
|
|
2670
|
+
const stack = new Error().stack || "";
|
|
2671
|
+
const isInternalAccess = stack.includes("zustand") || stack.includes("setState") || stack.includes("Object.assign") || stack.includes("react-three-fiber/packages/fiber/src/core");
|
|
2672
|
+
if (!isInternalAccess) {
|
|
2673
|
+
const cleanedStack = stack.split("\n").slice(2).join("\n") || "Stack trace unavailable";
|
|
2674
|
+
notifyDepreciated({
|
|
2675
|
+
heading: "Accessing state.gl in WebGPU mode",
|
|
2676
|
+
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
|
|
2677
|
+
});
|
|
2678
|
+
}
|
|
2679
|
+
}
|
|
2680
|
+
return currentState.internal.actualRenderer;
|
|
2681
|
+
},
|
|
2682
|
+
set(value) {
|
|
2683
|
+
rootStore.getState().internal.actualRenderer = value;
|
|
2684
|
+
},
|
|
2685
|
+
enumerable: true,
|
|
2686
|
+
configurable: true
|
|
2687
|
+
});
|
|
2688
|
+
Object.defineProperty(state, "renderer", {
|
|
2689
|
+
get() {
|
|
2690
|
+
return rootStore.getState().internal.actualRenderer;
|
|
2691
|
+
},
|
|
2692
|
+
set(value) {
|
|
2693
|
+
rootStore.getState().internal.actualRenderer = value;
|
|
2694
|
+
},
|
|
2695
|
+
enumerable: true,
|
|
2696
|
+
configurable: true
|
|
2697
|
+
});
|
|
2698
|
+
let oldScene = state.scene;
|
|
2699
|
+
rootStore.subscribe(() => {
|
|
2700
|
+
const currentState = rootStore.getState();
|
|
2701
|
+
const { scene, rootScene, set } = currentState;
|
|
2702
|
+
if (scene !== oldScene) {
|
|
2703
|
+
oldScene = scene;
|
|
2704
|
+
if (scene?.isScene && scene !== rootScene) {
|
|
2705
|
+
set({ rootScene: scene });
|
|
2706
|
+
}
|
|
2707
|
+
}
|
|
2708
|
+
});
|
|
2709
|
+
let oldSize = state.size;
|
|
2710
|
+
let oldDpr = state.viewport.dpr;
|
|
2711
|
+
let oldCamera = state.camera;
|
|
2712
|
+
rootStore.subscribe(() => {
|
|
2713
|
+
const { camera, size, viewport, set, internal } = rootStore.getState();
|
|
2714
|
+
const actualRenderer = internal.actualRenderer;
|
|
2715
|
+
const canvasTarget = internal.canvasTarget;
|
|
2716
|
+
if (size.width !== oldSize.width || size.height !== oldSize.height || viewport.dpr !== oldDpr) {
|
|
2717
|
+
oldSize = size;
|
|
2718
|
+
oldDpr = viewport.dpr;
|
|
2719
|
+
updateCamera(camera, size);
|
|
2720
|
+
if (canvasTarget) {
|
|
2721
|
+
if (viewport.dpr > 0) canvasTarget.setPixelRatio(viewport.dpr);
|
|
2722
|
+
const updateStyle = typeof HTMLCanvasElement !== "undefined" && canvasTarget.domElement instanceof HTMLCanvasElement;
|
|
2723
|
+
canvasTarget.setSize(size.width, size.height, updateStyle);
|
|
2724
|
+
} else {
|
|
2725
|
+
if (viewport.dpr > 0) actualRenderer.setPixelRatio(viewport.dpr);
|
|
2726
|
+
const updateStyle = typeof HTMLCanvasElement !== "undefined" && actualRenderer.domElement instanceof HTMLCanvasElement;
|
|
2727
|
+
actualRenderer.setSize(size.width, size.height, updateStyle);
|
|
2728
|
+
}
|
|
2729
|
+
}
|
|
2730
|
+
if (camera !== oldCamera) {
|
|
2731
|
+
oldCamera = camera;
|
|
2732
|
+
const { rootScene } = rootStore.getState();
|
|
2733
|
+
if (camera && rootScene && !camera.parent) {
|
|
2734
|
+
rootScene.add(camera);
|
|
2735
|
+
}
|
|
2736
|
+
set((state2) => ({ viewport: { ...state2.viewport, ...state2.viewport.getCurrentViewport(camera) } }));
|
|
2737
|
+
const currentState = rootStore.getState();
|
|
2738
|
+
if (currentState.autoUpdateFrustum && camera) {
|
|
2739
|
+
updateFrustum(camera, currentState.frustum);
|
|
2286
2740
|
}
|
|
2287
2741
|
}
|
|
2288
|
-
}
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2742
|
+
});
|
|
2743
|
+
rootStore.subscribe((state2) => invalidate(state2));
|
|
2744
|
+
return rootStore;
|
|
2745
|
+
};
|
|
2746
|
+
|
|
2747
|
+
const memoizedLoaders = /* @__PURE__ */ new WeakMap();
|
|
2748
|
+
const isConstructor$1 = (value) => typeof value === "function" && value?.prototype?.constructor === value;
|
|
2749
|
+
function getLoader(Proto) {
|
|
2750
|
+
if (isConstructor$1(Proto)) {
|
|
2751
|
+
let loader = memoizedLoaders.get(Proto);
|
|
2752
|
+
if (!loader) {
|
|
2753
|
+
loader = new Proto();
|
|
2754
|
+
memoizedLoaders.set(Proto, loader);
|
|
2299
2755
|
}
|
|
2300
|
-
return
|
|
2756
|
+
return loader;
|
|
2301
2757
|
}
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2758
|
+
return Proto;
|
|
2759
|
+
}
|
|
2760
|
+
function loadingFn(extensions, onProgress) {
|
|
2761
|
+
return function(Proto, input) {
|
|
2762
|
+
const loader = getLoader(Proto);
|
|
2763
|
+
if (extensions) extensions(loader);
|
|
2764
|
+
if ("loadAsync" in loader && typeof loader.loadAsync === "function") {
|
|
2765
|
+
return loader.loadAsync(input, onProgress).then((data) => {
|
|
2766
|
+
if (isObject3D(data?.scene)) Object.assign(data, buildGraph(data.scene));
|
|
2767
|
+
return data;
|
|
2768
|
+
});
|
|
2311
2769
|
}
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
*/
|
|
2331
|
-
hasUserJobsInPhase(phase, rootId) {
|
|
2332
|
-
const rootsToCheck = rootId ? [this.roots.get(rootId)].filter(Boolean) : Array.from(this.roots.values());
|
|
2333
|
-
return rootsToCheck.some((root) => {
|
|
2334
|
-
if (!root) return false;
|
|
2335
|
-
for (const job of root.jobs.values()) {
|
|
2336
|
-
if (job.phase === phase && !job.system && job.enabled) return true;
|
|
2337
|
-
}
|
|
2338
|
-
return false;
|
|
2339
|
-
});
|
|
2340
|
-
}
|
|
2341
|
-
//* Utility Methods ================================
|
|
2342
|
-
/**
|
|
2343
|
-
* Generate a unique root ID for automatic root registration.
|
|
2344
|
-
* @returns {string} A unique root ID in the format 'root_N'
|
|
2345
|
-
*/
|
|
2346
|
-
generateRootId() {
|
|
2347
|
-
return `root_${this.nextRootIndex++}`;
|
|
2348
|
-
}
|
|
2349
|
-
/**
|
|
2350
|
-
* Generate a unique job ID.
|
|
2351
|
-
* @returns {string} A unique job ID in the format 'job_N'
|
|
2352
|
-
* @private
|
|
2353
|
-
*/
|
|
2354
|
-
generateJobId() {
|
|
2355
|
-
return `job_${this.nextJobIndex}`;
|
|
2356
|
-
}
|
|
2357
|
-
/**
|
|
2358
|
-
* Normalize before/after constraints to a Set.
|
|
2359
|
-
* Handles undefined, single string, or array inputs.
|
|
2360
|
-
* @param {string | string[] | undefined} value - The constraint value(s)
|
|
2361
|
-
* @returns {Set<string>} Normalized Set of constraint strings
|
|
2362
|
-
* @private
|
|
2363
|
-
*/
|
|
2364
|
-
normalizeConstraints(value) {
|
|
2365
|
-
if (!value) return /* @__PURE__ */ new Set();
|
|
2366
|
-
if (Array.isArray(value)) return new Set(value);
|
|
2367
|
-
return /* @__PURE__ */ new Set([value]);
|
|
2368
|
-
}
|
|
2369
|
-
};
|
|
2370
|
-
//* Static State & Methods (Singleton Usage) ================================
|
|
2371
|
-
//* Cross-Bundle Singleton Key ==============================
|
|
2372
|
-
// Use Symbol.for() to ensure scheduler is shared across bundle boundaries
|
|
2373
|
-
// This prevents issues when mixing imports from @react-three/fiber and @react-three/fiber/webgpu
|
|
2374
|
-
__publicField(_Scheduler, "INSTANCE_KEY", Symbol.for("@react-three/fiber.scheduler"));
|
|
2375
|
-
let Scheduler = _Scheduler;
|
|
2376
|
-
const getScheduler = () => Scheduler.get();
|
|
2377
|
-
if (hmrData) {
|
|
2378
|
-
hmrData.accept?.();
|
|
2770
|
+
return new Promise(
|
|
2771
|
+
(res, reject) => loader.load(
|
|
2772
|
+
input,
|
|
2773
|
+
(data) => {
|
|
2774
|
+
if (isObject3D(data?.scene)) Object.assign(data, buildGraph(data.scene));
|
|
2775
|
+
res(data);
|
|
2776
|
+
},
|
|
2777
|
+
onProgress,
|
|
2778
|
+
(error) => reject(new Error(`Could not load ${input}: ${error?.message}`))
|
|
2779
|
+
)
|
|
2780
|
+
);
|
|
2781
|
+
};
|
|
2782
|
+
}
|
|
2783
|
+
function useLoader(loader, input, extensions, onProgress) {
|
|
2784
|
+
const keys = Array.isArray(input) ? input : [input];
|
|
2785
|
+
const fn = loadingFn(extensions, onProgress);
|
|
2786
|
+
const results = keys.map((key) => suspendReact.suspend(fn, [loader, key], { equal: is.equ }));
|
|
2787
|
+
return Array.isArray(input) ? results : results[0];
|
|
2379
2788
|
}
|
|
2789
|
+
useLoader.preload = function(loader, input, extensions, onProgress) {
|
|
2790
|
+
const keys = Array.isArray(input) ? input : [input];
|
|
2791
|
+
keys.forEach((key) => suspendReact.preload(loadingFn(extensions, onProgress), [loader, key]));
|
|
2792
|
+
};
|
|
2793
|
+
useLoader.clear = function(loader, input) {
|
|
2794
|
+
const keys = Array.isArray(input) ? input : [input];
|
|
2795
|
+
keys.forEach((key) => suspendReact.clear([loader, key]));
|
|
2796
|
+
};
|
|
2797
|
+
useLoader.loader = getLoader;
|
|
2380
2798
|
|
|
2381
2799
|
function useFrame(callback, priorityOrOptions) {
|
|
2382
2800
|
const store = React__namespace.useContext(context);
|
|
@@ -2557,6 +2975,9 @@ function useTexture(input, optionsOrOnLoad) {
|
|
|
2557
2975
|
const textureCache = useThree((state) => state.textures);
|
|
2558
2976
|
const options = typeof optionsOrOnLoad === "function" ? { onLoad: optionsOrOnLoad } : optionsOrOnLoad ?? {};
|
|
2559
2977
|
const { onLoad, cache = false } = options;
|
|
2978
|
+
const onLoadRef = React.useRef(onLoad);
|
|
2979
|
+
onLoadRef.current = onLoad;
|
|
2980
|
+
const onLoadCalledForRef = React.useRef(null);
|
|
2560
2981
|
const urls = React.useMemo(() => getUrls(input), [input]);
|
|
2561
2982
|
const cachedResult = React.useMemo(() => {
|
|
2562
2983
|
if (!cache) return null;
|
|
@@ -2567,9 +2988,13 @@ function useTexture(input, optionsOrOnLoad) {
|
|
|
2567
2988
|
webgpu.TextureLoader,
|
|
2568
2989
|
IsObject(input) ? Object.values(input) : input
|
|
2569
2990
|
);
|
|
2991
|
+
const inputKey = urls.join("\0");
|
|
2570
2992
|
React.useLayoutEffect(() => {
|
|
2571
|
-
if (
|
|
2572
|
-
|
|
2993
|
+
if (cachedResult) return;
|
|
2994
|
+
if (onLoadCalledForRef.current === inputKey) return;
|
|
2995
|
+
onLoadCalledForRef.current = inputKey;
|
|
2996
|
+
onLoadRef.current?.(loadedTextures);
|
|
2997
|
+
}, [cachedResult, loadedTextures, inputKey]);
|
|
2573
2998
|
React.useEffect(() => {
|
|
2574
2999
|
if (cachedResult) return;
|
|
2575
3000
|
if ("initTexture" in renderer) {
|
|
@@ -2736,16 +3161,33 @@ function useTextures() {
|
|
|
2736
3161
|
}, [store]);
|
|
2737
3162
|
}
|
|
2738
3163
|
|
|
2739
|
-
function useRenderTarget(
|
|
3164
|
+
function useRenderTarget(widthOrOptions, heightOrOptions, options) {
|
|
2740
3165
|
const isLegacy = useThree((s) => s.isLegacy);
|
|
2741
3166
|
const size = useThree((s) => s.size);
|
|
3167
|
+
let width;
|
|
3168
|
+
let height;
|
|
3169
|
+
let opts;
|
|
3170
|
+
if (typeof widthOrOptions === "object") {
|
|
3171
|
+
opts = widthOrOptions;
|
|
3172
|
+
} else if (typeof widthOrOptions === "number") {
|
|
3173
|
+
width = widthOrOptions;
|
|
3174
|
+
if (typeof heightOrOptions === "object") {
|
|
3175
|
+
height = widthOrOptions;
|
|
3176
|
+
opts = heightOrOptions;
|
|
3177
|
+
} else if (typeof heightOrOptions === "number") {
|
|
3178
|
+
height = heightOrOptions;
|
|
3179
|
+
opts = options;
|
|
3180
|
+
} else {
|
|
3181
|
+
height = widthOrOptions;
|
|
3182
|
+
}
|
|
3183
|
+
}
|
|
2742
3184
|
return React.useMemo(() => {
|
|
2743
3185
|
const w = width ?? size.width;
|
|
2744
3186
|
const h = height ?? size.height;
|
|
2745
3187
|
{
|
|
2746
|
-
return isLegacy ? new three.WebGLRenderTarget(w, h,
|
|
3188
|
+
return isLegacy ? new three.WebGLRenderTarget(w, h, opts) : new webgpu.RenderTarget(w, h, opts);
|
|
2747
3189
|
}
|
|
2748
|
-
}, [width, height, size.width, size.height,
|
|
3190
|
+
}, [width, height, size.width, size.height, opts, isLegacy]);
|
|
2749
3191
|
}
|
|
2750
3192
|
|
|
2751
3193
|
function useStore() {
|
|
@@ -2795,7 +3237,7 @@ function addTail(callback) {
|
|
|
2795
3237
|
function invalidate(state, frames = 1, stackFrames = false) {
|
|
2796
3238
|
getScheduler().invalidate(frames, stackFrames);
|
|
2797
3239
|
}
|
|
2798
|
-
function advance(timestamp
|
|
3240
|
+
function advance(timestamp) {
|
|
2799
3241
|
getScheduler().step(timestamp);
|
|
2800
3242
|
}
|
|
2801
3243
|
|
|
@@ -14249,6 +14691,7 @@ function swapInstances() {
|
|
|
14249
14691
|
instance.object = instance.props.object ?? new target(...instance.props.args ?? []);
|
|
14250
14692
|
instance.object.__r3f = instance;
|
|
14251
14693
|
setFiberRef(fiber, instance.object);
|
|
14694
|
+
delete instance.appliedOnce;
|
|
14252
14695
|
applyProps(instance.object, instance.props);
|
|
14253
14696
|
if (instance.props.attach) {
|
|
14254
14697
|
attach(parent, instance);
|
|
@@ -14322,8 +14765,22 @@ const reconciler = /* @__PURE__ */ createReconciler({
|
|
|
14322
14765
|
const isTailSibling = fiber.sibling === null || (fiber.flags & Update) === NoFlags;
|
|
14323
14766
|
if (isTailSibling) swapInstances();
|
|
14324
14767
|
},
|
|
14325
|
-
finalizeInitialChildren: () =>
|
|
14326
|
-
|
|
14768
|
+
finalizeInitialChildren: (instance) => {
|
|
14769
|
+
for (const prop in instance.props) {
|
|
14770
|
+
if (isFromRef(instance.props[prop])) return true;
|
|
14771
|
+
}
|
|
14772
|
+
return false;
|
|
14773
|
+
},
|
|
14774
|
+
commitMount(instance) {
|
|
14775
|
+
const resolved = {};
|
|
14776
|
+
for (const prop in instance.props) {
|
|
14777
|
+
const value = instance.props[prop];
|
|
14778
|
+
if (isFromRef(value)) {
|
|
14779
|
+
const ref = value[FROM_REF];
|
|
14780
|
+
if (ref.current != null) resolved[prop] = ref.current;
|
|
14781
|
+
}
|
|
14782
|
+
}
|
|
14783
|
+
if (Object.keys(resolved).length) applyProps(instance.object, resolved);
|
|
14327
14784
|
},
|
|
14328
14785
|
getPublicInstance: (instance) => instance?.object,
|
|
14329
14786
|
prepareForCommit: () => null,
|
|
@@ -14544,6 +15001,9 @@ function createRoot(canvas) {
|
|
|
14544
15001
|
let resolve;
|
|
14545
15002
|
pending = new Promise((_resolve) => resolve = _resolve);
|
|
14546
15003
|
const {
|
|
15004
|
+
id: canvasId,
|
|
15005
|
+
primaryCanvas,
|
|
15006
|
+
scheduler: schedulerConfig,
|
|
14547
15007
|
gl: glConfig,
|
|
14548
15008
|
renderer: rendererConfig,
|
|
14549
15009
|
size: propsSize,
|
|
@@ -14551,10 +15011,7 @@ function createRoot(canvas) {
|
|
|
14551
15011
|
events,
|
|
14552
15012
|
onCreated: onCreatedCallback,
|
|
14553
15013
|
shadows = false,
|
|
14554
|
-
linear = false,
|
|
14555
|
-
flat = false,
|
|
14556
15014
|
textureColorSpace = webgpu.SRGBColorSpace,
|
|
14557
|
-
legacy = false,
|
|
14558
15015
|
orthographic = false,
|
|
14559
15016
|
frameloop = "always",
|
|
14560
15017
|
dpr = [1, 2],
|
|
@@ -14566,7 +15023,8 @@ function createRoot(canvas) {
|
|
|
14566
15023
|
onDropMissed,
|
|
14567
15024
|
autoUpdateFrustum = true,
|
|
14568
15025
|
occlusion = false,
|
|
14569
|
-
_sizeProps
|
|
15026
|
+
_sizeProps,
|
|
15027
|
+
forceEven
|
|
14570
15028
|
} = props;
|
|
14571
15029
|
const state = store.getState();
|
|
14572
15030
|
const defaultGLProps = {
|
|
@@ -14576,7 +15034,8 @@ function createRoot(canvas) {
|
|
|
14576
15034
|
alpha: true
|
|
14577
15035
|
};
|
|
14578
15036
|
const defaultGPUProps = {
|
|
14579
|
-
canvas
|
|
15037
|
+
canvas,
|
|
15038
|
+
antialias: true
|
|
14580
15039
|
};
|
|
14581
15040
|
const wantsGL = (state.isLegacy || glConfig || !R3F_BUILD_WEBGPU || !rendererConfig);
|
|
14582
15041
|
if (glConfig && rendererConfig) {
|
|
@@ -14590,10 +15049,35 @@ function createRoot(canvas) {
|
|
|
14590
15049
|
});
|
|
14591
15050
|
}
|
|
14592
15051
|
let renderer = state.internal.actualRenderer;
|
|
15052
|
+
if (primaryCanvas && wantsGL) {
|
|
15053
|
+
throw new Error(
|
|
15054
|
+
"The `primaryCanvas` prop for multi-canvas rendering cannot be used with WebGL. Remove the `gl` prop or use WebGPU."
|
|
15055
|
+
);
|
|
15056
|
+
}
|
|
14593
15057
|
if (wantsGL && !state.internal.actualRenderer) {
|
|
14594
15058
|
renderer = await resolveRenderer(glConfig, defaultGLProps, three.WebGLRenderer);
|
|
14595
15059
|
state.internal.actualRenderer = renderer;
|
|
14596
|
-
state.set({ isLegacy: true, gl: renderer, renderer });
|
|
15060
|
+
state.set({ isLegacy: true, gl: renderer, renderer, primaryStore: store });
|
|
15061
|
+
} else if (!wantsGL && primaryCanvas && !state.internal.actualRenderer) {
|
|
15062
|
+
const primary = await waitForPrimary(primaryCanvas);
|
|
15063
|
+
renderer = primary.renderer;
|
|
15064
|
+
state.internal.actualRenderer = renderer;
|
|
15065
|
+
const canvasTarget = new webgpu.CanvasTarget(canvas);
|
|
15066
|
+
primary.store.setState((prev) => ({
|
|
15067
|
+
internal: { ...prev.internal, isMultiCanvas: true }
|
|
15068
|
+
}));
|
|
15069
|
+
state.set((prev) => ({
|
|
15070
|
+
webGPUSupported: primary.store.getState().webGPUSupported,
|
|
15071
|
+
renderer,
|
|
15072
|
+
primaryStore: primary.store,
|
|
15073
|
+
internal: {
|
|
15074
|
+
...prev.internal,
|
|
15075
|
+
canvasTarget,
|
|
15076
|
+
isMultiCanvas: true,
|
|
15077
|
+
isSecondary: true,
|
|
15078
|
+
targetId: primaryCanvas
|
|
15079
|
+
}
|
|
15080
|
+
}));
|
|
14597
15081
|
} else if (!wantsGL && !state.internal.actualRenderer) {
|
|
14598
15082
|
renderer = await resolveRenderer(rendererConfig, defaultGPUProps, webgpu.WebGPURenderer);
|
|
14599
15083
|
if (!renderer.hasInitialized?.()) {
|
|
@@ -14602,7 +15086,18 @@ function createRoot(canvas) {
|
|
|
14602
15086
|
const backend = renderer.backend;
|
|
14603
15087
|
const isWebGPUBackend = backend && "isWebGPUBackend" in backend;
|
|
14604
15088
|
state.internal.actualRenderer = renderer;
|
|
14605
|
-
state.set({ webGPUSupported: isWebGPUBackend, renderer });
|
|
15089
|
+
state.set({ webGPUSupported: isWebGPUBackend, renderer, primaryStore: store });
|
|
15090
|
+
if (canvasId && !state.internal.isSecondary) {
|
|
15091
|
+
const canvasTarget = new webgpu.CanvasTarget(canvas);
|
|
15092
|
+
const unregisterPrimary = registerPrimary(canvasId, renderer, store);
|
|
15093
|
+
state.set((prev) => ({
|
|
15094
|
+
internal: {
|
|
15095
|
+
...prev.internal,
|
|
15096
|
+
canvasTarget,
|
|
15097
|
+
unregisterPrimary
|
|
15098
|
+
}
|
|
15099
|
+
}));
|
|
15100
|
+
}
|
|
14606
15101
|
}
|
|
14607
15102
|
let raycaster = state.raycaster;
|
|
14608
15103
|
if (!raycaster) state.set({ raycaster: raycaster = new webgpu.Raycaster() });
|
|
@@ -14611,6 +15106,7 @@ function createRoot(canvas) {
|
|
|
14611
15106
|
if (!is.equ(params, raycaster.params, shallowLoose)) {
|
|
14612
15107
|
applyProps(raycaster, { params: { ...raycaster.params, ...params } });
|
|
14613
15108
|
}
|
|
15109
|
+
let tempCamera = state.camera;
|
|
14614
15110
|
if (!state.camera || state.camera === lastCamera && !is.equ(lastCamera, cameraOptions, shallowLoose)) {
|
|
14615
15111
|
lastCamera = cameraOptions;
|
|
14616
15112
|
const isCamera = cameraOptions?.isCamera;
|
|
@@ -14630,6 +15126,7 @@ function createRoot(canvas) {
|
|
|
14630
15126
|
if (!state.camera && !cameraOptions?.rotation) camera.lookAt(0, 0, 0);
|
|
14631
15127
|
}
|
|
14632
15128
|
state.set({ camera });
|
|
15129
|
+
tempCamera = camera;
|
|
14633
15130
|
raycaster.camera = camera;
|
|
14634
15131
|
}
|
|
14635
15132
|
if (!state.scene) {
|
|
@@ -14647,7 +15144,7 @@ function createRoot(canvas) {
|
|
|
14647
15144
|
rootScene: scene,
|
|
14648
15145
|
internal: { ...prev.internal, container: scene }
|
|
14649
15146
|
}));
|
|
14650
|
-
const camera =
|
|
15147
|
+
const camera = tempCamera;
|
|
14651
15148
|
if (camera && !camera.parent) scene.add(camera);
|
|
14652
15149
|
}
|
|
14653
15150
|
if (events && !state.events.handlers) {
|
|
@@ -14664,6 +15161,9 @@ function createRoot(canvas) {
|
|
|
14664
15161
|
if (_sizeProps !== void 0) {
|
|
14665
15162
|
state.set({ _sizeProps });
|
|
14666
15163
|
}
|
|
15164
|
+
if (forceEven !== void 0 && state.internal.forceEven !== forceEven) {
|
|
15165
|
+
state.set((prev) => ({ internal: { ...prev.internal, forceEven } }));
|
|
15166
|
+
}
|
|
14667
15167
|
const size = computeInitialSize(canvas, propsSize);
|
|
14668
15168
|
if (!state._sizeImperative && !is.equ(size, state.size, shallowLoose)) {
|
|
14669
15169
|
const wasImperative = state._sizeImperative;
|
|
@@ -14693,7 +15193,7 @@ function createRoot(canvas) {
|
|
|
14693
15193
|
const handleXRFrame = (timestamp, frame) => {
|
|
14694
15194
|
const state2 = store.getState();
|
|
14695
15195
|
if (state2.frameloop === "never") return;
|
|
14696
|
-
advance(timestamp
|
|
15196
|
+
advance(timestamp);
|
|
14697
15197
|
};
|
|
14698
15198
|
const actualRenderer = state.internal.actualRenderer;
|
|
14699
15199
|
const handleSessionChange = () => {
|
|
@@ -14705,16 +15205,16 @@ function createRoot(canvas) {
|
|
|
14705
15205
|
};
|
|
14706
15206
|
const xr = {
|
|
14707
15207
|
connect() {
|
|
14708
|
-
const { gl, renderer: renderer2
|
|
14709
|
-
const
|
|
14710
|
-
|
|
14711
|
-
|
|
15208
|
+
const { gl, renderer: renderer2 } = store.getState();
|
|
15209
|
+
const xrManager = (renderer2 || gl).xr;
|
|
15210
|
+
xrManager.addEventListener("sessionstart", handleSessionChange);
|
|
15211
|
+
xrManager.addEventListener("sessionend", handleSessionChange);
|
|
14712
15212
|
},
|
|
14713
15213
|
disconnect() {
|
|
14714
|
-
const { gl, renderer: renderer2
|
|
14715
|
-
const
|
|
14716
|
-
|
|
14717
|
-
|
|
15214
|
+
const { gl, renderer: renderer2 } = store.getState();
|
|
15215
|
+
const xrManager = (renderer2 || gl).xr;
|
|
15216
|
+
xrManager.removeEventListener("sessionstart", handleSessionChange);
|
|
15217
|
+
xrManager.removeEventListener("sessionend", handleSessionChange);
|
|
14718
15218
|
}
|
|
14719
15219
|
};
|
|
14720
15220
|
if (typeof renderer.xr?.addEventListener === "function") xr.connect();
|
|
@@ -14742,34 +15242,9 @@ function createRoot(canvas) {
|
|
|
14742
15242
|
renderer.shadowMap.needsUpdate = true;
|
|
14743
15243
|
}
|
|
14744
15244
|
}
|
|
14745
|
-
{
|
|
14746
|
-
|
|
14747
|
-
|
|
14748
|
-
const flatChanged = flat !== lastConfiguredProps.flat;
|
|
14749
|
-
if (legacyChanged) {
|
|
14750
|
-
if (legacy) {
|
|
14751
|
-
notifyDepreciated({
|
|
14752
|
-
heading: "Legacy Color Management",
|
|
14753
|
-
body: "Legacy color management is deprecated and will be removed in a future version.",
|
|
14754
|
-
link: "https://docs.pmnd.rs/react-three-fiber/api/hooks#useframe"
|
|
14755
|
-
});
|
|
14756
|
-
}
|
|
14757
|
-
}
|
|
14758
|
-
if (legacyChanged) {
|
|
14759
|
-
webgpu.ColorManagement.enabled = !legacy;
|
|
14760
|
-
lastConfiguredProps.legacy = legacy;
|
|
14761
|
-
}
|
|
14762
|
-
if (!configured || linearChanged) {
|
|
14763
|
-
renderer.outputColorSpace = linear ? webgpu.LinearSRGBColorSpace : webgpu.SRGBColorSpace;
|
|
14764
|
-
lastConfiguredProps.linear = linear;
|
|
14765
|
-
}
|
|
14766
|
-
if (!configured || flatChanged) {
|
|
14767
|
-
renderer.toneMapping = flat ? webgpu.NoToneMapping : webgpu.ACESFilmicToneMapping;
|
|
14768
|
-
lastConfiguredProps.flat = flat;
|
|
14769
|
-
}
|
|
14770
|
-
if (legacyChanged && state.legacy !== legacy) state.set(() => ({ legacy }));
|
|
14771
|
-
if (linearChanged && state.linear !== linear) state.set(() => ({ linear }));
|
|
14772
|
-
if (flatChanged && state.flat !== flat) state.set(() => ({ flat }));
|
|
15245
|
+
if (!configured) {
|
|
15246
|
+
renderer.outputColorSpace = webgpu.SRGBColorSpace;
|
|
15247
|
+
renderer.toneMapping = webgpu.ACESFilmicToneMapping;
|
|
14773
15248
|
}
|
|
14774
15249
|
if (textureColorSpace !== lastConfiguredProps.textureColorSpace) {
|
|
14775
15250
|
if (state.textureColorSpace !== textureColorSpace) state.set(() => ({ textureColorSpace }));
|
|
@@ -14787,11 +15262,26 @@ function createRoot(canvas) {
|
|
|
14787
15262
|
const scheduler = getScheduler();
|
|
14788
15263
|
const rootId = state.internal.rootId;
|
|
14789
15264
|
if (!rootId) {
|
|
14790
|
-
const newRootId = scheduler.generateRootId();
|
|
15265
|
+
const newRootId = canvasId || scheduler.generateRootId();
|
|
14791
15266
|
const unregisterRoot = scheduler.registerRoot(newRootId, {
|
|
14792
15267
|
getState: () => store.getState(),
|
|
14793
15268
|
onError: (err) => store.getState().setError(err)
|
|
14794
15269
|
});
|
|
15270
|
+
const unregisterCanvasTarget = scheduler.register(
|
|
15271
|
+
() => {
|
|
15272
|
+
const state2 = store.getState();
|
|
15273
|
+
if (state2.internal.isMultiCanvas && state2.internal.canvasTarget) {
|
|
15274
|
+
const renderer2 = state2.internal.actualRenderer;
|
|
15275
|
+
renderer2.setCanvasTarget(state2.internal.canvasTarget);
|
|
15276
|
+
}
|
|
15277
|
+
},
|
|
15278
|
+
{
|
|
15279
|
+
id: `${newRootId}_canvasTarget`,
|
|
15280
|
+
rootId: newRootId,
|
|
15281
|
+
phase: "start",
|
|
15282
|
+
system: true
|
|
15283
|
+
}
|
|
15284
|
+
);
|
|
14795
15285
|
const unregisterFrustum = scheduler.register(
|
|
14796
15286
|
() => {
|
|
14797
15287
|
const state2 = store.getState();
|
|
@@ -14833,11 +15323,15 @@ function createRoot(canvas) {
|
|
|
14833
15323
|
}
|
|
14834
15324
|
},
|
|
14835
15325
|
{
|
|
14836
|
-
|
|
15326
|
+
// Use canvas ID directly as job ID if available, otherwise use generated rootId
|
|
15327
|
+
id: canvasId || `${newRootId}_render`,
|
|
14837
15328
|
rootId: newRootId,
|
|
14838
15329
|
phase: "render",
|
|
14839
|
-
system: true
|
|
15330
|
+
system: true,
|
|
14840
15331
|
// Internal flag: this is a system job, not user-controlled
|
|
15332
|
+
// Apply scheduler config for render ordering and rate limiting
|
|
15333
|
+
...schedulerConfig?.after && { after: schedulerConfig.after },
|
|
15334
|
+
...schedulerConfig?.fps && { fps: schedulerConfig.fps }
|
|
14841
15335
|
}
|
|
14842
15336
|
);
|
|
14843
15337
|
state.set((state2) => ({
|
|
@@ -14846,6 +15340,7 @@ function createRoot(canvas) {
|
|
|
14846
15340
|
rootId: newRootId,
|
|
14847
15341
|
unregisterRoot: () => {
|
|
14848
15342
|
unregisterRoot();
|
|
15343
|
+
unregisterCanvasTarget();
|
|
14849
15344
|
unregisterFrustum();
|
|
14850
15345
|
unregisterVisibility();
|
|
14851
15346
|
unregisterRender();
|
|
@@ -14904,15 +15399,24 @@ function unmountComponentAtNode(canvas, callback) {
|
|
|
14904
15399
|
const renderer = state.internal.actualRenderer;
|
|
14905
15400
|
const unregisterRoot = state.internal.unregisterRoot;
|
|
14906
15401
|
if (unregisterRoot) unregisterRoot();
|
|
15402
|
+
const unregisterPrimary = state.internal.unregisterPrimary;
|
|
15403
|
+
if (unregisterPrimary) unregisterPrimary();
|
|
15404
|
+
const canvasTarget = state.internal.canvasTarget;
|
|
15405
|
+
if (canvasTarget?.dispose) canvasTarget.dispose();
|
|
14907
15406
|
state.events.disconnect?.();
|
|
14908
15407
|
cleanupHelperGroup(root.store);
|
|
14909
|
-
renderer
|
|
14910
|
-
|
|
14911
|
-
|
|
15408
|
+
if (state.isLegacy && renderer) {
|
|
15409
|
+
;
|
|
15410
|
+
renderer.renderLists?.dispose?.();
|
|
15411
|
+
renderer.forceContextLoss?.();
|
|
15412
|
+
}
|
|
15413
|
+
if (!state.internal.isSecondary) {
|
|
15414
|
+
if (renderer?.xr) state.xr.disconnect();
|
|
15415
|
+
}
|
|
14912
15416
|
dispose(state.scene);
|
|
14913
15417
|
_roots.delete(canvas);
|
|
14914
15418
|
if (callback) callback(canvas);
|
|
14915
|
-
} catch
|
|
15419
|
+
} catch {
|
|
14916
15420
|
}
|
|
14917
15421
|
}, 500);
|
|
14918
15422
|
}
|
|
@@ -14920,36 +15424,34 @@ function unmountComponentAtNode(canvas, callback) {
|
|
|
14920
15424
|
}
|
|
14921
15425
|
}
|
|
14922
15426
|
function createPortal(children, container, state) {
|
|
14923
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
15427
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Portal, { children, container, state });
|
|
14924
15428
|
}
|
|
14925
|
-
function
|
|
15429
|
+
function Portal({ children, container, state }) {
|
|
14926
15430
|
const isRef = React.useCallback((obj) => obj && "current" in obj, []);
|
|
14927
|
-
const [resolvedContainer,
|
|
15431
|
+
const [resolvedContainer, _setResolvedContainer] = React.useState(() => {
|
|
14928
15432
|
if (isRef(container)) return container.current ?? null;
|
|
14929
15433
|
return container;
|
|
14930
15434
|
});
|
|
15435
|
+
const setResolvedContainer = React.useCallback(
|
|
15436
|
+
(newContainer) => {
|
|
15437
|
+
if (!newContainer || newContainer === resolvedContainer) return;
|
|
15438
|
+
_setResolvedContainer(isRef(newContainer) ? newContainer.current : newContainer);
|
|
15439
|
+
},
|
|
15440
|
+
[resolvedContainer, _setResolvedContainer, isRef]
|
|
15441
|
+
);
|
|
14931
15442
|
React.useMemo(() => {
|
|
14932
|
-
if (isRef(container)) {
|
|
14933
|
-
|
|
14934
|
-
|
|
14935
|
-
|
|
14936
|
-
const updated = container.current;
|
|
14937
|
-
if (updated && updated !== resolvedContainer) {
|
|
14938
|
-
setResolvedContainer(updated);
|
|
14939
|
-
}
|
|
14940
|
-
});
|
|
14941
|
-
} else if (current !== resolvedContainer) {
|
|
14942
|
-
setResolvedContainer(current);
|
|
14943
|
-
}
|
|
14944
|
-
} else if (container !== resolvedContainer) {
|
|
14945
|
-
setResolvedContainer(container);
|
|
15443
|
+
if (isRef(container) && !container.current) {
|
|
15444
|
+
return queueMicrotask(() => {
|
|
15445
|
+
setResolvedContainer(container.current);
|
|
15446
|
+
});
|
|
14946
15447
|
}
|
|
14947
|
-
|
|
15448
|
+
setResolvedContainer(container);
|
|
15449
|
+
}, [container, isRef, setResolvedContainer]);
|
|
14948
15450
|
if (!resolvedContainer) return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, {});
|
|
14949
15451
|
const portalKey = resolvedContainer.uuid ?? `portal-${resolvedContainer.id ?? "unknown"}`;
|
|
14950
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
15452
|
+
return /* @__PURE__ */ jsxRuntime.jsx(PortalInner, { children, container: resolvedContainer, state }, portalKey);
|
|
14951
15453
|
}
|
|
14952
|
-
function
|
|
15454
|
+
function PortalInner({ state = {}, children, container }) {
|
|
14953
15455
|
const { events, size, injectScene = true, ...rest } = state;
|
|
14954
15456
|
const previousRoot = useStore();
|
|
14955
15457
|
const [raycaster] = React.useState(() => new webgpu.Raycaster());
|
|
@@ -14970,11 +15472,12 @@ function Portal({ state = {}, children, container }) {
|
|
|
14970
15472
|
};
|
|
14971
15473
|
}, [portalScene, container, injectScene]);
|
|
14972
15474
|
const inject = useMutableCallback((rootState, injectState) => {
|
|
15475
|
+
const resolvedSize = { ...rootState.size, ...injectState.size, ...size };
|
|
14973
15476
|
let viewport = void 0;
|
|
14974
|
-
if (injectState.camera && size) {
|
|
15477
|
+
if (injectState.camera && (size || injectState.size)) {
|
|
14975
15478
|
const camera = injectState.camera;
|
|
14976
|
-
viewport = rootState.viewport.getCurrentViewport(camera, new webgpu.Vector3(),
|
|
14977
|
-
if (camera !== rootState.camera) updateCamera(camera,
|
|
15479
|
+
viewport = rootState.viewport.getCurrentViewport(camera, new webgpu.Vector3(), resolvedSize);
|
|
15480
|
+
if (camera !== rootState.camera) updateCamera(camera, resolvedSize);
|
|
14978
15481
|
}
|
|
14979
15482
|
return {
|
|
14980
15483
|
// The intersect consists of the previous root state
|
|
@@ -14991,7 +15494,7 @@ function Portal({ state = {}, children, container }) {
|
|
|
14991
15494
|
previousRoot,
|
|
14992
15495
|
// Events, size and viewport can be overridden by the inject layer
|
|
14993
15496
|
events: { ...rootState.events, ...injectState.events, ...events },
|
|
14994
|
-
size:
|
|
15497
|
+
size: resolvedSize,
|
|
14995
15498
|
viewport: { ...rootState.viewport, ...viewport },
|
|
14996
15499
|
// Layers are allowed to override events
|
|
14997
15500
|
setEvents: (events2) => injectState.set((state2) => ({ ...state2, events: { ...state2.events, ...events2 } })),
|
|
@@ -15025,15 +15528,13 @@ function CanvasImpl({
|
|
|
15025
15528
|
fallback,
|
|
15026
15529
|
resize,
|
|
15027
15530
|
style,
|
|
15531
|
+
id,
|
|
15028
15532
|
gl,
|
|
15029
|
-
renderer,
|
|
15533
|
+
renderer: rendererProp,
|
|
15030
15534
|
events = createPointerEvents,
|
|
15031
15535
|
eventSource,
|
|
15032
15536
|
eventPrefix,
|
|
15033
15537
|
shadows,
|
|
15034
|
-
linear,
|
|
15035
|
-
flat,
|
|
15036
|
-
legacy,
|
|
15037
15538
|
orthographic,
|
|
15038
15539
|
frameloop,
|
|
15039
15540
|
dpr,
|
|
@@ -15048,10 +15549,43 @@ function CanvasImpl({
|
|
|
15048
15549
|
hmr,
|
|
15049
15550
|
width,
|
|
15050
15551
|
height,
|
|
15552
|
+
background,
|
|
15553
|
+
forceEven,
|
|
15051
15554
|
...props
|
|
15052
15555
|
}) {
|
|
15556
|
+
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 };
|
|
15557
|
+
const renderer = Object.keys(rendererConfig).length > 0 ? rendererConfig : rendererProp;
|
|
15053
15558
|
React__namespace.useMemo(() => extend(THREE), []);
|
|
15054
15559
|
const Bridge = useBridge();
|
|
15560
|
+
const backgroundProps = React__namespace.useMemo(() => {
|
|
15561
|
+
if (!background) return null;
|
|
15562
|
+
if (typeof background === "object" && !background.isColor) {
|
|
15563
|
+
const { backgroundMap, envMap, files, preset, ...rest } = background;
|
|
15564
|
+
return {
|
|
15565
|
+
...rest,
|
|
15566
|
+
preset,
|
|
15567
|
+
files: envMap || files,
|
|
15568
|
+
backgroundFiles: backgroundMap,
|
|
15569
|
+
background: true
|
|
15570
|
+
};
|
|
15571
|
+
}
|
|
15572
|
+
if (typeof background === "number") {
|
|
15573
|
+
return { color: background, background: true };
|
|
15574
|
+
}
|
|
15575
|
+
if (typeof background === "string") {
|
|
15576
|
+
if (background in presetsObj) {
|
|
15577
|
+
return { preset: background, background: true };
|
|
15578
|
+
}
|
|
15579
|
+
if (/^(https?:\/\/|\/|\.\/|\.\.\/)|\\.(hdr|exr|jpg|jpeg|png|webp|gif)$/i.test(background)) {
|
|
15580
|
+
return { files: background, background: true };
|
|
15581
|
+
}
|
|
15582
|
+
return { color: background, background: true };
|
|
15583
|
+
}
|
|
15584
|
+
if (background.isColor) {
|
|
15585
|
+
return { color: background, background: true };
|
|
15586
|
+
}
|
|
15587
|
+
return null;
|
|
15588
|
+
}, [background]);
|
|
15055
15589
|
const hasInitialSizeRef = React__namespace.useRef(false);
|
|
15056
15590
|
const measureConfig = React__namespace.useMemo(() => {
|
|
15057
15591
|
if (!hasInitialSizeRef.current) {
|
|
@@ -15068,15 +15602,20 @@ function CanvasImpl({
|
|
|
15068
15602
|
};
|
|
15069
15603
|
}, [resize, hasInitialSizeRef.current]);
|
|
15070
15604
|
const [containerRef, containerRect] = useMeasure__default(measureConfig);
|
|
15071
|
-
const effectiveSize = React__namespace.useMemo(
|
|
15072
|
-
|
|
15073
|
-
|
|
15074
|
-
|
|
15605
|
+
const effectiveSize = React__namespace.useMemo(() => {
|
|
15606
|
+
let w = width ?? containerRect.width;
|
|
15607
|
+
let h = height ?? containerRect.height;
|
|
15608
|
+
if (forceEven) {
|
|
15609
|
+
w = Math.ceil(w / 2) * 2;
|
|
15610
|
+
h = Math.ceil(h / 2) * 2;
|
|
15611
|
+
}
|
|
15612
|
+
return {
|
|
15613
|
+
width: w,
|
|
15614
|
+
height: h,
|
|
15075
15615
|
top: containerRect.top,
|
|
15076
15616
|
left: containerRect.left
|
|
15077
|
-
}
|
|
15078
|
-
|
|
15079
|
-
);
|
|
15617
|
+
};
|
|
15618
|
+
}, [width, height, containerRect, forceEven]);
|
|
15080
15619
|
if (!hasInitialSizeRef.current && effectiveSize.width > 0 && effectiveSize.height > 0) {
|
|
15081
15620
|
hasInitialSizeRef.current = true;
|
|
15082
15621
|
}
|
|
@@ -15116,14 +15655,14 @@ function CanvasImpl({
|
|
|
15116
15655
|
async function run() {
|
|
15117
15656
|
if (!effectActiveRef.current || !root.current) return;
|
|
15118
15657
|
await root.current.configure({
|
|
15658
|
+
id,
|
|
15659
|
+
primaryCanvas,
|
|
15660
|
+
scheduler,
|
|
15119
15661
|
gl,
|
|
15120
15662
|
renderer,
|
|
15121
15663
|
scene,
|
|
15122
15664
|
events,
|
|
15123
15665
|
shadows,
|
|
15124
|
-
linear,
|
|
15125
|
-
flat,
|
|
15126
|
-
legacy,
|
|
15127
15666
|
orthographic,
|
|
15128
15667
|
frameloop,
|
|
15129
15668
|
dpr,
|
|
@@ -15133,6 +15672,7 @@ function CanvasImpl({
|
|
|
15133
15672
|
size: effectiveSize,
|
|
15134
15673
|
// Store size props for reset functionality
|
|
15135
15674
|
_sizeProps: width !== void 0 || height !== void 0 ? { width, height } : null,
|
|
15675
|
+
forceEven,
|
|
15136
15676
|
// Pass mutable reference to onPointerMissed so it's free to update
|
|
15137
15677
|
onPointerMissed: (...args) => handlePointerMissed.current?.(...args),
|
|
15138
15678
|
onDragOverMissed: (...args) => handleDragOverMissed.current?.(...args),
|
|
@@ -15156,7 +15696,10 @@ function CanvasImpl({
|
|
|
15156
15696
|
});
|
|
15157
15697
|
if (!effectActiveRef.current || !root.current) return;
|
|
15158
15698
|
root.current.render(
|
|
15159
|
-
/* @__PURE__ */ jsxRuntime.jsx(Bridge, { children: /* @__PURE__ */ jsxRuntime.jsx(ErrorBoundary, { set: setError, children: /* @__PURE__ */ jsxRuntime.
|
|
15699
|
+
/* @__PURE__ */ jsxRuntime.jsx(Bridge, { children: /* @__PURE__ */ jsxRuntime.jsx(ErrorBoundary, { set: setError, children: /* @__PURE__ */ jsxRuntime.jsxs(React__namespace.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx(Block, { set: setBlock }), children: [
|
|
15700
|
+
backgroundProps && /* @__PURE__ */ jsxRuntime.jsx(Environment, { ...backgroundProps }),
|
|
15701
|
+
children ?? null
|
|
15702
|
+
] }) }) })
|
|
15160
15703
|
);
|
|
15161
15704
|
}
|
|
15162
15705
|
run();
|
|
@@ -15183,14 +15726,16 @@ function CanvasImpl({
|
|
|
15183
15726
|
const canvas = canvasRef.current;
|
|
15184
15727
|
if (!canvas) return;
|
|
15185
15728
|
const handleHMR = () => {
|
|
15186
|
-
|
|
15187
|
-
|
|
15188
|
-
rootEntry
|
|
15189
|
-
|
|
15190
|
-
|
|
15191
|
-
|
|
15192
|
-
|
|
15193
|
-
|
|
15729
|
+
queueMicrotask(() => {
|
|
15730
|
+
const rootEntry = _roots.get(canvas);
|
|
15731
|
+
if (rootEntry?.store) {
|
|
15732
|
+
rootEntry.store.setState((state) => ({
|
|
15733
|
+
nodes: {},
|
|
15734
|
+
uniforms: {},
|
|
15735
|
+
_hmrVersion: state._hmrVersion + 1
|
|
15736
|
+
}));
|
|
15737
|
+
}
|
|
15738
|
+
});
|
|
15194
15739
|
};
|
|
15195
15740
|
if (typeof ({ url: (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)) }) !== "undefined" && undefined) {
|
|
15196
15741
|
const hot = undefined;
|
|
@@ -15219,7 +15764,7 @@ function CanvasImpl({
|
|
|
15219
15764
|
...style
|
|
15220
15765
|
},
|
|
15221
15766
|
...props,
|
|
15222
|
-
children: /* @__PURE__ */ jsxRuntime.jsx("div", { ref: containerRef, className: "r3f-canvas-container", style: { width: "100%", height: "100%" }, children: /* @__PURE__ */ jsxRuntime.jsx("canvas", { ref: canvasRef, className: "r3f-canvas", style: { display: "block" }, children: fallback }) })
|
|
15767
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { ref: containerRef, className: "r3f-canvas-container", style: { width: "100%", height: "100%" }, children: /* @__PURE__ */ jsxRuntime.jsx("canvas", { ref: canvasRef, id, className: "r3f-canvas", style: { display: "block" }, children: fallback }) })
|
|
15223
15768
|
}
|
|
15224
15769
|
);
|
|
15225
15770
|
}
|
|
@@ -15231,8 +15776,15 @@ extend(THREE);
|
|
|
15231
15776
|
|
|
15232
15777
|
exports.Block = Block;
|
|
15233
15778
|
exports.Canvas = Canvas;
|
|
15779
|
+
exports.Environment = Environment;
|
|
15780
|
+
exports.EnvironmentCube = EnvironmentCube;
|
|
15781
|
+
exports.EnvironmentMap = EnvironmentMap;
|
|
15782
|
+
exports.EnvironmentPortal = EnvironmentPortal;
|
|
15234
15783
|
exports.ErrorBoundary = ErrorBoundary;
|
|
15784
|
+
exports.FROM_REF = FROM_REF;
|
|
15235
15785
|
exports.IsObject = IsObject;
|
|
15786
|
+
exports.ONCE = ONCE;
|
|
15787
|
+
exports.Portal = Portal;
|
|
15236
15788
|
exports.R3F_BUILD_LEGACY = R3F_BUILD_LEGACY;
|
|
15237
15789
|
exports.R3F_BUILD_WEBGPU = R3F_BUILD_WEBGPU;
|
|
15238
15790
|
exports.REACT_INTERNAL_PROPS = REACT_INTERNAL_PROPS;
|
|
@@ -15262,30 +15814,41 @@ exports.events = createPointerEvents;
|
|
|
15262
15814
|
exports.extend = extend;
|
|
15263
15815
|
exports.findInitialRoot = findInitialRoot;
|
|
15264
15816
|
exports.flushSync = flushSync;
|
|
15817
|
+
exports.fromRef = fromRef;
|
|
15265
15818
|
exports.getInstanceProps = getInstanceProps;
|
|
15819
|
+
exports.getPrimary = getPrimary;
|
|
15820
|
+
exports.getPrimaryIds = getPrimaryIds;
|
|
15266
15821
|
exports.getRootState = getRootState;
|
|
15267
15822
|
exports.getScheduler = getScheduler;
|
|
15268
15823
|
exports.getUuidPrefix = getUuidPrefix;
|
|
15269
15824
|
exports.hasConstructor = hasConstructor;
|
|
15825
|
+
exports.hasPrimary = hasPrimary;
|
|
15270
15826
|
exports.invalidate = invalidate;
|
|
15271
15827
|
exports.invalidateInstance = invalidateInstance;
|
|
15272
15828
|
exports.is = is;
|
|
15273
15829
|
exports.isColorRepresentation = isColorRepresentation;
|
|
15274
15830
|
exports.isCopyable = isCopyable;
|
|
15831
|
+
exports.isFromRef = isFromRef;
|
|
15275
15832
|
exports.isObject3D = isObject3D;
|
|
15833
|
+
exports.isOnce = isOnce;
|
|
15276
15834
|
exports.isOrthographicCamera = isOrthographicCamera;
|
|
15277
15835
|
exports.isRef = isRef;
|
|
15278
15836
|
exports.isRenderer = isRenderer;
|
|
15279
15837
|
exports.isTexture = isTexture;
|
|
15280
15838
|
exports.isVectorLike = isVectorLike;
|
|
15839
|
+
exports.once = once;
|
|
15281
15840
|
exports.prepare = prepare;
|
|
15841
|
+
exports.presetsObj = presetsObj;
|
|
15282
15842
|
exports.reconciler = reconciler;
|
|
15843
|
+
exports.registerPrimary = registerPrimary;
|
|
15283
15844
|
exports.removeInteractivity = removeInteractivity;
|
|
15284
15845
|
exports.resolve = resolve;
|
|
15285
15846
|
exports.unmountComponentAtNode = unmountComponentAtNode;
|
|
15847
|
+
exports.unregisterPrimary = unregisterPrimary;
|
|
15286
15848
|
exports.updateCamera = updateCamera;
|
|
15287
15849
|
exports.updateFrustum = updateFrustum;
|
|
15288
15850
|
exports.useBridge = useBridge;
|
|
15851
|
+
exports.useEnvironment = useEnvironment;
|
|
15289
15852
|
exports.useFrame = useFrame;
|
|
15290
15853
|
exports.useGraph = useGraph;
|
|
15291
15854
|
exports.useInstanceHandle = useInstanceHandle;
|
|
@@ -15297,3 +15860,4 @@ exports.useStore = useStore;
|
|
|
15297
15860
|
exports.useTexture = useTexture;
|
|
15298
15861
|
exports.useTextures = useTextures;
|
|
15299
15862
|
exports.useThree = useThree;
|
|
15863
|
+
exports.waitForPrimary = waitForPrimary;
|