@react-three/fiber 10.0.0-alpha.1 → 10.0.0-canary.1b98c17
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 +1499 -614
- package/dist/index.d.cts +2130 -1274
- package/dist/index.d.mts +2130 -1274
- package/dist/index.d.ts +2130 -1274
- package/dist/index.mjs +1483 -618
- package/dist/legacy.cjs +1481 -621
- package/dist/legacy.d.cts +2131 -1275
- package/dist/legacy.d.mts +2131 -1275
- package/dist/legacy.d.ts +2131 -1275
- package/dist/legacy.mjs +1465 -625
- package/dist/webgpu/index.cjs +2098 -601
- package/dist/webgpu/index.d.cts +2391 -1300
- package/dist/webgpu/index.d.mts +2391 -1300
- package/dist/webgpu/index.d.ts +2391 -1300
- package/dist/webgpu/index.mjs +2074 -604
- package/package.json +7 -5
- package/react-reconciler/constants.js +1 -9
- package/react-reconciler/index.js +4 -20
- package/readme.md +244 -318
package/dist/legacy.mjs
CHANGED
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
import * as three from 'three';
|
|
2
|
-
import { WebGLRenderTarget, Frustum, Matrix4, Group, BoxGeometry, MeshBasicNodeMaterial, Mesh, Node, NodeUpdateType, Layers, RGBAFormat, UnsignedByteType, Vector3, Vector2, TextureLoader, Texture as Texture$1,
|
|
3
|
-
import { jsx, Fragment } from 'react/jsx-runtime';
|
|
2
|
+
import { WebGLRenderTarget, CubeReflectionMapping, EquirectangularReflectionMapping, CubeTextureLoader, Scene, WebGLCubeRenderTarget, HalfFloatType, Color, Frustum, Matrix4, Group, BoxGeometry, MeshBasicNodeMaterial, Mesh, Node, NodeUpdateType, Layers, SRGBColorSpace, RGBAFormat, UnsignedByteType, Vector3, Vector2, TextureLoader, Texture as Texture$1, Raycaster, OrthographicCamera, PerspectiveCamera, PCFShadowMap, VSMShadowMap, BasicShadowMap, ACESFilmicToneMapping, WebGLRenderer } from 'three';
|
|
3
|
+
import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
|
|
4
4
|
import * as React from 'react';
|
|
5
|
-
import React__default, {
|
|
5
|
+
import React__default, { useLayoutEffect, useRef, useMemo, useEffect, useContext, useImperativeHandle, useCallback, useState } from 'react';
|
|
6
6
|
import useMeasure from 'react-use-measure';
|
|
7
7
|
import { useFiber, useContextBridge, traverseFiber, FiberProvider } from 'its-fine';
|
|
8
|
+
import { useThree as useThree$1, useLoader as useLoader$1, useFrame as useFrame$1, createPortal as createPortal$1, applyProps as applyProps$1, extend as extend$1 } from '@react-three/fiber';
|
|
9
|
+
import { GroundedSkybox } from 'three/examples/jsm/objects/GroundedSkybox.js';
|
|
10
|
+
import { HDRLoader } from 'three/examples/jsm/loaders/HDRLoader.js';
|
|
11
|
+
import { EXRLoader } from 'three/examples/jsm/loaders/EXRLoader.js';
|
|
12
|
+
import { UltraHDRLoader } from 'three/examples/jsm/loaders/UltraHDRLoader.js';
|
|
13
|
+
import { GainMapLoader } from '@monogrid/gainmap-js';
|
|
8
14
|
import Tb, { unstable_scheduleCallback, unstable_IdlePriority } from 'scheduler';
|
|
9
15
|
import { createWithEqualityFn } from 'zustand/traditional';
|
|
10
16
|
import { suspend, preload, clear } from 'suspend-react';
|
|
@@ -45,6 +51,389 @@ const THREE = /*#__PURE__*/_mergeNamespaces({
|
|
|
45
51
|
WebGPURenderer: WebGPURenderer
|
|
46
52
|
}, [three]);
|
|
47
53
|
|
|
54
|
+
const primaryRegistry = /* @__PURE__ */ new Map();
|
|
55
|
+
const pendingSubscribers = /* @__PURE__ */ new Map();
|
|
56
|
+
function registerPrimary(id, renderer, store) {
|
|
57
|
+
if (primaryRegistry.has(id)) {
|
|
58
|
+
console.warn(`Canvas with id="${id}" already registered. Overwriting.`);
|
|
59
|
+
}
|
|
60
|
+
const entry = { renderer, store };
|
|
61
|
+
primaryRegistry.set(id, entry);
|
|
62
|
+
const subscribers = pendingSubscribers.get(id);
|
|
63
|
+
if (subscribers) {
|
|
64
|
+
subscribers.forEach((callback) => callback(entry));
|
|
65
|
+
pendingSubscribers.delete(id);
|
|
66
|
+
}
|
|
67
|
+
return () => {
|
|
68
|
+
const currentEntry = primaryRegistry.get(id);
|
|
69
|
+
if (currentEntry?.renderer === renderer) {
|
|
70
|
+
primaryRegistry.delete(id);
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
function getPrimary(id) {
|
|
75
|
+
return primaryRegistry.get(id);
|
|
76
|
+
}
|
|
77
|
+
function waitForPrimary(id, timeout = 5e3) {
|
|
78
|
+
const existing = primaryRegistry.get(id);
|
|
79
|
+
if (existing) {
|
|
80
|
+
return Promise.resolve(existing);
|
|
81
|
+
}
|
|
82
|
+
return new Promise((resolve, reject) => {
|
|
83
|
+
const timeoutId = setTimeout(() => {
|
|
84
|
+
const subscribers = pendingSubscribers.get(id);
|
|
85
|
+
if (subscribers) {
|
|
86
|
+
const index = subscribers.indexOf(callback);
|
|
87
|
+
if (index !== -1) subscribers.splice(index, 1);
|
|
88
|
+
if (subscribers.length === 0) pendingSubscribers.delete(id);
|
|
89
|
+
}
|
|
90
|
+
reject(new Error(`Timeout waiting for canvas with id="${id}". Make sure a <Canvas id="${id}"> is mounted.`));
|
|
91
|
+
}, timeout);
|
|
92
|
+
const callback = (entry) => {
|
|
93
|
+
clearTimeout(timeoutId);
|
|
94
|
+
resolve(entry);
|
|
95
|
+
};
|
|
96
|
+
if (!pendingSubscribers.has(id)) {
|
|
97
|
+
pendingSubscribers.set(id, []);
|
|
98
|
+
}
|
|
99
|
+
pendingSubscribers.get(id).push(callback);
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
function hasPrimary(id) {
|
|
103
|
+
return primaryRegistry.has(id);
|
|
104
|
+
}
|
|
105
|
+
function unregisterPrimary(id) {
|
|
106
|
+
primaryRegistry.delete(id);
|
|
107
|
+
}
|
|
108
|
+
function getPrimaryIds() {
|
|
109
|
+
return Array.from(primaryRegistry.keys());
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const presetsObj = {
|
|
113
|
+
apartment: "lebombo_1k.hdr",
|
|
114
|
+
city: "potsdamer_platz_1k.hdr",
|
|
115
|
+
dawn: "kiara_1_dawn_1k.hdr",
|
|
116
|
+
forest: "forest_slope_1k.hdr",
|
|
117
|
+
lobby: "st_fagans_interior_1k.hdr",
|
|
118
|
+
night: "dikhololo_night_1k.hdr",
|
|
119
|
+
park: "rooitou_park_1k.hdr",
|
|
120
|
+
studio: "studio_small_03_1k.hdr",
|
|
121
|
+
sunset: "venice_sunset_1k.hdr",
|
|
122
|
+
warehouse: "empty_warehouse_01_1k.hdr"
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
const CUBEMAP_ROOT = "https://raw.githack.com/pmndrs/drei-assets/456060a26bbeb8fdf79326f224b6d99b8bcce736/hdri/";
|
|
126
|
+
const isArray = (arr) => Array.isArray(arr);
|
|
127
|
+
const defaultFiles = ["/px.png", "/nx.png", "/py.png", "/ny.png", "/pz.png", "/nz.png"];
|
|
128
|
+
function useEnvironment({
|
|
129
|
+
files = defaultFiles,
|
|
130
|
+
path = "",
|
|
131
|
+
preset = void 0,
|
|
132
|
+
colorSpace = void 0,
|
|
133
|
+
extensions
|
|
134
|
+
} = {}) {
|
|
135
|
+
if (preset) {
|
|
136
|
+
validatePreset(preset);
|
|
137
|
+
files = presetsObj[preset];
|
|
138
|
+
path = CUBEMAP_ROOT;
|
|
139
|
+
}
|
|
140
|
+
const multiFile = isArray(files);
|
|
141
|
+
const { extension, isCubemap } = getExtension(files);
|
|
142
|
+
const loader = getLoader$1(extension);
|
|
143
|
+
if (!loader) throw new Error("useEnvironment: Unrecognized file extension: " + files);
|
|
144
|
+
const renderer = useThree$1((state) => state.renderer);
|
|
145
|
+
useLayoutEffect(() => {
|
|
146
|
+
if (extension !== "webp" && extension !== "jpg" && extension !== "jpeg") return;
|
|
147
|
+
function clearGainmapTexture() {
|
|
148
|
+
useLoader$1.clear(loader, multiFile ? [files] : files);
|
|
149
|
+
}
|
|
150
|
+
renderer.domElement.addEventListener("webglcontextlost", clearGainmapTexture, { once: true });
|
|
151
|
+
}, [extension, files, loader, multiFile, renderer.domElement]);
|
|
152
|
+
const loaderResult = useLoader$1(
|
|
153
|
+
loader,
|
|
154
|
+
multiFile ? [files] : files,
|
|
155
|
+
(loader2) => {
|
|
156
|
+
if (extension === "webp" || extension === "jpg" || extension === "jpeg") {
|
|
157
|
+
loader2.setRenderer?.(renderer);
|
|
158
|
+
}
|
|
159
|
+
loader2.setPath?.(path);
|
|
160
|
+
if (extensions) extensions(loader2);
|
|
161
|
+
}
|
|
162
|
+
);
|
|
163
|
+
let texture = multiFile ? (
|
|
164
|
+
// @ts-ignore
|
|
165
|
+
loaderResult[0]
|
|
166
|
+
) : loaderResult;
|
|
167
|
+
if (extension === "jpg" || extension === "jpeg" || extension === "webp") {
|
|
168
|
+
texture = texture.renderTarget?.texture;
|
|
169
|
+
}
|
|
170
|
+
texture.mapping = isCubemap ? CubeReflectionMapping : EquirectangularReflectionMapping;
|
|
171
|
+
texture.colorSpace = colorSpace ?? (isCubemap ? "srgb" : "srgb-linear");
|
|
172
|
+
return texture;
|
|
173
|
+
}
|
|
174
|
+
const preloadDefaultOptions = {
|
|
175
|
+
files: defaultFiles,
|
|
176
|
+
path: "",
|
|
177
|
+
preset: void 0,
|
|
178
|
+
extensions: void 0
|
|
179
|
+
};
|
|
180
|
+
useEnvironment.preload = (preloadOptions) => {
|
|
181
|
+
const options = { ...preloadDefaultOptions, ...preloadOptions };
|
|
182
|
+
let { files, path = "" } = options;
|
|
183
|
+
const { preset, extensions } = options;
|
|
184
|
+
if (preset) {
|
|
185
|
+
validatePreset(preset);
|
|
186
|
+
files = presetsObj[preset];
|
|
187
|
+
path = CUBEMAP_ROOT;
|
|
188
|
+
}
|
|
189
|
+
const { extension } = getExtension(files);
|
|
190
|
+
if (extension === "webp" || extension === "jpg" || extension === "jpeg") {
|
|
191
|
+
throw new Error("useEnvironment: Preloading gainmaps is not supported");
|
|
192
|
+
}
|
|
193
|
+
const loader = getLoader$1(extension);
|
|
194
|
+
if (!loader) throw new Error("useEnvironment: Unrecognized file extension: " + files);
|
|
195
|
+
useLoader$1.preload(loader, isArray(files) ? [files] : files, (loader2) => {
|
|
196
|
+
loader2.setPath?.(path);
|
|
197
|
+
if (extensions) extensions(loader2);
|
|
198
|
+
});
|
|
199
|
+
};
|
|
200
|
+
const clearDefaultOptins = {
|
|
201
|
+
files: defaultFiles,
|
|
202
|
+
preset: void 0
|
|
203
|
+
};
|
|
204
|
+
useEnvironment.clear = (clearOptions) => {
|
|
205
|
+
const options = { ...clearDefaultOptins, ...clearOptions };
|
|
206
|
+
let { files } = options;
|
|
207
|
+
const { preset } = options;
|
|
208
|
+
if (preset) {
|
|
209
|
+
validatePreset(preset);
|
|
210
|
+
files = presetsObj[preset];
|
|
211
|
+
}
|
|
212
|
+
const { extension } = getExtension(files);
|
|
213
|
+
const loader = getLoader$1(extension);
|
|
214
|
+
if (!loader) throw new Error("useEnvironment: Unrecognized file extension: " + files);
|
|
215
|
+
useLoader$1.clear(loader, isArray(files) ? [files] : files);
|
|
216
|
+
};
|
|
217
|
+
function validatePreset(preset) {
|
|
218
|
+
if (!(preset in presetsObj)) throw new Error("Preset must be one of: " + Object.keys(presetsObj).join(", "));
|
|
219
|
+
}
|
|
220
|
+
function getExtension(files) {
|
|
221
|
+
const isCubemap = isArray(files) && files.length === 6;
|
|
222
|
+
const isGainmap = isArray(files) && files.length === 3 && files.some((file) => file.endsWith("json"));
|
|
223
|
+
const firstEntry = isArray(files) ? files[0] : files;
|
|
224
|
+
const extension = isCubemap ? "cube" : isGainmap ? "webp" : firstEntry.startsWith("data:application/exr") ? "exr" : firstEntry.startsWith("data:application/hdr") ? "hdr" : firstEntry.startsWith("data:image/jpeg") ? "jpg" : firstEntry.split(".").pop()?.split("?")?.shift()?.toLowerCase();
|
|
225
|
+
return { extension, isCubemap, isGainmap };
|
|
226
|
+
}
|
|
227
|
+
function getLoader$1(extension) {
|
|
228
|
+
const loader = extension === "cube" ? CubeTextureLoader : extension === "hdr" ? HDRLoader : extension === "exr" ? EXRLoader : extension === "jpg" || extension === "jpeg" ? UltraHDRLoader : extension === "webp" ? GainMapLoader : null;
|
|
229
|
+
return loader;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
const isRef$1 = (obj) => obj.current && obj.current.isScene;
|
|
233
|
+
const resolveScene = (scene) => isRef$1(scene) ? scene.current : scene;
|
|
234
|
+
function setEnvProps(background, scene, defaultScene, texture, sceneProps = {}) {
|
|
235
|
+
sceneProps = {
|
|
236
|
+
backgroundBlurriness: 0,
|
|
237
|
+
backgroundIntensity: 1,
|
|
238
|
+
backgroundRotation: [0, 0, 0],
|
|
239
|
+
environmentIntensity: 1,
|
|
240
|
+
environmentRotation: [0, 0, 0],
|
|
241
|
+
...sceneProps
|
|
242
|
+
};
|
|
243
|
+
const target = resolveScene(scene || defaultScene);
|
|
244
|
+
const oldbg = target.background;
|
|
245
|
+
const oldenv = target.environment;
|
|
246
|
+
const oldSceneProps = {
|
|
247
|
+
// @ts-ignore
|
|
248
|
+
backgroundBlurriness: target.backgroundBlurriness,
|
|
249
|
+
// @ts-ignore
|
|
250
|
+
backgroundIntensity: target.backgroundIntensity,
|
|
251
|
+
// @ts-ignore
|
|
252
|
+
backgroundRotation: target.backgroundRotation?.clone?.() ?? [0, 0, 0],
|
|
253
|
+
// @ts-ignore
|
|
254
|
+
environmentIntensity: target.environmentIntensity,
|
|
255
|
+
// @ts-ignore
|
|
256
|
+
environmentRotation: target.environmentRotation?.clone?.() ?? [0, 0, 0]
|
|
257
|
+
};
|
|
258
|
+
if (background !== "only") target.environment = texture;
|
|
259
|
+
if (background) target.background = texture;
|
|
260
|
+
applyProps$1(target, sceneProps);
|
|
261
|
+
return () => {
|
|
262
|
+
if (background !== "only") target.environment = oldenv;
|
|
263
|
+
if (background) target.background = oldbg;
|
|
264
|
+
applyProps$1(target, oldSceneProps);
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
function EnvironmentMap({ scene, background = false, map, ...config }) {
|
|
268
|
+
const defaultScene = useThree$1((state) => state.scene);
|
|
269
|
+
React.useLayoutEffect(() => {
|
|
270
|
+
if (map) return setEnvProps(background, scene, defaultScene, map, config);
|
|
271
|
+
});
|
|
272
|
+
return null;
|
|
273
|
+
}
|
|
274
|
+
function EnvironmentCube({
|
|
275
|
+
background = false,
|
|
276
|
+
scene,
|
|
277
|
+
blur,
|
|
278
|
+
backgroundBlurriness,
|
|
279
|
+
backgroundIntensity,
|
|
280
|
+
backgroundRotation,
|
|
281
|
+
environmentIntensity,
|
|
282
|
+
environmentRotation,
|
|
283
|
+
...rest
|
|
284
|
+
}) {
|
|
285
|
+
const texture = useEnvironment(rest);
|
|
286
|
+
const defaultScene = useThree$1((state) => state.scene);
|
|
287
|
+
React.useLayoutEffect(() => {
|
|
288
|
+
return setEnvProps(background, scene, defaultScene, texture, {
|
|
289
|
+
backgroundBlurriness: blur ?? backgroundBlurriness,
|
|
290
|
+
backgroundIntensity,
|
|
291
|
+
backgroundRotation,
|
|
292
|
+
environmentIntensity,
|
|
293
|
+
environmentRotation
|
|
294
|
+
});
|
|
295
|
+
});
|
|
296
|
+
React.useEffect(() => {
|
|
297
|
+
return () => {
|
|
298
|
+
texture.dispose();
|
|
299
|
+
};
|
|
300
|
+
}, [texture]);
|
|
301
|
+
return null;
|
|
302
|
+
}
|
|
303
|
+
function EnvironmentPortal({
|
|
304
|
+
children,
|
|
305
|
+
near = 0.1,
|
|
306
|
+
far = 1e3,
|
|
307
|
+
resolution = 256,
|
|
308
|
+
frames = 1,
|
|
309
|
+
map,
|
|
310
|
+
background = false,
|
|
311
|
+
blur,
|
|
312
|
+
backgroundBlurriness,
|
|
313
|
+
backgroundIntensity,
|
|
314
|
+
backgroundRotation,
|
|
315
|
+
environmentIntensity,
|
|
316
|
+
environmentRotation,
|
|
317
|
+
scene,
|
|
318
|
+
files,
|
|
319
|
+
path,
|
|
320
|
+
preset = void 0,
|
|
321
|
+
extensions
|
|
322
|
+
}) {
|
|
323
|
+
const gl = useThree$1((state) => state.gl);
|
|
324
|
+
const defaultScene = useThree$1((state) => state.scene);
|
|
325
|
+
const camera = React.useRef(null);
|
|
326
|
+
const [virtualScene] = React.useState(() => new Scene());
|
|
327
|
+
const fbo = React.useMemo(() => {
|
|
328
|
+
const fbo2 = new WebGLCubeRenderTarget(resolution);
|
|
329
|
+
fbo2.texture.type = HalfFloatType;
|
|
330
|
+
return fbo2;
|
|
331
|
+
}, [resolution]);
|
|
332
|
+
React.useEffect(() => {
|
|
333
|
+
return () => {
|
|
334
|
+
fbo.dispose();
|
|
335
|
+
};
|
|
336
|
+
}, [fbo]);
|
|
337
|
+
React.useLayoutEffect(() => {
|
|
338
|
+
if (frames === 1) {
|
|
339
|
+
const autoClear = gl.autoClear;
|
|
340
|
+
gl.autoClear = true;
|
|
341
|
+
camera.current.update(gl, virtualScene);
|
|
342
|
+
gl.autoClear = autoClear;
|
|
343
|
+
}
|
|
344
|
+
return setEnvProps(background, scene, defaultScene, fbo.texture, {
|
|
345
|
+
backgroundBlurriness: blur ?? backgroundBlurriness,
|
|
346
|
+
backgroundIntensity,
|
|
347
|
+
backgroundRotation,
|
|
348
|
+
environmentIntensity,
|
|
349
|
+
environmentRotation
|
|
350
|
+
});
|
|
351
|
+
}, [
|
|
352
|
+
children,
|
|
353
|
+
virtualScene,
|
|
354
|
+
fbo.texture,
|
|
355
|
+
scene,
|
|
356
|
+
defaultScene,
|
|
357
|
+
background,
|
|
358
|
+
frames,
|
|
359
|
+
gl,
|
|
360
|
+
blur,
|
|
361
|
+
backgroundBlurriness,
|
|
362
|
+
backgroundIntensity,
|
|
363
|
+
backgroundRotation,
|
|
364
|
+
environmentIntensity,
|
|
365
|
+
environmentRotation
|
|
366
|
+
]);
|
|
367
|
+
let count = 1;
|
|
368
|
+
useFrame$1(() => {
|
|
369
|
+
if (frames === Infinity || count < frames) {
|
|
370
|
+
const autoClear = gl.autoClear;
|
|
371
|
+
gl.autoClear = true;
|
|
372
|
+
camera.current.update(gl, virtualScene);
|
|
373
|
+
gl.autoClear = autoClear;
|
|
374
|
+
count++;
|
|
375
|
+
}
|
|
376
|
+
});
|
|
377
|
+
return /* @__PURE__ */ jsx(Fragment, { children: createPortal$1(
|
|
378
|
+
/* @__PURE__ */ jsxs(Fragment, { children: [
|
|
379
|
+
children,
|
|
380
|
+
/* @__PURE__ */ jsx("cubeCamera", { ref: camera, args: [near, far, fbo] }),
|
|
381
|
+
files || preset ? /* @__PURE__ */ jsx(EnvironmentCube, { background: true, files, preset, path, extensions }) : map ? /* @__PURE__ */ jsx(EnvironmentMap, { background: true, map, extensions }) : null
|
|
382
|
+
] }),
|
|
383
|
+
virtualScene
|
|
384
|
+
) });
|
|
385
|
+
}
|
|
386
|
+
function EnvironmentGround(props) {
|
|
387
|
+
const textureDefault = useEnvironment(props);
|
|
388
|
+
const texture = props.map || textureDefault;
|
|
389
|
+
React.useMemo(() => extend$1({ GroundProjectedEnvImpl: GroundedSkybox }), []);
|
|
390
|
+
React.useEffect(() => {
|
|
391
|
+
return () => {
|
|
392
|
+
textureDefault.dispose();
|
|
393
|
+
};
|
|
394
|
+
}, [textureDefault]);
|
|
395
|
+
const height = props.ground?.height ?? 15;
|
|
396
|
+
const radius = props.ground?.radius ?? 60;
|
|
397
|
+
const scale = props.ground?.scale ?? 1e3;
|
|
398
|
+
const args = React.useMemo(
|
|
399
|
+
() => [texture, height, radius],
|
|
400
|
+
[texture, height, radius]
|
|
401
|
+
);
|
|
402
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
403
|
+
/* @__PURE__ */ jsx(EnvironmentMap, { ...props, map: texture }),
|
|
404
|
+
/* @__PURE__ */ jsx("groundProjectedEnvImpl", { args, scale })
|
|
405
|
+
] });
|
|
406
|
+
}
|
|
407
|
+
function EnvironmentColor({ color, scene }) {
|
|
408
|
+
const defaultScene = useThree$1((state) => state.scene);
|
|
409
|
+
React.useLayoutEffect(() => {
|
|
410
|
+
if (color === void 0) return;
|
|
411
|
+
const target = resolveScene(scene || defaultScene);
|
|
412
|
+
const oldBg = target.background;
|
|
413
|
+
target.background = new Color(color);
|
|
414
|
+
return () => {
|
|
415
|
+
target.background = oldBg;
|
|
416
|
+
};
|
|
417
|
+
});
|
|
418
|
+
return null;
|
|
419
|
+
}
|
|
420
|
+
function EnvironmentDualSource(props) {
|
|
421
|
+
const { backgroundFiles, ...envProps } = props;
|
|
422
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
423
|
+
/* @__PURE__ */ jsx(EnvironmentCube, { ...envProps, background: false }),
|
|
424
|
+
/* @__PURE__ */ jsx(EnvironmentCube, { ...props, files: backgroundFiles, background: "only" })
|
|
425
|
+
] });
|
|
426
|
+
}
|
|
427
|
+
function Environment(props) {
|
|
428
|
+
if (props.color && !props.files && !props.preset && !props.map) {
|
|
429
|
+
return /* @__PURE__ */ jsx(EnvironmentColor, { ...props });
|
|
430
|
+
}
|
|
431
|
+
if (props.backgroundFiles && props.backgroundFiles !== props.files) {
|
|
432
|
+
return /* @__PURE__ */ jsx(EnvironmentDualSource, { ...props });
|
|
433
|
+
}
|
|
434
|
+
return props.ground ? /* @__PURE__ */ jsx(EnvironmentGround, { ...props }) : props.map ? /* @__PURE__ */ jsx(EnvironmentMap, { ...props }) : props.children ? /* @__PURE__ */ jsx(EnvironmentPortal, { ...props }) : /* @__PURE__ */ jsx(EnvironmentCube, { ...props });
|
|
435
|
+
}
|
|
436
|
+
|
|
48
437
|
var __defProp$2 = Object.defineProperty;
|
|
49
438
|
var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
50
439
|
var __publicField$2 = (obj, key, value) => __defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
@@ -224,7 +613,8 @@ function prepare(target, root, type, props) {
|
|
|
224
613
|
object,
|
|
225
614
|
eventCount: 0,
|
|
226
615
|
handlers: {},
|
|
227
|
-
isHidden: false
|
|
616
|
+
isHidden: false,
|
|
617
|
+
deferredRefs: []
|
|
228
618
|
};
|
|
229
619
|
if (object) object.__r3f = instance;
|
|
230
620
|
}
|
|
@@ -273,7 +663,7 @@ function createOcclusionObserverNode(store, uniform) {
|
|
|
273
663
|
let occlusionSetupPromise = null;
|
|
274
664
|
function enableOcclusion(store) {
|
|
275
665
|
const state = store.getState();
|
|
276
|
-
const { internal, renderer
|
|
666
|
+
const { internal, renderer } = state;
|
|
277
667
|
if (internal.occlusionEnabled || occlusionSetupPromise) return;
|
|
278
668
|
const hasOcclusionSupport = typeof renderer?.isOccluded === "function";
|
|
279
669
|
if (!hasOcclusionSupport) {
|
|
@@ -436,6 +826,22 @@ function hasVisibilityHandlers(handlers) {
|
|
|
436
826
|
return !!(handlers.onFramed || handlers.onOccluded || handlers.onVisible);
|
|
437
827
|
}
|
|
438
828
|
|
|
829
|
+
const FROM_REF = Symbol.for("@react-three/fiber.fromRef");
|
|
830
|
+
function fromRef(ref) {
|
|
831
|
+
return { [FROM_REF]: ref };
|
|
832
|
+
}
|
|
833
|
+
function isFromRef(value) {
|
|
834
|
+
return value !== null && typeof value === "object" && FROM_REF in value;
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
const ONCE = Symbol.for("@react-three/fiber.once");
|
|
838
|
+
function once(...args) {
|
|
839
|
+
return { [ONCE]: args.length ? args : true };
|
|
840
|
+
}
|
|
841
|
+
function isOnce(value) {
|
|
842
|
+
return value !== null && typeof value === "object" && ONCE in value;
|
|
843
|
+
}
|
|
844
|
+
|
|
439
845
|
const RESERVED_PROPS = [
|
|
440
846
|
"children",
|
|
441
847
|
"key",
|
|
@@ -506,7 +912,7 @@ function getMemoizedPrototype(root) {
|
|
|
506
912
|
ctor = new root.constructor();
|
|
507
913
|
MEMOIZED_PROTOTYPES.set(root.constructor, ctor);
|
|
508
914
|
}
|
|
509
|
-
} catch
|
|
915
|
+
} catch {
|
|
510
916
|
}
|
|
511
917
|
return ctor;
|
|
512
918
|
}
|
|
@@ -537,7 +943,7 @@ function applyProps(object, props) {
|
|
|
537
943
|
const rootState = instance && findInitialRoot(instance).getState();
|
|
538
944
|
const prevHandlers = instance?.eventCount;
|
|
539
945
|
for (const prop in props) {
|
|
540
|
-
|
|
946
|
+
const value = props[prop];
|
|
541
947
|
if (RESERVED_PROPS.includes(prop)) continue;
|
|
542
948
|
if (instance && EVENT_REGEX.test(prop)) {
|
|
543
949
|
if (typeof value === "function") instance.handlers[prop] = value;
|
|
@@ -552,6 +958,25 @@ function applyProps(object, props) {
|
|
|
552
958
|
continue;
|
|
553
959
|
}
|
|
554
960
|
if (value === void 0) continue;
|
|
961
|
+
if (isFromRef(value)) {
|
|
962
|
+
instance?.deferredRefs?.push({ prop, ref: value[FROM_REF] });
|
|
963
|
+
continue;
|
|
964
|
+
}
|
|
965
|
+
if (isOnce(value)) {
|
|
966
|
+
if (instance?.appliedOnce?.has(prop)) continue;
|
|
967
|
+
if (instance) {
|
|
968
|
+
instance.appliedOnce ?? (instance.appliedOnce = /* @__PURE__ */ new Set());
|
|
969
|
+
instance.appliedOnce.add(prop);
|
|
970
|
+
}
|
|
971
|
+
const { root: targetRoot, key: targetKey } = resolve(object, prop);
|
|
972
|
+
const args = value[ONCE];
|
|
973
|
+
if (typeof targetRoot[targetKey] === "function") {
|
|
974
|
+
targetRoot[targetKey](...args === true ? [] : args);
|
|
975
|
+
} else if (args !== true && args.length > 0) {
|
|
976
|
+
targetRoot[targetKey] = args[0];
|
|
977
|
+
}
|
|
978
|
+
continue;
|
|
979
|
+
}
|
|
555
980
|
let { root, key, target } = resolve(object, prop);
|
|
556
981
|
if (target === void 0 && (typeof root !== "object" || root === null)) {
|
|
557
982
|
throw Error(`R3F: Cannot set "${prop}". Ensure it is an object before setting "${key}".`);
|
|
@@ -574,7 +999,10 @@ function applyProps(object, props) {
|
|
|
574
999
|
else target.set(value);
|
|
575
1000
|
} else {
|
|
576
1001
|
root[key] = value;
|
|
577
|
-
if (
|
|
1002
|
+
if (key.endsWith("Node") && root.isMaterial) {
|
|
1003
|
+
root.needsUpdate = true;
|
|
1004
|
+
}
|
|
1005
|
+
if (rootState && rootState.renderer?.outputColorSpace === SRGBColorSpace && colorMaps.includes(key) && isTexture(value) && root[key]?.isTexture && // sRGB textures must be RGBA8 since r137 https://github.com/mrdoob/three.js/pull/23129
|
|
578
1006
|
root[key].format === RGBAFormat && root[key].type === UnsignedByteType) {
|
|
579
1007
|
root[key].colorSpace = rootState.textureColorSpace;
|
|
580
1008
|
}
|
|
@@ -607,38 +1035,60 @@ function applyProps(object, props) {
|
|
|
607
1035
|
return object;
|
|
608
1036
|
}
|
|
609
1037
|
|
|
1038
|
+
const DEFAULT_POINTER_ID = 0;
|
|
1039
|
+
const XR_POINTER_ID_START = 1e3;
|
|
1040
|
+
function getPointerState(internal, pointerId) {
|
|
1041
|
+
let state = internal.pointerMap.get(pointerId);
|
|
1042
|
+
if (!state) {
|
|
1043
|
+
state = {
|
|
1044
|
+
hovered: /* @__PURE__ */ new Map(),
|
|
1045
|
+
captured: /* @__PURE__ */ new Map(),
|
|
1046
|
+
initialClick: [0, 0],
|
|
1047
|
+
initialHits: []
|
|
1048
|
+
};
|
|
1049
|
+
internal.pointerMap.set(pointerId, state);
|
|
1050
|
+
}
|
|
1051
|
+
return state;
|
|
1052
|
+
}
|
|
1053
|
+
function getPointerId(event) {
|
|
1054
|
+
return "pointerId" in event ? event.pointerId : DEFAULT_POINTER_ID;
|
|
1055
|
+
}
|
|
610
1056
|
function makeId(event) {
|
|
611
1057
|
return (event.eventObject || event.object).uuid + "/" + event.index + event.instanceId;
|
|
612
1058
|
}
|
|
613
|
-
function releaseInternalPointerCapture(
|
|
614
|
-
const
|
|
1059
|
+
function releaseInternalPointerCapture(internal, obj, pointerId) {
|
|
1060
|
+
const pointerState = internal.pointerMap.get(pointerId);
|
|
1061
|
+
if (!pointerState) return;
|
|
1062
|
+
const captureData = pointerState.captured.get(obj);
|
|
615
1063
|
if (captureData) {
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
capturedMap.delete(pointerId);
|
|
619
|
-
captureData.target.releasePointerCapture(pointerId);
|
|
620
|
-
}
|
|
1064
|
+
pointerState.captured.delete(obj);
|
|
1065
|
+
captureData.target.releasePointerCapture(pointerId);
|
|
621
1066
|
}
|
|
622
1067
|
}
|
|
623
1068
|
function removeInteractivity(store, object) {
|
|
624
1069
|
const { internal } = store.getState();
|
|
625
1070
|
internal.interaction = internal.interaction.filter((o) => o !== object);
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
1071
|
+
for (const [pointerId, pointerState] of internal.pointerMap) {
|
|
1072
|
+
pointerState.initialHits = pointerState.initialHits.filter((o) => o !== object);
|
|
1073
|
+
pointerState.hovered.forEach((value, key) => {
|
|
1074
|
+
if (value.eventObject === object || value.object === object) {
|
|
1075
|
+
pointerState.hovered.delete(key);
|
|
1076
|
+
}
|
|
1077
|
+
});
|
|
1078
|
+
if (pointerState.captured.has(object)) {
|
|
1079
|
+
releaseInternalPointerCapture(internal, object, pointerId);
|
|
630
1080
|
}
|
|
631
|
-
}
|
|
632
|
-
internal.capturedMap.forEach((captures, pointerId) => {
|
|
633
|
-
releaseInternalPointerCapture(internal.capturedMap, object, captures, pointerId);
|
|
634
|
-
});
|
|
1081
|
+
}
|
|
635
1082
|
unregisterVisibility(store, object);
|
|
636
1083
|
}
|
|
637
1084
|
function createEvents(store) {
|
|
638
|
-
function calculateDistance(event) {
|
|
1085
|
+
function calculateDistance(event, pointerId) {
|
|
639
1086
|
const { internal } = store.getState();
|
|
640
|
-
const
|
|
641
|
-
|
|
1087
|
+
const pointerState = internal.pointerMap.get(pointerId);
|
|
1088
|
+
if (!pointerState) return 0;
|
|
1089
|
+
const [initialX, initialY] = pointerState.initialClick;
|
|
1090
|
+
const dx = event.offsetX - initialX;
|
|
1091
|
+
const dy = event.offsetY - initialY;
|
|
642
1092
|
return Math.round(Math.sqrt(dx * dx + dy * dy));
|
|
643
1093
|
}
|
|
644
1094
|
function filterPointerEvents(objects) {
|
|
@@ -674,6 +1124,15 @@ function createEvents(store) {
|
|
|
674
1124
|
return state2.raycaster.camera ? state2.raycaster.intersectObject(obj, true) : [];
|
|
675
1125
|
}
|
|
676
1126
|
let hits = eventsObjects.flatMap(handleRaycast).sort((a, b) => {
|
|
1127
|
+
const aInteractivePriority = a.object.userData?.interactivePriority;
|
|
1128
|
+
const bInteractivePriority = b.object.userData?.interactivePriority;
|
|
1129
|
+
if (aInteractivePriority !== void 0 || bInteractivePriority !== void 0) {
|
|
1130
|
+
if (aInteractivePriority !== void 0 && bInteractivePriority === void 0) return -1;
|
|
1131
|
+
if (bInteractivePriority !== void 0 && aInteractivePriority === void 0) return 1;
|
|
1132
|
+
if (aInteractivePriority !== bInteractivePriority) {
|
|
1133
|
+
return (bInteractivePriority ?? 0) - (aInteractivePriority ?? 0);
|
|
1134
|
+
}
|
|
1135
|
+
}
|
|
677
1136
|
const aState = getRootState(a.object);
|
|
678
1137
|
const bState = getRootState(b.object);
|
|
679
1138
|
const aPriority = aState?.events?.priority ?? 1;
|
|
@@ -689,14 +1148,19 @@ function createEvents(store) {
|
|
|
689
1148
|
for (const hit of hits) {
|
|
690
1149
|
let eventObject = hit.object;
|
|
691
1150
|
while (eventObject) {
|
|
692
|
-
if (eventObject.__r3f?.eventCount)
|
|
1151
|
+
if (eventObject.__r3f?.eventCount) {
|
|
693
1152
|
intersections.push({ ...hit, eventObject });
|
|
1153
|
+
}
|
|
694
1154
|
eventObject = eventObject.parent;
|
|
695
1155
|
}
|
|
696
1156
|
}
|
|
697
|
-
if ("pointerId" in event
|
|
698
|
-
|
|
699
|
-
|
|
1157
|
+
if ("pointerId" in event) {
|
|
1158
|
+
const pointerId = event.pointerId;
|
|
1159
|
+
const pointerState = state.internal.pointerMap.get(pointerId);
|
|
1160
|
+
if (pointerState?.captured.size) {
|
|
1161
|
+
for (const captureData of pointerState.captured.values()) {
|
|
1162
|
+
if (!duplicates.has(makeId(captureData.intersection))) intersections.push(captureData.intersection);
|
|
1163
|
+
}
|
|
700
1164
|
}
|
|
701
1165
|
}
|
|
702
1166
|
return intersections;
|
|
@@ -709,28 +1173,26 @@ function createEvents(store) {
|
|
|
709
1173
|
if (state) {
|
|
710
1174
|
const { raycaster, pointer, camera, internal } = state;
|
|
711
1175
|
const unprojectedPoint = new Vector3(pointer.x, pointer.y, 0).unproject(camera);
|
|
712
|
-
const hasPointerCapture = (id) =>
|
|
1176
|
+
const hasPointerCapture = (id) => {
|
|
1177
|
+
const pointerState = internal.pointerMap.get(id);
|
|
1178
|
+
return pointerState?.captured.has(hit.eventObject) ?? false;
|
|
1179
|
+
};
|
|
713
1180
|
const setPointerCapture = (id) => {
|
|
714
1181
|
const captureData = { intersection: hit, target: event.target };
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
} else {
|
|
718
|
-
internal.capturedMap.set(id, /* @__PURE__ */ new Map([[hit.eventObject, captureData]]));
|
|
719
|
-
}
|
|
1182
|
+
const pointerState = getPointerState(internal, id);
|
|
1183
|
+
pointerState.captured.set(hit.eventObject, captureData);
|
|
720
1184
|
event.target.setPointerCapture(id);
|
|
721
1185
|
};
|
|
722
1186
|
const releasePointerCapture = (id) => {
|
|
723
|
-
|
|
724
|
-
if (captures) {
|
|
725
|
-
releaseInternalPointerCapture(internal.capturedMap, hit.eventObject, captures, id);
|
|
726
|
-
}
|
|
1187
|
+
releaseInternalPointerCapture(internal, hit.eventObject, id);
|
|
727
1188
|
};
|
|
728
|
-
|
|
729
|
-
for (
|
|
730
|
-
|
|
1189
|
+
const extractEventProps = {};
|
|
1190
|
+
for (const prop in event) {
|
|
1191
|
+
const property = event[prop];
|
|
731
1192
|
if (typeof property !== "function") extractEventProps[prop] = property;
|
|
732
1193
|
}
|
|
733
|
-
|
|
1194
|
+
const eventPointerId = "pointerId" in event ? event.pointerId : void 0;
|
|
1195
|
+
const raycastEvent = {
|
|
734
1196
|
...hit,
|
|
735
1197
|
...extractEventProps,
|
|
736
1198
|
pointer,
|
|
@@ -740,18 +1202,19 @@ function createEvents(store) {
|
|
|
740
1202
|
unprojectedPoint,
|
|
741
1203
|
ray: raycaster.ray,
|
|
742
1204
|
camera,
|
|
1205
|
+
pointerId: eventPointerId,
|
|
743
1206
|
// Hijack stopPropagation, which just sets a flag
|
|
744
1207
|
stopPropagation() {
|
|
745
|
-
const
|
|
1208
|
+
const pointerState = eventPointerId !== void 0 ? internal.pointerMap.get(eventPointerId) : void 0;
|
|
746
1209
|
if (
|
|
747
1210
|
// ...if this pointer hasn't been captured
|
|
748
|
-
!
|
|
749
|
-
|
|
1211
|
+
!pointerState?.captured.size || // ... or if the hit object is capturing the pointer
|
|
1212
|
+
pointerState.captured.has(hit.eventObject)
|
|
750
1213
|
) {
|
|
751
1214
|
raycastEvent.stopped = localState.stopped = true;
|
|
752
|
-
if (
|
|
1215
|
+
if (pointerState?.hovered.size && Array.from(pointerState.hovered.values()).find((i) => i.eventObject === hit.eventObject)) {
|
|
753
1216
|
const higher = intersections.slice(0, intersections.indexOf(hit));
|
|
754
|
-
cancelPointer([...higher, hit]);
|
|
1217
|
+
cancelPointer([...higher, hit], eventPointerId);
|
|
755
1218
|
}
|
|
756
1219
|
}
|
|
757
1220
|
},
|
|
@@ -767,15 +1230,18 @@ function createEvents(store) {
|
|
|
767
1230
|
}
|
|
768
1231
|
return intersections;
|
|
769
1232
|
}
|
|
770
|
-
function cancelPointer(intersections) {
|
|
1233
|
+
function cancelPointer(intersections, pointerId) {
|
|
771
1234
|
const { internal } = store.getState();
|
|
772
|
-
|
|
1235
|
+
const pid = pointerId ?? DEFAULT_POINTER_ID;
|
|
1236
|
+
const pointerState = internal.pointerMap.get(pid);
|
|
1237
|
+
if (!pointerState) return;
|
|
1238
|
+
for (const [hoveredId, hoveredObj] of pointerState.hovered) {
|
|
773
1239
|
if (!intersections.length || !intersections.find(
|
|
774
1240
|
(hit) => hit.object === hoveredObj.object && hit.index === hoveredObj.index && hit.instanceId === hoveredObj.instanceId
|
|
775
1241
|
)) {
|
|
776
1242
|
const eventObject = hoveredObj.eventObject;
|
|
777
1243
|
const instance = eventObject.__r3f;
|
|
778
|
-
|
|
1244
|
+
pointerState.hovered.delete(hoveredId);
|
|
779
1245
|
if (instance?.eventCount) {
|
|
780
1246
|
const handlers = instance.handlers;
|
|
781
1247
|
const data = { ...hoveredObj, intersections };
|
|
@@ -804,41 +1270,118 @@ function createEvents(store) {
|
|
|
804
1270
|
instance?.handlers.onDropMissed?.(event);
|
|
805
1271
|
}
|
|
806
1272
|
}
|
|
1273
|
+
function cleanupPointer(pointerId) {
|
|
1274
|
+
const { internal } = store.getState();
|
|
1275
|
+
const pointerState = internal.pointerMap.get(pointerId);
|
|
1276
|
+
if (pointerState) {
|
|
1277
|
+
for (const [, hoveredObj] of pointerState.hovered) {
|
|
1278
|
+
const eventObject = hoveredObj.eventObject;
|
|
1279
|
+
const instance = eventObject.__r3f;
|
|
1280
|
+
if (instance?.eventCount) {
|
|
1281
|
+
const handlers = instance.handlers;
|
|
1282
|
+
const data = { ...hoveredObj, intersections: [] };
|
|
1283
|
+
handlers.onPointerOut?.(data);
|
|
1284
|
+
handlers.onPointerLeave?.(data);
|
|
1285
|
+
}
|
|
1286
|
+
}
|
|
1287
|
+
internal.pointerMap.delete(pointerId);
|
|
1288
|
+
}
|
|
1289
|
+
internal.pointerDirty.delete(pointerId);
|
|
1290
|
+
}
|
|
1291
|
+
function processDeferredPointer(event, pointerId) {
|
|
1292
|
+
const state = store.getState();
|
|
1293
|
+
const { internal } = state;
|
|
1294
|
+
if (!state.events.enabled) return;
|
|
1295
|
+
const filter = filterPointerEvents;
|
|
1296
|
+
const hits = intersect(event, filter);
|
|
1297
|
+
cancelPointer(hits, pointerId);
|
|
1298
|
+
function onIntersect(data) {
|
|
1299
|
+
const eventObject = data.eventObject;
|
|
1300
|
+
const instance = eventObject.__r3f;
|
|
1301
|
+
if (!instance?.eventCount) return;
|
|
1302
|
+
const handlers = instance.handlers;
|
|
1303
|
+
if (handlers.onPointerOver || handlers.onPointerEnter || handlers.onPointerOut || handlers.onPointerLeave) {
|
|
1304
|
+
const id = makeId(data);
|
|
1305
|
+
const pointerState = getPointerState(internal, pointerId);
|
|
1306
|
+
const hoveredItem = pointerState.hovered.get(id);
|
|
1307
|
+
if (!hoveredItem) {
|
|
1308
|
+
pointerState.hovered.set(id, data);
|
|
1309
|
+
handlers.onPointerOver?.(data);
|
|
1310
|
+
handlers.onPointerEnter?.(data);
|
|
1311
|
+
} else if (hoveredItem.stopped) {
|
|
1312
|
+
data.stopPropagation();
|
|
1313
|
+
}
|
|
1314
|
+
}
|
|
1315
|
+
handlers.onPointerMove?.(data);
|
|
1316
|
+
}
|
|
1317
|
+
handleIntersects(hits, event, 0, onIntersect);
|
|
1318
|
+
}
|
|
807
1319
|
function handlePointer(name) {
|
|
808
1320
|
switch (name) {
|
|
809
1321
|
case "onPointerLeave":
|
|
810
|
-
case "onPointerCancel":
|
|
811
1322
|
case "onDragLeave":
|
|
812
1323
|
return () => cancelPointer([]);
|
|
1324
|
+
// Global cancel of these events
|
|
1325
|
+
case "onPointerCancel":
|
|
1326
|
+
return (event) => {
|
|
1327
|
+
const pointerId = getPointerId(event);
|
|
1328
|
+
cleanupPointer(pointerId);
|
|
1329
|
+
};
|
|
813
1330
|
case "onLostPointerCapture":
|
|
814
1331
|
return (event) => {
|
|
815
1332
|
const { internal } = store.getState();
|
|
816
|
-
|
|
1333
|
+
const pointerId = getPointerId(event);
|
|
1334
|
+
const pointerState = internal.pointerMap.get(pointerId);
|
|
1335
|
+
if (pointerState?.captured.size) {
|
|
817
1336
|
requestAnimationFrame(() => {
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
1337
|
+
const pointerState2 = internal.pointerMap.get(pointerId);
|
|
1338
|
+
if (pointerState2?.captured.size) {
|
|
1339
|
+
pointerState2.captured.clear();
|
|
821
1340
|
}
|
|
1341
|
+
cancelPointer([], pointerId);
|
|
822
1342
|
});
|
|
823
1343
|
}
|
|
824
1344
|
};
|
|
825
1345
|
}
|
|
826
1346
|
return function handleEvent(event) {
|
|
827
1347
|
const state = store.getState();
|
|
828
|
-
const { onPointerMissed, onDragOverMissed, onDropMissed, internal } = state;
|
|
1348
|
+
const { onPointerMissed, onDragOverMissed, onDropMissed, internal, events } = state;
|
|
1349
|
+
const pointerId = getPointerId(event);
|
|
829
1350
|
internal.lastEvent.current = event;
|
|
830
|
-
if (!
|
|
1351
|
+
if (!events.enabled) return;
|
|
831
1352
|
const isPointerMove = name === "onPointerMove";
|
|
832
1353
|
const isDragOver = name === "onDragOver";
|
|
833
1354
|
const isDrop = name === "onDrop";
|
|
834
1355
|
const isClickEvent = name === "onClick" || name === "onContextMenu" || name === "onDoubleClick";
|
|
1356
|
+
const isPointerDown = name === "onPointerDown";
|
|
1357
|
+
const isPointerUp = name === "onPointerUp";
|
|
1358
|
+
const isWheel = name === "onWheel";
|
|
1359
|
+
const canDeferRaycasts = events.frameTimedRaycasts && state.frameloop === "always";
|
|
1360
|
+
if (isPointerMove && canDeferRaycasts) {
|
|
1361
|
+
events.compute?.(event, state);
|
|
1362
|
+
internal.pointerDirty.set(pointerId, event);
|
|
1363
|
+
return;
|
|
1364
|
+
}
|
|
1365
|
+
if (isWheel && canDeferRaycasts && !events.alwaysFireOnScroll) {
|
|
1366
|
+
events.compute?.(event, state);
|
|
1367
|
+
internal.pointerDirty.set(pointerId, event);
|
|
1368
|
+
return;
|
|
1369
|
+
}
|
|
1370
|
+
if ((isClickEvent || isPointerDown || isPointerUp) && internal.pointerDirty.has(pointerId)) {
|
|
1371
|
+
const deferredEvent = internal.pointerDirty.get(pointerId);
|
|
1372
|
+
internal.pointerDirty.delete(pointerId);
|
|
1373
|
+
processDeferredPointer(deferredEvent, pointerId);
|
|
1374
|
+
}
|
|
835
1375
|
const filter = isPointerMove || isDragOver || isDrop ? filterPointerEvents : void 0;
|
|
836
1376
|
const hits = intersect(event, filter);
|
|
837
|
-
const delta = isClickEvent ? calculateDistance(event) : 0;
|
|
838
|
-
if (
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
1377
|
+
const delta = isClickEvent ? calculateDistance(event, pointerId) : 0;
|
|
1378
|
+
if (isPointerDown) {
|
|
1379
|
+
const pointerState2 = getPointerState(internal, pointerId);
|
|
1380
|
+
pointerState2.initialClick = [event.offsetX, event.offsetY];
|
|
1381
|
+
pointerState2.initialHits = hits.map((hit) => hit.eventObject);
|
|
1382
|
+
}
|
|
1383
|
+
const pointerState = internal.pointerMap.get(pointerId);
|
|
1384
|
+
const initialHits = pointerState?.initialHits ?? [];
|
|
842
1385
|
if (isClickEvent && !hits.length) {
|
|
843
1386
|
if (delta <= 2) {
|
|
844
1387
|
pointerMissed(event, internal.interaction);
|
|
@@ -853,7 +1396,9 @@ function createEvents(store) {
|
|
|
853
1396
|
dropMissed(event, internal.interaction);
|
|
854
1397
|
if (onDropMissed) onDropMissed(event);
|
|
855
1398
|
}
|
|
856
|
-
if (isPointerMove || isDragOver)
|
|
1399
|
+
if (isPointerMove || isDragOver) {
|
|
1400
|
+
cancelPointer(hits, pointerId);
|
|
1401
|
+
}
|
|
857
1402
|
function onIntersect(data) {
|
|
858
1403
|
const eventObject = data.eventObject;
|
|
859
1404
|
const instance = eventObject.__r3f;
|
|
@@ -862,9 +1407,10 @@ function createEvents(store) {
|
|
|
862
1407
|
if (isPointerMove) {
|
|
863
1408
|
if (handlers.onPointerOver || handlers.onPointerEnter || handlers.onPointerOut || handlers.onPointerLeave) {
|
|
864
1409
|
const id = makeId(data);
|
|
865
|
-
const
|
|
1410
|
+
const pointerState2 = getPointerState(internal, pointerId);
|
|
1411
|
+
const hoveredItem = pointerState2.hovered.get(id);
|
|
866
1412
|
if (!hoveredItem) {
|
|
867
|
-
|
|
1413
|
+
pointerState2.hovered.set(id, data);
|
|
868
1414
|
handlers.onPointerOver?.(data);
|
|
869
1415
|
handlers.onPointerEnter?.(data);
|
|
870
1416
|
} else if (hoveredItem.stopped) {
|
|
@@ -874,9 +1420,10 @@ function createEvents(store) {
|
|
|
874
1420
|
handlers.onPointerMove?.(data);
|
|
875
1421
|
} else if (isDragOver) {
|
|
876
1422
|
const id = makeId(data);
|
|
877
|
-
const
|
|
1423
|
+
const pointerState2 = getPointerState(internal, pointerId);
|
|
1424
|
+
const hoveredItem = pointerState2.hovered.get(id);
|
|
878
1425
|
if (!hoveredItem) {
|
|
879
|
-
|
|
1426
|
+
pointerState2.hovered.set(id, data);
|
|
880
1427
|
handlers.onDragOverEnter?.(data);
|
|
881
1428
|
} else if (hoveredItem.stopped) {
|
|
882
1429
|
data.stopPropagation();
|
|
@@ -887,18 +1434,18 @@ function createEvents(store) {
|
|
|
887
1434
|
} else {
|
|
888
1435
|
const handler = handlers[name];
|
|
889
1436
|
if (handler) {
|
|
890
|
-
if (!isClickEvent ||
|
|
1437
|
+
if (!isClickEvent || initialHits.includes(eventObject)) {
|
|
891
1438
|
pointerMissed(
|
|
892
1439
|
event,
|
|
893
|
-
internal.interaction.filter((object) => !
|
|
1440
|
+
internal.interaction.filter((object) => !initialHits.includes(object))
|
|
894
1441
|
);
|
|
895
1442
|
handler(data);
|
|
896
1443
|
}
|
|
897
1444
|
} else {
|
|
898
|
-
if (isClickEvent &&
|
|
1445
|
+
if (isClickEvent && initialHits.includes(eventObject)) {
|
|
899
1446
|
pointerMissed(
|
|
900
1447
|
event,
|
|
901
|
-
internal.interaction.filter((object) => !
|
|
1448
|
+
internal.interaction.filter((object) => !initialHits.includes(object))
|
|
902
1449
|
);
|
|
903
1450
|
}
|
|
904
1451
|
}
|
|
@@ -907,7 +1454,15 @@ function createEvents(store) {
|
|
|
907
1454
|
handleIntersects(hits, event, delta, onIntersect);
|
|
908
1455
|
};
|
|
909
1456
|
}
|
|
910
|
-
|
|
1457
|
+
function flushDeferredPointers() {
|
|
1458
|
+
const { internal, events } = store.getState();
|
|
1459
|
+
if (!events.frameTimedRaycasts) return;
|
|
1460
|
+
for (const [pointerId, event] of internal.pointerDirty) {
|
|
1461
|
+
processDeferredPointer(event, pointerId);
|
|
1462
|
+
}
|
|
1463
|
+
internal.pointerDirty.clear();
|
|
1464
|
+
}
|
|
1465
|
+
return { handlePointer, flushDeferredPointers, processDeferredPointer };
|
|
911
1466
|
}
|
|
912
1467
|
const DOM_EVENTS = {
|
|
913
1468
|
onClick: ["click", false],
|
|
@@ -926,11 +1481,16 @@ const DOM_EVENTS = {
|
|
|
926
1481
|
onLostPointerCapture: ["lostpointercapture", true]
|
|
927
1482
|
};
|
|
928
1483
|
function createPointerEvents(store) {
|
|
929
|
-
const { handlePointer } = createEvents(store);
|
|
1484
|
+
const { handlePointer, flushDeferredPointers, processDeferredPointer } = createEvents(store);
|
|
1485
|
+
let nextXRPointerId = XR_POINTER_ID_START;
|
|
1486
|
+
const xrPointers = /* @__PURE__ */ new Map();
|
|
930
1487
|
return {
|
|
931
1488
|
priority: 1,
|
|
932
1489
|
enabled: true,
|
|
933
|
-
|
|
1490
|
+
frameTimedRaycasts: true,
|
|
1491
|
+
alwaysFireOnScroll: true,
|
|
1492
|
+
updateOnFrame: false,
|
|
1493
|
+
compute(event, state) {
|
|
934
1494
|
state.pointer.set(event.offsetX / state.size.width * 2 - 1, -(event.offsetY / state.size.height) * 2 + 1);
|
|
935
1495
|
state.raycaster.setFromCamera(state.pointer, state.camera);
|
|
936
1496
|
},
|
|
@@ -939,11 +1499,33 @@ function createPointerEvents(store) {
|
|
|
939
1499
|
(acc, key) => ({ ...acc, [key]: handlePointer(key) }),
|
|
940
1500
|
{}
|
|
941
1501
|
),
|
|
942
|
-
update: () => {
|
|
1502
|
+
update: (pointerId) => {
|
|
1503
|
+
const { events, internal } = store.getState();
|
|
1504
|
+
if (!events.handlers) return;
|
|
1505
|
+
if (pointerId !== void 0) {
|
|
1506
|
+
const event = internal.pointerDirty.get(pointerId);
|
|
1507
|
+
if (event) {
|
|
1508
|
+
internal.pointerDirty.delete(pointerId);
|
|
1509
|
+
processDeferredPointer(event, pointerId);
|
|
1510
|
+
} else if (internal.lastEvent?.current) {
|
|
1511
|
+
processDeferredPointer(internal.lastEvent.current, pointerId);
|
|
1512
|
+
}
|
|
1513
|
+
} else {
|
|
1514
|
+
flushDeferredPointers();
|
|
1515
|
+
if (internal.lastEvent?.current) {
|
|
1516
|
+
events.handlers.onPointerMove(internal.lastEvent.current);
|
|
1517
|
+
}
|
|
1518
|
+
}
|
|
1519
|
+
},
|
|
1520
|
+
flush: () => {
|
|
943
1521
|
const { events, internal } = store.getState();
|
|
944
|
-
|
|
1522
|
+
flushDeferredPointers();
|
|
1523
|
+
if (events.updateOnFrame && internal.lastEvent?.current && events.handlers) {
|
|
1524
|
+
events.handlers.onPointerMove(internal.lastEvent.current);
|
|
1525
|
+
}
|
|
945
1526
|
},
|
|
946
1527
|
connect: (target) => {
|
|
1528
|
+
if (!target) return;
|
|
947
1529
|
const { set, events } = store.getState();
|
|
948
1530
|
events.disconnect?.();
|
|
949
1531
|
set((state) => ({ events: { ...state.events, connected: target } }));
|
|
@@ -967,6 +1549,32 @@ function createPointerEvents(store) {
|
|
|
967
1549
|
}
|
|
968
1550
|
set((state) => ({ events: { ...state.events, connected: void 0 } }));
|
|
969
1551
|
}
|
|
1552
|
+
},
|
|
1553
|
+
registerPointer: (config) => {
|
|
1554
|
+
const pointerId = nextXRPointerId++;
|
|
1555
|
+
xrPointers.set(pointerId, config);
|
|
1556
|
+
const { internal } = store.getState();
|
|
1557
|
+
getPointerState(internal, pointerId);
|
|
1558
|
+
return pointerId;
|
|
1559
|
+
},
|
|
1560
|
+
unregisterPointer: (pointerId) => {
|
|
1561
|
+
xrPointers.delete(pointerId);
|
|
1562
|
+
const { internal } = store.getState();
|
|
1563
|
+
const pointerState = internal.pointerMap.get(pointerId);
|
|
1564
|
+
if (pointerState) {
|
|
1565
|
+
for (const [, hoveredObj] of pointerState.hovered) {
|
|
1566
|
+
const eventObject = hoveredObj.eventObject;
|
|
1567
|
+
const instance = eventObject.__r3f;
|
|
1568
|
+
if (instance?.eventCount) {
|
|
1569
|
+
const handlers = instance.handlers;
|
|
1570
|
+
const data = { ...hoveredObj, intersections: [] };
|
|
1571
|
+
handlers.onPointerOut?.(data);
|
|
1572
|
+
handlers.onPointerLeave?.(data);
|
|
1573
|
+
}
|
|
1574
|
+
}
|
|
1575
|
+
internal.pointerMap.delete(pointerId);
|
|
1576
|
+
}
|
|
1577
|
+
internal.pointerDirty.delete(pointerId);
|
|
970
1578
|
}
|
|
971
1579
|
};
|
|
972
1580
|
}
|
|
@@ -1028,300 +1636,26 @@ function notifyAlpha({ message, link }) {
|
|
|
1028
1636
|
}
|
|
1029
1637
|
}
|
|
1030
1638
|
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
}
|
|
1052
|
-
}
|
|
1053
|
-
let performanceTimeout = void 0;
|
|
1054
|
-
const setPerformanceCurrent = (current) => set((state2) => ({ performance: { ...state2.performance, current } }));
|
|
1055
|
-
const pointer = new Vector2();
|
|
1056
|
-
const rootState = {
|
|
1057
|
-
set,
|
|
1058
|
-
get,
|
|
1059
|
-
// Mock objects that have to be configured
|
|
1060
|
-
gl: null,
|
|
1061
|
-
renderer: null,
|
|
1062
|
-
camera: null,
|
|
1063
|
-
frustum: new Frustum(),
|
|
1064
|
-
autoUpdateFrustum: true,
|
|
1065
|
-
raycaster: null,
|
|
1066
|
-
events: { priority: 1, enabled: true, connected: false },
|
|
1067
|
-
scene: null,
|
|
1068
|
-
rootScene: null,
|
|
1069
|
-
xr: null,
|
|
1070
|
-
inspector: null,
|
|
1071
|
-
invalidate: (frames = 1, stackFrames = false) => invalidate(get(), frames, stackFrames),
|
|
1072
|
-
advance: (timestamp, runGlobalEffects) => advance(timestamp, runGlobalEffects, get()),
|
|
1073
|
-
legacy: false,
|
|
1074
|
-
linear: false,
|
|
1075
|
-
flat: false,
|
|
1076
|
-
textureColorSpace: "srgb",
|
|
1077
|
-
isLegacy: false,
|
|
1078
|
-
webGPUSupported: false,
|
|
1079
|
-
isNative: false,
|
|
1080
|
-
controls: null,
|
|
1081
|
-
pointer,
|
|
1082
|
-
mouse: pointer,
|
|
1083
|
-
frameloop: "always",
|
|
1084
|
-
onPointerMissed: void 0,
|
|
1085
|
-
onDragOverMissed: void 0,
|
|
1086
|
-
onDropMissed: void 0,
|
|
1087
|
-
performance: {
|
|
1088
|
-
current: 1,
|
|
1089
|
-
min: 0.5,
|
|
1090
|
-
max: 1,
|
|
1091
|
-
debounce: 200,
|
|
1092
|
-
regress: () => {
|
|
1093
|
-
const state2 = get();
|
|
1094
|
-
if (performanceTimeout) clearTimeout(performanceTimeout);
|
|
1095
|
-
if (state2.performance.current !== state2.performance.min) setPerformanceCurrent(state2.performance.min);
|
|
1096
|
-
performanceTimeout = setTimeout(
|
|
1097
|
-
() => setPerformanceCurrent(get().performance.max),
|
|
1098
|
-
state2.performance.debounce
|
|
1099
|
-
);
|
|
1100
|
-
}
|
|
1101
|
-
},
|
|
1102
|
-
size: { width: 0, height: 0, top: 0, left: 0 },
|
|
1103
|
-
viewport: {
|
|
1104
|
-
initialDpr: 0,
|
|
1105
|
-
dpr: 0,
|
|
1106
|
-
width: 0,
|
|
1107
|
-
height: 0,
|
|
1108
|
-
top: 0,
|
|
1109
|
-
left: 0,
|
|
1110
|
-
aspect: 0,
|
|
1111
|
-
distance: 0,
|
|
1112
|
-
factor: 0,
|
|
1113
|
-
getCurrentViewport
|
|
1114
|
-
},
|
|
1115
|
-
setEvents: (events) => set((state2) => ({ ...state2, events: { ...state2.events, ...events } })),
|
|
1116
|
-
setSize: (width, height, top = 0, left = 0) => {
|
|
1117
|
-
const camera = get().camera;
|
|
1118
|
-
const size = { width, height, top, left };
|
|
1119
|
-
set((state2) => ({ size, viewport: { ...state2.viewport, ...getCurrentViewport(camera, defaultTarget, size) } }));
|
|
1120
|
-
},
|
|
1121
|
-
setDpr: (dpr) => set((state2) => {
|
|
1122
|
-
const resolved = calculateDpr(dpr);
|
|
1123
|
-
return { viewport: { ...state2.viewport, dpr: resolved, initialDpr: state2.viewport.initialDpr || resolved } };
|
|
1124
|
-
}),
|
|
1125
|
-
setFrameloop: (frameloop = "always") => {
|
|
1126
|
-
set(() => ({ frameloop }));
|
|
1127
|
-
},
|
|
1128
|
-
setError: (error) => set(() => ({ error })),
|
|
1129
|
-
error: null,
|
|
1130
|
-
//* TSL State (managed via hooks: useUniforms, useNodes, useTextures, usePostProcessing) ==============================
|
|
1131
|
-
uniforms: {},
|
|
1132
|
-
nodes: {},
|
|
1133
|
-
textures: /* @__PURE__ */ new Map(),
|
|
1134
|
-
postProcessing: null,
|
|
1135
|
-
passes: {},
|
|
1136
|
-
previousRoot: void 0,
|
|
1137
|
-
internal: {
|
|
1138
|
-
// Events
|
|
1139
|
-
interaction: [],
|
|
1140
|
-
hovered: /* @__PURE__ */ new Map(),
|
|
1141
|
-
subscribers: [],
|
|
1142
|
-
initialClick: [0, 0],
|
|
1143
|
-
initialHits: [],
|
|
1144
|
-
capturedMap: /* @__PURE__ */ new Map(),
|
|
1145
|
-
lastEvent: React.createRef(),
|
|
1146
|
-
// Visibility tracking (onFramed, onOccluded, onVisible)
|
|
1147
|
-
visibilityRegistry: /* @__PURE__ */ new Map(),
|
|
1148
|
-
// Occlusion system (WebGPU only)
|
|
1149
|
-
occlusionEnabled: false,
|
|
1150
|
-
occlusionObserver: null,
|
|
1151
|
-
occlusionCache: /* @__PURE__ */ new Map(),
|
|
1152
|
-
helperGroup: null,
|
|
1153
|
-
// Updates
|
|
1154
|
-
active: false,
|
|
1155
|
-
frames: 0,
|
|
1156
|
-
priority: 0,
|
|
1157
|
-
subscribe: (ref, priority, store) => {
|
|
1158
|
-
const internal = get().internal;
|
|
1159
|
-
internal.priority = internal.priority + (priority > 0 ? 1 : 0);
|
|
1160
|
-
internal.subscribers.push({ ref, priority, store });
|
|
1161
|
-
internal.subscribers = internal.subscribers.sort((a, b) => a.priority - b.priority);
|
|
1162
|
-
return () => {
|
|
1163
|
-
const internal2 = get().internal;
|
|
1164
|
-
if (internal2?.subscribers) {
|
|
1165
|
-
internal2.priority = internal2.priority - (priority > 0 ? 1 : 0);
|
|
1166
|
-
internal2.subscribers = internal2.subscribers.filter((s) => s.ref !== ref);
|
|
1167
|
-
}
|
|
1168
|
-
};
|
|
1169
|
-
},
|
|
1170
|
-
// Renderer Storage (single source of truth)
|
|
1171
|
-
actualRenderer: null,
|
|
1172
|
-
// Scheduler for useFrameNext (initialized in renderer.tsx)
|
|
1173
|
-
scheduler: null
|
|
1174
|
-
}
|
|
1175
|
-
};
|
|
1176
|
-
return rootState;
|
|
1177
|
-
});
|
|
1178
|
-
const state = rootStore.getState();
|
|
1179
|
-
Object.defineProperty(state, "gl", {
|
|
1180
|
-
get() {
|
|
1181
|
-
const currentState = rootStore.getState();
|
|
1182
|
-
if (!currentState.isLegacy && currentState.internal.actualRenderer) {
|
|
1183
|
-
const stack = new Error().stack || "";
|
|
1184
|
-
const isInternalAccess = stack.includes("zustand") || stack.includes("setState") || stack.includes("Object.assign") || stack.includes("react-three-fiber/packages/fiber/src/core");
|
|
1185
|
-
if (!isInternalAccess) {
|
|
1186
|
-
const cleanedStack = stack.split("\n").slice(2).join("\n") || "Stack trace unavailable";
|
|
1187
|
-
notifyDepreciated({
|
|
1188
|
-
heading: "Accessing state.gl in WebGPU mode",
|
|
1189
|
-
body: "Please use state.renderer instead. state.gl is deprecated and will be removed in future versions.\n\nFor backwards compatibility, state.gl currently maps to state.renderer, but this may cause issues with libraries expecting WebGLRenderer.\n\nAccessed from:\n" + cleanedStack
|
|
1190
|
-
});
|
|
1191
|
-
}
|
|
1192
|
-
}
|
|
1193
|
-
return currentState.internal.actualRenderer;
|
|
1194
|
-
},
|
|
1195
|
-
set(value) {
|
|
1196
|
-
rootStore.getState().internal.actualRenderer = value;
|
|
1197
|
-
},
|
|
1198
|
-
enumerable: true,
|
|
1199
|
-
configurable: true
|
|
1200
|
-
});
|
|
1201
|
-
Object.defineProperty(state, "renderer", {
|
|
1202
|
-
get() {
|
|
1203
|
-
return rootStore.getState().internal.actualRenderer;
|
|
1204
|
-
},
|
|
1205
|
-
set(value) {
|
|
1206
|
-
rootStore.getState().internal.actualRenderer = value;
|
|
1207
|
-
},
|
|
1208
|
-
enumerable: true,
|
|
1209
|
-
configurable: true
|
|
1210
|
-
});
|
|
1211
|
-
let oldScene = state.scene;
|
|
1212
|
-
rootStore.subscribe(() => {
|
|
1213
|
-
const currentState = rootStore.getState();
|
|
1214
|
-
const { scene, rootScene, set } = currentState;
|
|
1215
|
-
if (scene !== oldScene) {
|
|
1216
|
-
oldScene = scene;
|
|
1217
|
-
if (scene?.isScene && scene !== rootScene) {
|
|
1218
|
-
set({ rootScene: scene });
|
|
1219
|
-
}
|
|
1220
|
-
}
|
|
1221
|
-
});
|
|
1222
|
-
let oldSize = state.size;
|
|
1223
|
-
let oldDpr = state.viewport.dpr;
|
|
1224
|
-
let oldCamera = state.camera;
|
|
1225
|
-
rootStore.subscribe(() => {
|
|
1226
|
-
const { camera, size, viewport, set, internal } = rootStore.getState();
|
|
1227
|
-
const actualRenderer = internal.actualRenderer;
|
|
1228
|
-
if (size.width !== oldSize.width || size.height !== oldSize.height || viewport.dpr !== oldDpr) {
|
|
1229
|
-
oldSize = size;
|
|
1230
|
-
oldDpr = viewport.dpr;
|
|
1231
|
-
updateCamera(camera, size);
|
|
1232
|
-
if (viewport.dpr > 0) actualRenderer.setPixelRatio(viewport.dpr);
|
|
1233
|
-
const updateStyle = typeof HTMLCanvasElement !== "undefined" && actualRenderer.domElement instanceof HTMLCanvasElement;
|
|
1234
|
-
actualRenderer.setSize(size.width, size.height, updateStyle);
|
|
1235
|
-
}
|
|
1236
|
-
if (camera !== oldCamera) {
|
|
1237
|
-
oldCamera = camera;
|
|
1238
|
-
const { rootScene } = rootStore.getState();
|
|
1239
|
-
if (camera && rootScene && !camera.parent) {
|
|
1240
|
-
rootScene.add(camera);
|
|
1241
|
-
}
|
|
1242
|
-
set((state2) => ({ viewport: { ...state2.viewport, ...state2.viewport.getCurrentViewport(camera) } }));
|
|
1243
|
-
const currentState = rootStore.getState();
|
|
1244
|
-
if (currentState.autoUpdateFrustum && camera) {
|
|
1245
|
-
updateFrustum(camera, currentState.frustum);
|
|
1246
|
-
}
|
|
1247
|
-
}
|
|
1248
|
-
});
|
|
1249
|
-
rootStore.subscribe((state2) => invalidate(state2));
|
|
1250
|
-
return rootStore;
|
|
1251
|
-
};
|
|
1252
|
-
|
|
1253
|
-
const memoizedLoaders = /* @__PURE__ */ new WeakMap();
|
|
1254
|
-
const isConstructor$1 = (value) => typeof value === "function" && value?.prototype?.constructor === value;
|
|
1255
|
-
function getLoader(Proto) {
|
|
1256
|
-
if (isConstructor$1(Proto)) {
|
|
1257
|
-
let loader = memoizedLoaders.get(Proto);
|
|
1258
|
-
if (!loader) {
|
|
1259
|
-
loader = new Proto();
|
|
1260
|
-
memoizedLoaders.set(Proto, loader);
|
|
1261
|
-
}
|
|
1262
|
-
return loader;
|
|
1263
|
-
}
|
|
1264
|
-
return Proto;
|
|
1265
|
-
}
|
|
1266
|
-
function loadingFn(extensions, onProgress) {
|
|
1267
|
-
return function(Proto, input) {
|
|
1268
|
-
const loader = getLoader(Proto);
|
|
1269
|
-
if (extensions) extensions(loader);
|
|
1270
|
-
if ("loadAsync" in loader && typeof loader.loadAsync === "function") {
|
|
1271
|
-
return loader.loadAsync(input, onProgress).then((data) => {
|
|
1272
|
-
if (isObject3D(data?.scene)) Object.assign(data, buildGraph(data.scene));
|
|
1273
|
-
return data;
|
|
1274
|
-
});
|
|
1275
|
-
}
|
|
1276
|
-
return new Promise(
|
|
1277
|
-
(res, reject) => loader.load(
|
|
1278
|
-
input,
|
|
1279
|
-
(data) => {
|
|
1280
|
-
if (isObject3D(data?.scene)) Object.assign(data, buildGraph(data.scene));
|
|
1281
|
-
res(data);
|
|
1282
|
-
},
|
|
1283
|
-
onProgress,
|
|
1284
|
-
(error) => reject(new Error(`Could not load ${input}: ${error?.message}`))
|
|
1285
|
-
)
|
|
1286
|
-
);
|
|
1287
|
-
};
|
|
1288
|
-
}
|
|
1289
|
-
function useLoader(loader, input, extensions, onProgress) {
|
|
1290
|
-
const keys = Array.isArray(input) ? input : [input];
|
|
1291
|
-
const fn = loadingFn(extensions, onProgress);
|
|
1292
|
-
const results = keys.map((key) => suspend(fn, [loader, key], { equal: is.equ }));
|
|
1293
|
-
return Array.isArray(input) ? results : results[0];
|
|
1294
|
-
}
|
|
1295
|
-
useLoader.preload = function(loader, input, extensions, onProgress) {
|
|
1296
|
-
const keys = Array.isArray(input) ? input : [input];
|
|
1297
|
-
keys.forEach((key) => preload(loadingFn(extensions, onProgress), [loader, key]));
|
|
1298
|
-
};
|
|
1299
|
-
useLoader.clear = function(loader, input) {
|
|
1300
|
-
const keys = Array.isArray(input) ? input : [input];
|
|
1301
|
-
keys.forEach((key) => clear([loader, key]));
|
|
1302
|
-
};
|
|
1303
|
-
useLoader.loader = getLoader;
|
|
1304
|
-
|
|
1305
|
-
var __defProp$1 = Object.defineProperty;
|
|
1306
|
-
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1307
|
-
var __publicField$1 = (obj, key, value) => __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1308
|
-
const DEFAULT_PHASES = ["start", "input", "physics", "update", "render", "finish"];
|
|
1309
|
-
class PhaseGraph {
|
|
1310
|
-
constructor() {
|
|
1311
|
-
/** Ordered list of phase nodes */
|
|
1312
|
-
__publicField$1(this, "phases", []);
|
|
1313
|
-
/** Quick lookup by name */
|
|
1314
|
-
__publicField$1(this, "phaseMap", /* @__PURE__ */ new Map());
|
|
1315
|
-
/** Cached ordered names (invalidated on changes) */
|
|
1316
|
-
__publicField$1(this, "orderedNamesCache", null);
|
|
1317
|
-
this.initializeDefaultPhases();
|
|
1318
|
-
}
|
|
1319
|
-
//* Initialization --------------------------------
|
|
1320
|
-
initializeDefaultPhases() {
|
|
1321
|
-
for (const name of DEFAULT_PHASES) {
|
|
1322
|
-
const node = { name, isAutoGenerated: false };
|
|
1323
|
-
this.phases.push(node);
|
|
1324
|
-
this.phaseMap.set(name, node);
|
|
1639
|
+
var __defProp$1 = Object.defineProperty;
|
|
1640
|
+
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1641
|
+
var __publicField$1 = (obj, key, value) => __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1642
|
+
const DEFAULT_PHASES = ["start", "input", "physics", "update", "render", "finish"];
|
|
1643
|
+
class PhaseGraph {
|
|
1644
|
+
constructor() {
|
|
1645
|
+
/** Ordered list of phase nodes */
|
|
1646
|
+
__publicField$1(this, "phases", []);
|
|
1647
|
+
/** Quick lookup by name */
|
|
1648
|
+
__publicField$1(this, "phaseMap", /* @__PURE__ */ new Map());
|
|
1649
|
+
/** Cached ordered names (invalidated on changes) */
|
|
1650
|
+
__publicField$1(this, "orderedNamesCache", null);
|
|
1651
|
+
this.initializeDefaultPhases();
|
|
1652
|
+
}
|
|
1653
|
+
//* Initialization --------------------------------
|
|
1654
|
+
initializeDefaultPhases() {
|
|
1655
|
+
for (const name of DEFAULT_PHASES) {
|
|
1656
|
+
const node = { name, isAutoGenerated: false };
|
|
1657
|
+
this.phases.push(node);
|
|
1658
|
+
this.phaseMap.set(name, node);
|
|
1325
1659
|
}
|
|
1326
1660
|
this.invalidateCache();
|
|
1327
1661
|
}
|
|
@@ -1340,8 +1674,9 @@ class PhaseGraph {
|
|
|
1340
1674
|
const node = { name, isAutoGenerated: false };
|
|
1341
1675
|
let insertIndex = this.phases.length;
|
|
1342
1676
|
const targetIndex = this.getPhaseIndex(before ?? after);
|
|
1343
|
-
if (targetIndex !== -1)
|
|
1344
|
-
|
|
1677
|
+
if (targetIndex !== -1) {
|
|
1678
|
+
insertIndex = before ? targetIndex : targetIndex + 1;
|
|
1679
|
+
} else {
|
|
1345
1680
|
const constraintType = before ? "before" : "after";
|
|
1346
1681
|
console.warn(`[useFrame] Phase "${before ?? after}" not found for '${constraintType}' constraint`);
|
|
1347
1682
|
}
|
|
@@ -1553,7 +1888,7 @@ function shouldRun(job, now) {
|
|
|
1553
1888
|
const minInterval = 1e3 / job.fps;
|
|
1554
1889
|
const lastRun = job.lastRun ?? 0;
|
|
1555
1890
|
const elapsed = now - lastRun;
|
|
1556
|
-
if (elapsed < minInterval) return false;
|
|
1891
|
+
if (elapsed < minInterval - 1) return false;
|
|
1557
1892
|
if (job.drop) {
|
|
1558
1893
|
job.lastRun = now;
|
|
1559
1894
|
} else {
|
|
@@ -2222,116 +2557,444 @@ const _Scheduler = class _Scheduler {
|
|
|
2222
2557
|
root.sortedJobs = rebuildSortedJobs(root.jobs, this.phaseGraph);
|
|
2223
2558
|
root.needsRebuild = false;
|
|
2224
2559
|
}
|
|
2225
|
-
const providedState = root.getState?.() ?? {};
|
|
2226
|
-
const frameState = {
|
|
2227
|
-
...providedState,
|
|
2228
|
-
time: timestamp,
|
|
2229
|
-
delta,
|
|
2230
|
-
elapsed: this.loopState.elapsedTime / 1e3,
|
|
2231
|
-
// Convert ms to seconds
|
|
2232
|
-
frame: this.loopState.frameCount
|
|
2233
|
-
};
|
|
2234
|
-
for (const job of root.sortedJobs) {
|
|
2235
|
-
if (!shouldRun(job, timestamp)) continue;
|
|
2236
|
-
try {
|
|
2237
|
-
job.callback(frameState, delta);
|
|
2238
|
-
} catch (error) {
|
|
2239
|
-
console.error(`[Scheduler] Error in job "${job.id}":`, error);
|
|
2240
|
-
this.triggerError(error instanceof Error ? error : new Error(String(error)));
|
|
2560
|
+
const providedState = root.getState?.() ?? {};
|
|
2561
|
+
const frameState = {
|
|
2562
|
+
...providedState,
|
|
2563
|
+
time: timestamp,
|
|
2564
|
+
delta,
|
|
2565
|
+
elapsed: this.loopState.elapsedTime / 1e3,
|
|
2566
|
+
// Convert ms to seconds
|
|
2567
|
+
frame: this.loopState.frameCount
|
|
2568
|
+
};
|
|
2569
|
+
for (const job of root.sortedJobs) {
|
|
2570
|
+
if (!shouldRun(job, timestamp)) continue;
|
|
2571
|
+
try {
|
|
2572
|
+
job.callback(frameState, delta);
|
|
2573
|
+
} catch (error) {
|
|
2574
|
+
console.error(`[Scheduler] Error in job "${job.id}":`, error);
|
|
2575
|
+
this.triggerError(error instanceof Error ? error : new Error(String(error)));
|
|
2576
|
+
}
|
|
2577
|
+
}
|
|
2578
|
+
}
|
|
2579
|
+
//* Debug & Inspection Methods ================================
|
|
2580
|
+
/**
|
|
2581
|
+
* Get the total number of registered jobs across all roots.
|
|
2582
|
+
* Includes both per-root jobs and global before/after jobs.
|
|
2583
|
+
* @returns {number} Total job count
|
|
2584
|
+
*/
|
|
2585
|
+
getJobCount() {
|
|
2586
|
+
let count = 0;
|
|
2587
|
+
for (const root of this.roots.values()) {
|
|
2588
|
+
count += root.jobs.size;
|
|
2589
|
+
}
|
|
2590
|
+
return count + this.globalBeforeJobs.size + this.globalAfterJobs.size;
|
|
2591
|
+
}
|
|
2592
|
+
/**
|
|
2593
|
+
* Get all registered job IDs across all roots.
|
|
2594
|
+
* Includes both per-root jobs and global before/after jobs.
|
|
2595
|
+
* @returns {string[]} Array of all job IDs
|
|
2596
|
+
*/
|
|
2597
|
+
getJobIds() {
|
|
2598
|
+
const ids = [];
|
|
2599
|
+
for (const root of this.roots.values()) {
|
|
2600
|
+
ids.push(...root.jobs.keys());
|
|
2601
|
+
}
|
|
2602
|
+
ids.push(...this.globalBeforeJobs.keys());
|
|
2603
|
+
ids.push(...this.globalAfterJobs.keys());
|
|
2604
|
+
return ids;
|
|
2605
|
+
}
|
|
2606
|
+
/**
|
|
2607
|
+
* Get the number of registered roots (Canvas instances).
|
|
2608
|
+
* @returns {number} Number of registered roots
|
|
2609
|
+
*/
|
|
2610
|
+
getRootCount() {
|
|
2611
|
+
return this.roots.size;
|
|
2612
|
+
}
|
|
2613
|
+
/**
|
|
2614
|
+
* Check if any user (non-system) jobs are registered in a specific phase.
|
|
2615
|
+
* Used by the default render job to know if a user has taken over rendering.
|
|
2616
|
+
*
|
|
2617
|
+
* @param phase The phase to check
|
|
2618
|
+
* @param rootId Optional root ID to check (checks all roots if not provided)
|
|
2619
|
+
* @returns true if any user jobs exist in the phase
|
|
2620
|
+
*/
|
|
2621
|
+
hasUserJobsInPhase(phase, rootId) {
|
|
2622
|
+
const rootsToCheck = rootId ? [this.roots.get(rootId)].filter(Boolean) : Array.from(this.roots.values());
|
|
2623
|
+
return rootsToCheck.some((root) => {
|
|
2624
|
+
if (!root) return false;
|
|
2625
|
+
for (const job of root.jobs.values()) {
|
|
2626
|
+
if (job.phase === phase && !job.system && job.enabled) return true;
|
|
2627
|
+
}
|
|
2628
|
+
return false;
|
|
2629
|
+
});
|
|
2630
|
+
}
|
|
2631
|
+
//* Utility Methods ================================
|
|
2632
|
+
/**
|
|
2633
|
+
* Generate a unique root ID for automatic root registration.
|
|
2634
|
+
* @returns {string} A unique root ID in the format 'root_N'
|
|
2635
|
+
*/
|
|
2636
|
+
generateRootId() {
|
|
2637
|
+
return `root_${this.nextRootIndex++}`;
|
|
2638
|
+
}
|
|
2639
|
+
/**
|
|
2640
|
+
* Generate a unique job ID.
|
|
2641
|
+
* @returns {string} A unique job ID in the format 'job_N'
|
|
2642
|
+
* @private
|
|
2643
|
+
*/
|
|
2644
|
+
generateJobId() {
|
|
2645
|
+
return `job_${this.nextJobIndex}`;
|
|
2646
|
+
}
|
|
2647
|
+
/**
|
|
2648
|
+
* Normalize before/after constraints to a Set.
|
|
2649
|
+
* Handles undefined, single string, or array inputs.
|
|
2650
|
+
* @param {string | string[] | undefined} value - The constraint value(s)
|
|
2651
|
+
* @returns {Set<string>} Normalized Set of constraint strings
|
|
2652
|
+
* @private
|
|
2653
|
+
*/
|
|
2654
|
+
normalizeConstraints(value) {
|
|
2655
|
+
if (!value) return /* @__PURE__ */ new Set();
|
|
2656
|
+
if (Array.isArray(value)) return new Set(value);
|
|
2657
|
+
return /* @__PURE__ */ new Set([value]);
|
|
2658
|
+
}
|
|
2659
|
+
};
|
|
2660
|
+
//* Static State & Methods (Singleton Usage) ================================
|
|
2661
|
+
//* Cross-Bundle Singleton Key ==============================
|
|
2662
|
+
// Use Symbol.for() to ensure scheduler is shared across bundle boundaries
|
|
2663
|
+
// This prevents issues when mixing imports from @react-three/fiber and @react-three/fiber/webgpu
|
|
2664
|
+
__publicField(_Scheduler, "INSTANCE_KEY", Symbol.for("@react-three/fiber.scheduler"));
|
|
2665
|
+
let Scheduler = _Scheduler;
|
|
2666
|
+
const getScheduler = () => Scheduler.get();
|
|
2667
|
+
if (hmrData) {
|
|
2668
|
+
hmrData.accept?.();
|
|
2669
|
+
}
|
|
2670
|
+
|
|
2671
|
+
const R3F_CONTEXT = Symbol.for("@react-three/fiber.context");
|
|
2672
|
+
const context = globalThis[R3F_CONTEXT] ?? (globalThis[R3F_CONTEXT] = React.createContext(null));
|
|
2673
|
+
const createStore = (invalidate, advance) => {
|
|
2674
|
+
const rootStore = createWithEqualityFn((set, get) => {
|
|
2675
|
+
const position = new Vector3();
|
|
2676
|
+
const defaultTarget = new Vector3();
|
|
2677
|
+
const tempTarget = new Vector3();
|
|
2678
|
+
function getCurrentViewport(camera = get().camera, target = defaultTarget, size = get().size) {
|
|
2679
|
+
const { width, height, top, left } = size;
|
|
2680
|
+
const aspect = width / height;
|
|
2681
|
+
if (target.isVector3) tempTarget.copy(target);
|
|
2682
|
+
else tempTarget.set(...target);
|
|
2683
|
+
const distance = camera.getWorldPosition(position).distanceTo(tempTarget);
|
|
2684
|
+
if (isOrthographicCamera(camera)) {
|
|
2685
|
+
return { width: width / camera.zoom, height: height / camera.zoom, top, left, factor: 1, distance, aspect };
|
|
2686
|
+
} else {
|
|
2687
|
+
const fov = camera.fov * Math.PI / 180;
|
|
2688
|
+
const h = 2 * Math.tan(fov / 2) * distance;
|
|
2689
|
+
const w = h * (width / height);
|
|
2690
|
+
return { width: w, height: h, top, left, factor: width / w, distance, aspect };
|
|
2691
|
+
}
|
|
2692
|
+
}
|
|
2693
|
+
let performanceTimeout = void 0;
|
|
2694
|
+
const setPerformanceCurrent = (current) => set((state2) => ({ performance: { ...state2.performance, current } }));
|
|
2695
|
+
const pointer = new Vector2();
|
|
2696
|
+
const rootState = {
|
|
2697
|
+
set,
|
|
2698
|
+
get,
|
|
2699
|
+
// Mock objects that have to be configured
|
|
2700
|
+
// primaryStore is set after store creation (self-reference for primary, primary's store for secondary)
|
|
2701
|
+
primaryStore: null,
|
|
2702
|
+
gl: null,
|
|
2703
|
+
renderer: null,
|
|
2704
|
+
camera: null,
|
|
2705
|
+
frustum: new Frustum(),
|
|
2706
|
+
autoUpdateFrustum: true,
|
|
2707
|
+
raycaster: null,
|
|
2708
|
+
events: {
|
|
2709
|
+
priority: 1,
|
|
2710
|
+
enabled: true,
|
|
2711
|
+
connected: false,
|
|
2712
|
+
frameTimedRaycasts: true,
|
|
2713
|
+
alwaysFireOnScroll: true,
|
|
2714
|
+
updateOnFrame: false
|
|
2715
|
+
},
|
|
2716
|
+
scene: null,
|
|
2717
|
+
rootScene: null,
|
|
2718
|
+
xr: null,
|
|
2719
|
+
inspector: null,
|
|
2720
|
+
invalidate: (frames = 1, stackFrames = false) => invalidate(get(), frames, stackFrames),
|
|
2721
|
+
advance: (timestamp, runGlobalEffects) => advance(timestamp, runGlobalEffects, get()),
|
|
2722
|
+
textureColorSpace: SRGBColorSpace,
|
|
2723
|
+
isLegacy: false,
|
|
2724
|
+
webGPUSupported: false,
|
|
2725
|
+
isNative: false,
|
|
2726
|
+
controls: null,
|
|
2727
|
+
pointer,
|
|
2728
|
+
mouse: pointer,
|
|
2729
|
+
frameloop: "always",
|
|
2730
|
+
onPointerMissed: void 0,
|
|
2731
|
+
onDragOverMissed: void 0,
|
|
2732
|
+
onDropMissed: void 0,
|
|
2733
|
+
performance: {
|
|
2734
|
+
current: 1,
|
|
2735
|
+
min: 0.5,
|
|
2736
|
+
max: 1,
|
|
2737
|
+
debounce: 200,
|
|
2738
|
+
regress: () => {
|
|
2739
|
+
const state2 = get();
|
|
2740
|
+
if (performanceTimeout) clearTimeout(performanceTimeout);
|
|
2741
|
+
if (state2.performance.current !== state2.performance.min) setPerformanceCurrent(state2.performance.min);
|
|
2742
|
+
performanceTimeout = setTimeout(
|
|
2743
|
+
() => setPerformanceCurrent(get().performance.max),
|
|
2744
|
+
state2.performance.debounce
|
|
2745
|
+
);
|
|
2746
|
+
}
|
|
2747
|
+
},
|
|
2748
|
+
size: { width: 0, height: 0, top: 0, left: 0 },
|
|
2749
|
+
viewport: {
|
|
2750
|
+
initialDpr: 0,
|
|
2751
|
+
dpr: 0,
|
|
2752
|
+
width: 0,
|
|
2753
|
+
height: 0,
|
|
2754
|
+
top: 0,
|
|
2755
|
+
left: 0,
|
|
2756
|
+
aspect: 0,
|
|
2757
|
+
distance: 0,
|
|
2758
|
+
factor: 0,
|
|
2759
|
+
getCurrentViewport
|
|
2760
|
+
},
|
|
2761
|
+
setEvents: (events) => set((state2) => ({ ...state2, events: { ...state2.events, ...events } })),
|
|
2762
|
+
setSize: (width, height, top, left) => {
|
|
2763
|
+
const state2 = get();
|
|
2764
|
+
if (width === void 0) {
|
|
2765
|
+
set({ _sizeImperative: false });
|
|
2766
|
+
if (state2._sizeProps) {
|
|
2767
|
+
const { width: propW, height: propH } = state2._sizeProps;
|
|
2768
|
+
if (propW !== void 0 || propH !== void 0) {
|
|
2769
|
+
const currentSize = state2.size;
|
|
2770
|
+
const newSize = {
|
|
2771
|
+
width: propW ?? currentSize.width,
|
|
2772
|
+
height: propH ?? currentSize.height,
|
|
2773
|
+
top: currentSize.top,
|
|
2774
|
+
left: currentSize.left
|
|
2775
|
+
};
|
|
2776
|
+
set((s) => ({
|
|
2777
|
+
size: newSize,
|
|
2778
|
+
viewport: { ...s.viewport, ...getCurrentViewport(state2.camera, defaultTarget, newSize) }
|
|
2779
|
+
}));
|
|
2780
|
+
getScheduler().invalidate();
|
|
2781
|
+
}
|
|
2782
|
+
}
|
|
2783
|
+
return;
|
|
2784
|
+
}
|
|
2785
|
+
const w = width;
|
|
2786
|
+
const h = height ?? width;
|
|
2787
|
+
const t = top ?? state2.size.top;
|
|
2788
|
+
const l = left ?? state2.size.left;
|
|
2789
|
+
const size = { width: w, height: h, top: t, left: l };
|
|
2790
|
+
set((s) => ({
|
|
2791
|
+
size,
|
|
2792
|
+
viewport: { ...s.viewport, ...getCurrentViewport(state2.camera, defaultTarget, size) },
|
|
2793
|
+
_sizeImperative: true
|
|
2794
|
+
}));
|
|
2795
|
+
getScheduler().invalidate();
|
|
2796
|
+
},
|
|
2797
|
+
setDpr: (dpr) => set((state2) => {
|
|
2798
|
+
const resolved = calculateDpr(dpr);
|
|
2799
|
+
return { viewport: { ...state2.viewport, dpr: resolved, initialDpr: state2.viewport.initialDpr || resolved } };
|
|
2800
|
+
}),
|
|
2801
|
+
setFrameloop: (frameloop = "always") => {
|
|
2802
|
+
set(() => ({ frameloop }));
|
|
2803
|
+
},
|
|
2804
|
+
setError: (error) => set(() => ({ error })),
|
|
2805
|
+
error: null,
|
|
2806
|
+
//* TSL State (managed via hooks: useUniforms, useNodes, useBuffers, useGPUStorage, useTextures, useRenderPipeline) ==============================
|
|
2807
|
+
uniforms: {},
|
|
2808
|
+
nodes: {},
|
|
2809
|
+
buffers: {},
|
|
2810
|
+
gpuStorage: {},
|
|
2811
|
+
textures: /* @__PURE__ */ new Map(),
|
|
2812
|
+
renderPipeline: null,
|
|
2813
|
+
passes: {},
|
|
2814
|
+
_hmrVersion: 0,
|
|
2815
|
+
_sizeImperative: false,
|
|
2816
|
+
_sizeProps: null,
|
|
2817
|
+
previousRoot: void 0,
|
|
2818
|
+
internal: {
|
|
2819
|
+
// Events
|
|
2820
|
+
interaction: [],
|
|
2821
|
+
subscribers: [],
|
|
2822
|
+
// Per-pointer state (new unified structure)
|
|
2823
|
+
pointerMap: /* @__PURE__ */ new Map(),
|
|
2824
|
+
pointerDirty: /* @__PURE__ */ new Map(),
|
|
2825
|
+
lastEvent: React.createRef(),
|
|
2826
|
+
// Deprecated but kept for backwards compatibility
|
|
2827
|
+
hovered: /* @__PURE__ */ new Map(),
|
|
2828
|
+
initialClick: [0, 0],
|
|
2829
|
+
initialHits: [],
|
|
2830
|
+
capturedMap: /* @__PURE__ */ new Map(),
|
|
2831
|
+
// Visibility tracking (onFramed, onOccluded, onVisible)
|
|
2832
|
+
visibilityRegistry: /* @__PURE__ */ new Map(),
|
|
2833
|
+
// Occlusion system (WebGPU only)
|
|
2834
|
+
occlusionEnabled: false,
|
|
2835
|
+
occlusionObserver: null,
|
|
2836
|
+
occlusionCache: /* @__PURE__ */ new Map(),
|
|
2837
|
+
helperGroup: null,
|
|
2838
|
+
// Updates
|
|
2839
|
+
active: false,
|
|
2840
|
+
frames: 0,
|
|
2841
|
+
priority: 0,
|
|
2842
|
+
subscribe: (ref, priority, store) => {
|
|
2843
|
+
const internal = get().internal;
|
|
2844
|
+
internal.priority = internal.priority + (priority > 0 ? 1 : 0);
|
|
2845
|
+
internal.subscribers.push({ ref, priority, store });
|
|
2846
|
+
internal.subscribers = internal.subscribers.sort((a, b) => a.priority - b.priority);
|
|
2847
|
+
return () => {
|
|
2848
|
+
const internal2 = get().internal;
|
|
2849
|
+
if (internal2?.subscribers) {
|
|
2850
|
+
internal2.priority = internal2.priority - (priority > 0 ? 1 : 0);
|
|
2851
|
+
internal2.subscribers = internal2.subscribers.filter((s) => s.ref !== ref);
|
|
2852
|
+
}
|
|
2853
|
+
};
|
|
2854
|
+
},
|
|
2855
|
+
// Renderer Storage (single source of truth)
|
|
2856
|
+
actualRenderer: null,
|
|
2857
|
+
// Scheduler for useFrameNext (initialized in renderer.tsx)
|
|
2858
|
+
scheduler: null
|
|
2859
|
+
}
|
|
2860
|
+
};
|
|
2861
|
+
return rootState;
|
|
2862
|
+
});
|
|
2863
|
+
const state = rootStore.getState();
|
|
2864
|
+
Object.defineProperty(state, "gl", {
|
|
2865
|
+
get() {
|
|
2866
|
+
const currentState = rootStore.getState();
|
|
2867
|
+
if (!currentState.isLegacy && currentState.internal.actualRenderer) {
|
|
2868
|
+
const stack = new Error().stack || "";
|
|
2869
|
+
const isInternalAccess = stack.includes("zustand") || stack.includes("setState") || stack.includes("Object.assign") || stack.includes("react-three-fiber/packages/fiber/src/core");
|
|
2870
|
+
if (!isInternalAccess) {
|
|
2871
|
+
const cleanedStack = stack.split("\n").slice(2).join("\n") || "Stack trace unavailable";
|
|
2872
|
+
notifyDepreciated({
|
|
2873
|
+
heading: "Accessing state.gl in WebGPU mode",
|
|
2874
|
+
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
|
|
2875
|
+
});
|
|
2876
|
+
}
|
|
2877
|
+
}
|
|
2878
|
+
return currentState.internal.actualRenderer;
|
|
2879
|
+
},
|
|
2880
|
+
set(value) {
|
|
2881
|
+
rootStore.getState().internal.actualRenderer = value;
|
|
2882
|
+
},
|
|
2883
|
+
enumerable: true,
|
|
2884
|
+
configurable: true
|
|
2885
|
+
});
|
|
2886
|
+
Object.defineProperty(state, "renderer", {
|
|
2887
|
+
get() {
|
|
2888
|
+
return rootStore.getState().internal.actualRenderer;
|
|
2889
|
+
},
|
|
2890
|
+
set(value) {
|
|
2891
|
+
rootStore.getState().internal.actualRenderer = value;
|
|
2892
|
+
},
|
|
2893
|
+
enumerable: true,
|
|
2894
|
+
configurable: true
|
|
2895
|
+
});
|
|
2896
|
+
let oldScene = state.scene;
|
|
2897
|
+
rootStore.subscribe(() => {
|
|
2898
|
+
const currentState = rootStore.getState();
|
|
2899
|
+
const { scene, rootScene, set } = currentState;
|
|
2900
|
+
if (scene !== oldScene) {
|
|
2901
|
+
oldScene = scene;
|
|
2902
|
+
if (scene?.isScene && scene !== rootScene) {
|
|
2903
|
+
set({ rootScene: scene });
|
|
2904
|
+
}
|
|
2905
|
+
}
|
|
2906
|
+
});
|
|
2907
|
+
let oldSize = state.size;
|
|
2908
|
+
let oldDpr = state.viewport.dpr;
|
|
2909
|
+
let oldCamera = state.camera;
|
|
2910
|
+
rootStore.subscribe(() => {
|
|
2911
|
+
const { camera, size, viewport, set, internal } = rootStore.getState();
|
|
2912
|
+
const actualRenderer = internal.actualRenderer;
|
|
2913
|
+
const canvasTarget = internal.canvasTarget;
|
|
2914
|
+
if (size.width !== oldSize.width || size.height !== oldSize.height || viewport.dpr !== oldDpr) {
|
|
2915
|
+
oldSize = size;
|
|
2916
|
+
oldDpr = viewport.dpr;
|
|
2917
|
+
updateCamera(camera, size);
|
|
2918
|
+
if (internal.isSecondary && canvasTarget) {
|
|
2919
|
+
if (viewport.dpr > 0) canvasTarget.setPixelRatio(viewport.dpr);
|
|
2920
|
+
canvasTarget.setSize(size.width, size.height, false);
|
|
2921
|
+
} else {
|
|
2922
|
+
if (viewport.dpr > 0) actualRenderer.setPixelRatio(viewport.dpr);
|
|
2923
|
+
actualRenderer.setSize(size.width, size.height, false);
|
|
2924
|
+
if (canvasTarget) {
|
|
2925
|
+
if (viewport.dpr > 0) canvasTarget.setPixelRatio(viewport.dpr);
|
|
2926
|
+
canvasTarget.setSize(size.width, size.height, false);
|
|
2927
|
+
}
|
|
2928
|
+
}
|
|
2929
|
+
}
|
|
2930
|
+
if (camera !== oldCamera) {
|
|
2931
|
+
oldCamera = camera;
|
|
2932
|
+
const { rootScene } = rootStore.getState();
|
|
2933
|
+
if (camera && rootScene && !camera.parent) {
|
|
2934
|
+
rootScene.add(camera);
|
|
2935
|
+
}
|
|
2936
|
+
set((state2) => ({ viewport: { ...state2.viewport, ...state2.viewport.getCurrentViewport(camera) } }));
|
|
2937
|
+
const currentState = rootStore.getState();
|
|
2938
|
+
if (currentState.autoUpdateFrustum && camera) {
|
|
2939
|
+
updateFrustum(camera, currentState.frustum);
|
|
2241
2940
|
}
|
|
2242
2941
|
}
|
|
2243
|
-
}
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2942
|
+
});
|
|
2943
|
+
rootStore.subscribe((state2) => invalidate(state2));
|
|
2944
|
+
return rootStore;
|
|
2945
|
+
};
|
|
2946
|
+
|
|
2947
|
+
const memoizedLoaders = /* @__PURE__ */ new WeakMap();
|
|
2948
|
+
const isConstructor$1 = (value) => typeof value === "function" && value?.prototype?.constructor === value;
|
|
2949
|
+
function getLoader(Proto) {
|
|
2950
|
+
if (isConstructor$1(Proto)) {
|
|
2951
|
+
let loader = memoizedLoaders.get(Proto);
|
|
2952
|
+
if (!loader) {
|
|
2953
|
+
loader = new Proto();
|
|
2954
|
+
memoizedLoaders.set(Proto, loader);
|
|
2254
2955
|
}
|
|
2255
|
-
return
|
|
2956
|
+
return loader;
|
|
2256
2957
|
}
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2958
|
+
return Proto;
|
|
2959
|
+
}
|
|
2960
|
+
function loadingFn(extensions, onProgress) {
|
|
2961
|
+
return function(Proto, input) {
|
|
2962
|
+
const loader = getLoader(Proto);
|
|
2963
|
+
if (extensions) extensions(loader);
|
|
2964
|
+
if ("loadAsync" in loader && typeof loader.loadAsync === "function") {
|
|
2965
|
+
return loader.loadAsync(input, onProgress).then((data) => {
|
|
2966
|
+
if (isObject3D(data?.scene)) Object.assign(data, buildGraph(data.scene));
|
|
2967
|
+
return data;
|
|
2968
|
+
});
|
|
2266
2969
|
}
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
*/
|
|
2286
|
-
hasUserJobsInPhase(phase, rootId) {
|
|
2287
|
-
const rootsToCheck = rootId ? [this.roots.get(rootId)].filter(Boolean) : Array.from(this.roots.values());
|
|
2288
|
-
return rootsToCheck.some((root) => {
|
|
2289
|
-
if (!root) return false;
|
|
2290
|
-
for (const job of root.jobs.values()) {
|
|
2291
|
-
if (job.phase === phase && !job.system && job.enabled) return true;
|
|
2292
|
-
}
|
|
2293
|
-
return false;
|
|
2294
|
-
});
|
|
2295
|
-
}
|
|
2296
|
-
//* Utility Methods ================================
|
|
2297
|
-
/**
|
|
2298
|
-
* Generate a unique root ID for automatic root registration.
|
|
2299
|
-
* @returns {string} A unique root ID in the format 'root_N'
|
|
2300
|
-
*/
|
|
2301
|
-
generateRootId() {
|
|
2302
|
-
return `root_${this.nextRootIndex++}`;
|
|
2303
|
-
}
|
|
2304
|
-
/**
|
|
2305
|
-
* Generate a unique job ID.
|
|
2306
|
-
* @returns {string} A unique job ID in the format 'job_N'
|
|
2307
|
-
* @private
|
|
2308
|
-
*/
|
|
2309
|
-
generateJobId() {
|
|
2310
|
-
return `job_${this.nextJobIndex}`;
|
|
2311
|
-
}
|
|
2312
|
-
/**
|
|
2313
|
-
* Normalize before/after constraints to a Set.
|
|
2314
|
-
* Handles undefined, single string, or array inputs.
|
|
2315
|
-
* @param {string | string[] | undefined} value - The constraint value(s)
|
|
2316
|
-
* @returns {Set<string>} Normalized Set of constraint strings
|
|
2317
|
-
* @private
|
|
2318
|
-
*/
|
|
2319
|
-
normalizeConstraints(value) {
|
|
2320
|
-
if (!value) return /* @__PURE__ */ new Set();
|
|
2321
|
-
if (Array.isArray(value)) return new Set(value);
|
|
2322
|
-
return /* @__PURE__ */ new Set([value]);
|
|
2323
|
-
}
|
|
2324
|
-
};
|
|
2325
|
-
//* Static State & Methods (Singleton Usage) ================================
|
|
2326
|
-
//* Cross-Bundle Singleton Key ==============================
|
|
2327
|
-
// Use Symbol.for() to ensure scheduler is shared across bundle boundaries
|
|
2328
|
-
// This prevents issues when mixing imports from @react-three/fiber and @react-three/fiber/webgpu
|
|
2329
|
-
__publicField(_Scheduler, "INSTANCE_KEY", Symbol.for("@react-three/fiber.scheduler"));
|
|
2330
|
-
let Scheduler = _Scheduler;
|
|
2331
|
-
const getScheduler = () => Scheduler.get();
|
|
2332
|
-
if (hmrData) {
|
|
2333
|
-
hmrData.accept?.();
|
|
2970
|
+
return new Promise(
|
|
2971
|
+
(res, reject) => loader.load(
|
|
2972
|
+
input,
|
|
2973
|
+
(data) => {
|
|
2974
|
+
if (isObject3D(data?.scene)) Object.assign(data, buildGraph(data.scene));
|
|
2975
|
+
res(data);
|
|
2976
|
+
},
|
|
2977
|
+
onProgress,
|
|
2978
|
+
(error) => reject(new Error(`Could not load ${input}: ${error?.message}`))
|
|
2979
|
+
)
|
|
2980
|
+
);
|
|
2981
|
+
};
|
|
2982
|
+
}
|
|
2983
|
+
function useLoader(loader, input, extensions, onProgress) {
|
|
2984
|
+
const keys = Array.isArray(input) ? input : [input];
|
|
2985
|
+
const fn = loadingFn(extensions, onProgress);
|
|
2986
|
+
const results = keys.map((key) => suspend(fn, [loader, key], { equal: is.equ }));
|
|
2987
|
+
return Array.isArray(input) ? results : results[0];
|
|
2334
2988
|
}
|
|
2989
|
+
useLoader.preload = function(loader, input, extensions, onProgress) {
|
|
2990
|
+
const keys = Array.isArray(input) ? input : [input];
|
|
2991
|
+
keys.forEach((key) => preload(loadingFn(extensions, onProgress), [loader, key]));
|
|
2992
|
+
};
|
|
2993
|
+
useLoader.clear = function(loader, input) {
|
|
2994
|
+
const keys = Array.isArray(input) ? input : [input];
|
|
2995
|
+
keys.forEach((key) => clear([loader, key]));
|
|
2996
|
+
};
|
|
2997
|
+
useLoader.loader = getLoader;
|
|
2335
2998
|
|
|
2336
2999
|
function useFrame(callback, priorityOrOptions) {
|
|
2337
3000
|
const store = React.useContext(context);
|
|
@@ -2512,6 +3175,9 @@ function useTexture(input, optionsOrOnLoad) {
|
|
|
2512
3175
|
const textureCache = useThree((state) => state.textures);
|
|
2513
3176
|
const options = typeof optionsOrOnLoad === "function" ? { onLoad: optionsOrOnLoad } : optionsOrOnLoad ?? {};
|
|
2514
3177
|
const { onLoad, cache = false } = options;
|
|
3178
|
+
const onLoadRef = useRef(onLoad);
|
|
3179
|
+
onLoadRef.current = onLoad;
|
|
3180
|
+
const onLoadCalledForRef = useRef(null);
|
|
2515
3181
|
const urls = useMemo(() => getUrls(input), [input]);
|
|
2516
3182
|
const cachedResult = useMemo(() => {
|
|
2517
3183
|
if (!cache) return null;
|
|
@@ -2522,9 +3188,13 @@ function useTexture(input, optionsOrOnLoad) {
|
|
|
2522
3188
|
TextureLoader,
|
|
2523
3189
|
IsObject(input) ? Object.values(input) : input
|
|
2524
3190
|
);
|
|
3191
|
+
const inputKey = urls.join("\0");
|
|
2525
3192
|
useLayoutEffect(() => {
|
|
2526
|
-
if (
|
|
2527
|
-
|
|
3193
|
+
if (cachedResult) return;
|
|
3194
|
+
if (onLoadCalledForRef.current === inputKey) return;
|
|
3195
|
+
onLoadCalledForRef.current = inputKey;
|
|
3196
|
+
onLoadRef.current?.(loadedTextures);
|
|
3197
|
+
}, [cachedResult, loadedTextures, inputKey]);
|
|
2528
3198
|
useEffect(() => {
|
|
2529
3199
|
if (cachedResult) return;
|
|
2530
3200
|
if ("initTexture" in renderer) {
|
|
@@ -2691,14 +3361,31 @@ function useTextures() {
|
|
|
2691
3361
|
}, [store]);
|
|
2692
3362
|
}
|
|
2693
3363
|
|
|
2694
|
-
function useRenderTarget(
|
|
3364
|
+
function useRenderTarget(widthOrOptions, heightOrOptions, options) {
|
|
2695
3365
|
const isLegacy = useThree((s) => s.isLegacy);
|
|
2696
3366
|
const size = useThree((s) => s.size);
|
|
3367
|
+
let width;
|
|
3368
|
+
let height;
|
|
3369
|
+
let opts;
|
|
3370
|
+
if (typeof widthOrOptions === "object") {
|
|
3371
|
+
opts = widthOrOptions;
|
|
3372
|
+
} else if (typeof widthOrOptions === "number") {
|
|
3373
|
+
width = widthOrOptions;
|
|
3374
|
+
if (typeof heightOrOptions === "object") {
|
|
3375
|
+
height = widthOrOptions;
|
|
3376
|
+
opts = heightOrOptions;
|
|
3377
|
+
} else if (typeof heightOrOptions === "number") {
|
|
3378
|
+
height = heightOrOptions;
|
|
3379
|
+
opts = options;
|
|
3380
|
+
} else {
|
|
3381
|
+
height = widthOrOptions;
|
|
3382
|
+
}
|
|
3383
|
+
}
|
|
2697
3384
|
return useMemo(() => {
|
|
2698
3385
|
const w = width ?? size.width;
|
|
2699
3386
|
const h = height ?? size.height;
|
|
2700
|
-
return new WebGLRenderTarget(w, h,
|
|
2701
|
-
}, [width, height, size.width, size.height,
|
|
3387
|
+
return new WebGLRenderTarget(w, h, opts);
|
|
3388
|
+
}, [width, height, size.width, size.height, opts, isLegacy]);
|
|
2702
3389
|
}
|
|
2703
3390
|
|
|
2704
3391
|
function useStore() {
|
|
@@ -2748,28 +3435,18 @@ function addTail(callback) {
|
|
|
2748
3435
|
function invalidate(state, frames = 1, stackFrames = false) {
|
|
2749
3436
|
getScheduler().invalidate(frames, stackFrames);
|
|
2750
3437
|
}
|
|
2751
|
-
function advance(timestamp
|
|
3438
|
+
function advance(timestamp) {
|
|
2752
3439
|
getScheduler().step(timestamp);
|
|
2753
3440
|
}
|
|
2754
3441
|
|
|
2755
|
-
const version = "10.0.0-alpha.
|
|
3442
|
+
const version = "10.0.0-alpha.2";
|
|
2756
3443
|
const packageData = {
|
|
2757
3444
|
version: version};
|
|
2758
3445
|
|
|
2759
3446
|
function Xb(Tt) {
|
|
2760
3447
|
return Tt && Tt.__esModule && Object.prototype.hasOwnProperty.call(Tt, "default") ? Tt.default : Tt;
|
|
2761
3448
|
}
|
|
2762
|
-
var Rm = { exports: {} }, Og = { exports: {} };
|
|
2763
|
-
/**
|
|
2764
|
-
* @license React
|
|
2765
|
-
* react-reconciler.production.js
|
|
2766
|
-
*
|
|
2767
|
-
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2768
|
-
*
|
|
2769
|
-
* This source code is licensed under the MIT license found in the
|
|
2770
|
-
* LICENSE file in the root directory of this source tree.
|
|
2771
|
-
*/
|
|
2772
|
-
var _b;
|
|
3449
|
+
var Rm = { exports: {} }, Og = { exports: {} }, _b;
|
|
2773
3450
|
function Kb() {
|
|
2774
3451
|
return _b || (_b = 1, (function(Tt) {
|
|
2775
3452
|
Tt.exports = function(m) {
|
|
@@ -3841,7 +4518,6 @@ Error generating stack: ` + l.message + `
|
|
|
3841
4518
|
if (J === cl || J === jc) throw J;
|
|
3842
4519
|
var Ge = Yn(29, J, null, P.mode);
|
|
3843
4520
|
return Ge.lanes = H, Ge.return = P, Ge;
|
|
3844
|
-
} finally {
|
|
3845
4521
|
}
|
|
3846
4522
|
};
|
|
3847
4523
|
}
|
|
@@ -4495,7 +5171,6 @@ Error generating stack: ` + l.message + `
|
|
|
4495
5171
|
var h = r.lastRenderedState, y = d(h, a);
|
|
4496
5172
|
if (c.hasEagerState = true, c.eagerState = y, jn(y, h)) return go(t, r, c, 0), Ne === null && Bn(), false;
|
|
4497
5173
|
} catch {
|
|
4498
|
-
} finally {
|
|
4499
5174
|
}
|
|
4500
5175
|
if (a = yo(t, r, c, l), a !== null) return nt(a, t, l), ns(a, r, l), true;
|
|
4501
5176
|
}
|
|
@@ -6916,10 +7591,7 @@ Error generating stack: ` + l.message + `
|
|
|
6916
7591
|
function vr(t, r) {
|
|
6917
7592
|
Sf(t, r), (t = t.alternate) && Sf(t, r);
|
|
6918
7593
|
}
|
|
6919
|
-
var ie = {}, Fm = React__default, tt = Tb, Lt = Object.assign, hc = Symbol.for("react.element"), zs = Symbol.for("react.transitional.element"), sa = Symbol.for("react.portal"), $a = Symbol.for("react.fragment"), kf = Symbol.for("react.strict_mode"), Cs = Symbol.for("react.profiler"), mc = Symbol.for("react.consumer"), Io = Symbol.for("react.context"), Zi = Symbol.for("react.forward_ref"), Va = Symbol.for("react.suspense"), Te = Symbol.for("react.suspense_list"), wf = Symbol.for("react.memo"), ua = Symbol.for("react.lazy");
|
|
6920
|
-
var gc = Symbol.for("react.activity");
|
|
6921
|
-
var $r = Symbol.for("react.memo_cache_sentinel");
|
|
6922
|
-
var Pf = Symbol.iterator, xf = Symbol.for("react.client.reference"), ca = Array.isArray, M = Fm.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, Yp = m.rendererVersion, zf = m.rendererPackageName, Cf = m.extraDevToolsConfig, Ts = m.getPublicInstance, Hm = m.getRootHostContext, Xp = m.getChildHostContext, Am = m.prepareForCommit, _s = m.resetAfterCommit, Vr = m.createInstance;
|
|
7594
|
+
var ie = {}, Fm = React__default, tt = Tb, Lt = Object.assign, hc = Symbol.for("react.element"), zs = Symbol.for("react.transitional.element"), sa = Symbol.for("react.portal"), $a = Symbol.for("react.fragment"), kf = Symbol.for("react.strict_mode"), Cs = Symbol.for("react.profiler"), mc = Symbol.for("react.consumer"), Io = Symbol.for("react.context"), Zi = Symbol.for("react.forward_ref"), Va = Symbol.for("react.suspense"), Te = Symbol.for("react.suspense_list"), wf = Symbol.for("react.memo"), ua = Symbol.for("react.lazy"), gc = Symbol.for("react.activity"), $r = Symbol.for("react.memo_cache_sentinel"), Pf = Symbol.iterator, xf = Symbol.for("react.client.reference"), ca = Array.isArray, M = Fm.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, Yp = m.rendererVersion, zf = m.rendererPackageName, Cf = m.extraDevToolsConfig, Ts = m.getPublicInstance, Hm = m.getRootHostContext, Xp = m.getChildHostContext, Am = m.prepareForCommit, _s = m.resetAfterCommit, Vr = m.createInstance;
|
|
6923
7595
|
m.cloneMutableInstance;
|
|
6924
7596
|
var yc = m.appendInitialChild, Kp = m.finalizeInitialChildren, Rs = m.shouldSetTextContent, bc = m.createTextInstance;
|
|
6925
7597
|
m.cloneMutableTextInstance;
|
|
@@ -7288,17 +7960,7 @@ No matching component was found for:
|
|
|
7288
7960
|
}, Tt.exports.default = Tt.exports, Object.defineProperty(Tt.exports, "__esModule", { value: true });
|
|
7289
7961
|
})(Og)), Og.exports;
|
|
7290
7962
|
}
|
|
7291
|
-
var Mg = { exports: {} };
|
|
7292
|
-
/**
|
|
7293
|
-
* @license React
|
|
7294
|
-
* react-reconciler.development.js
|
|
7295
|
-
*
|
|
7296
|
-
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
7297
|
-
*
|
|
7298
|
-
* This source code is licensed under the MIT license found in the
|
|
7299
|
-
* LICENSE file in the root directory of this source tree.
|
|
7300
|
-
*/
|
|
7301
|
-
var Rb;
|
|
7963
|
+
var Mg = { exports: {} }, Rb;
|
|
7302
7964
|
function e0() {
|
|
7303
7965
|
return Rb || (Rb = 1, (function(Tt) {
|
|
7304
7966
|
process.env.NODE_ENV !== "production" && (Tt.exports = function(m) {
|
|
@@ -13065,10 +13727,7 @@ Check the render method of %s.`, G(di) || "Unknown")), i = zo(n), i.payload = {
|
|
|
13065
13727
|
function Ic() {
|
|
13066
13728
|
return di;
|
|
13067
13729
|
}
|
|
13068
|
-
var le = {}, qm = React__default, St = Tb, ze = Object.assign, Uh = Symbol.for("react.element"), Ho = Symbol.for("react.transitional.element"), Ao = Symbol.for("react.portal"), ol = Symbol.for("react.fragment"), Lc = Symbol.for("react.strict_mode"), Uf = Symbol.for("react.profiler"), ei = Symbol.for("react.consumer"), on = Symbol.for("react.context"), jn = Symbol.for("react.forward_ref"), Nc = Symbol.for("react.suspense"), Bf = Symbol.for("react.suspense_list"), al = Symbol.for("react.memo"), kt = Symbol.for("react.lazy");
|
|
13069
|
-
var Ds = Symbol.for("react.activity");
|
|
13070
|
-
var Bh = Symbol.for("react.memo_cache_sentinel");
|
|
13071
|
-
var ni = Symbol.iterator, il = Symbol.for("react.client.reference"), fn = Array.isArray, x = qm.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, Jt = m.rendererVersion, Zt = m.rendererPackageName, jo = m.extraDevToolsConfig, ot = m.getPublicInstance, Zr = m.getRootHostContext, Dn = m.getChildHostContext, Ws = m.prepareForCommit, pa = m.resetAfterCommit, Fc = m.createInstance;
|
|
13730
|
+
var le = {}, qm = React__default, St = Tb, ze = Object.assign, Uh = Symbol.for("react.element"), Ho = Symbol.for("react.transitional.element"), Ao = Symbol.for("react.portal"), ol = Symbol.for("react.fragment"), Lc = Symbol.for("react.strict_mode"), Uf = Symbol.for("react.profiler"), ei = Symbol.for("react.consumer"), on = Symbol.for("react.context"), jn = Symbol.for("react.forward_ref"), Nc = Symbol.for("react.suspense"), Bf = Symbol.for("react.suspense_list"), al = Symbol.for("react.memo"), kt = Symbol.for("react.lazy"), Ds = Symbol.for("react.activity"), Bh = Symbol.for("react.memo_cache_sentinel"), ni = Symbol.iterator, il = Symbol.for("react.client.reference"), fn = Array.isArray, x = qm.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, Jt = m.rendererVersion, Zt = m.rendererPackageName, jo = m.extraDevToolsConfig, ot = m.getPublicInstance, Zr = m.getRootHostContext, Dn = m.getChildHostContext, Ws = m.prepareForCommit, pa = m.resetAfterCommit, Fc = m.createInstance;
|
|
13072
13731
|
m.cloneMutableInstance;
|
|
13073
13732
|
var bn = m.appendInitialChild, Ue = m.finalizeInitialChildren, ue = m.shouldSetTextContent, Do = m.createTextInstance;
|
|
13074
13733
|
m.cloneMutableTextInstance;
|
|
@@ -14036,15 +14695,6 @@ function n0() {
|
|
|
14036
14695
|
var t0 = n0();
|
|
14037
14696
|
const r0 = Xb(t0);
|
|
14038
14697
|
|
|
14039
|
-
/**
|
|
14040
|
-
* @license React
|
|
14041
|
-
* react-reconciler-constants.production.js
|
|
14042
|
-
*
|
|
14043
|
-
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
14044
|
-
*
|
|
14045
|
-
* This source code is licensed under the MIT license found in the
|
|
14046
|
-
* LICENSE file in the root directory of this source tree.
|
|
14047
|
-
*/
|
|
14048
14698
|
const t = 1, o = 8, r = 32, e = 2;
|
|
14049
14699
|
|
|
14050
14700
|
function createReconciler(config) {
|
|
@@ -14071,10 +14721,11 @@ function extend(objects) {
|
|
|
14071
14721
|
function validateInstance(type, props) {
|
|
14072
14722
|
const name = toPascalCase(type);
|
|
14073
14723
|
const target = catalogue[name];
|
|
14074
|
-
if (type !== "primitive" && !target)
|
|
14724
|
+
if (type !== "primitive" && !target) {
|
|
14075
14725
|
throw new Error(
|
|
14076
14726
|
`R3F: ${name} is not part of the THREE namespace! Did you forget to extend? See: https://docs.pmnd.rs/react-three-fiber/api/objects#using-3rd-party-objects-declaratively`
|
|
14077
14727
|
);
|
|
14728
|
+
}
|
|
14078
14729
|
if (type === "primitive" && !props.object) throw new Error(`R3F: Primitives without 'object' are invalid!`);
|
|
14079
14730
|
if (props.args !== void 0 && !Array.isArray(props.args)) throw new Error("R3F: The args prop must be an array!");
|
|
14080
14731
|
}
|
|
@@ -14238,6 +14889,7 @@ function swapInstances() {
|
|
|
14238
14889
|
instance.object = instance.props.object ?? new target(...instance.props.args ?? []);
|
|
14239
14890
|
instance.object.__r3f = instance;
|
|
14240
14891
|
setFiberRef(fiber, instance.object);
|
|
14892
|
+
delete instance.appliedOnce;
|
|
14241
14893
|
applyProps(instance.object, instance.props);
|
|
14242
14894
|
if (instance.props.attach) {
|
|
14243
14895
|
attach(parent, instance);
|
|
@@ -14311,8 +14963,22 @@ const reconciler = /* @__PURE__ */ createReconciler({
|
|
|
14311
14963
|
const isTailSibling = fiber.sibling === null || (fiber.flags & Update) === NoFlags;
|
|
14312
14964
|
if (isTailSibling) swapInstances();
|
|
14313
14965
|
},
|
|
14314
|
-
finalizeInitialChildren: () =>
|
|
14315
|
-
|
|
14966
|
+
finalizeInitialChildren: (instance) => {
|
|
14967
|
+
for (const prop in instance.props) {
|
|
14968
|
+
if (isFromRef(instance.props[prop])) return true;
|
|
14969
|
+
}
|
|
14970
|
+
return false;
|
|
14971
|
+
},
|
|
14972
|
+
commitMount(instance) {
|
|
14973
|
+
const resolved = {};
|
|
14974
|
+
for (const prop in instance.props) {
|
|
14975
|
+
const value = instance.props[prop];
|
|
14976
|
+
if (isFromRef(value)) {
|
|
14977
|
+
const ref = value[FROM_REF];
|
|
14978
|
+
if (ref.current != null) resolved[prop] = ref.current;
|
|
14979
|
+
}
|
|
14980
|
+
}
|
|
14981
|
+
if (Object.keys(resolved).length) applyProps(instance.object, resolved);
|
|
14316
14982
|
},
|
|
14317
14983
|
getPublicInstance: (instance) => instance?.object,
|
|
14318
14984
|
prepareForCommit: () => null,
|
|
@@ -14525,14 +15191,17 @@ function createRoot(canvas) {
|
|
|
14525
15191
|
if (!prevRoot) _roots.set(canvas, { fiber, store });
|
|
14526
15192
|
let onCreated;
|
|
14527
15193
|
let lastCamera;
|
|
14528
|
-
|
|
15194
|
+
const lastConfiguredProps = {};
|
|
14529
15195
|
let configured = false;
|
|
14530
15196
|
let pending = null;
|
|
14531
15197
|
return {
|
|
14532
15198
|
async configure(props = {}) {
|
|
14533
15199
|
let resolve;
|
|
14534
15200
|
pending = new Promise((_resolve) => resolve = _resolve);
|
|
14535
|
-
|
|
15201
|
+
const {
|
|
15202
|
+
id: canvasId,
|
|
15203
|
+
primaryCanvas,
|
|
15204
|
+
scheduler: schedulerConfig,
|
|
14536
15205
|
gl: glConfig,
|
|
14537
15206
|
renderer: rendererConfig,
|
|
14538
15207
|
size: propsSize,
|
|
@@ -14540,10 +15209,6 @@ function createRoot(canvas) {
|
|
|
14540
15209
|
events,
|
|
14541
15210
|
onCreated: onCreatedCallback,
|
|
14542
15211
|
shadows = false,
|
|
14543
|
-
linear = false,
|
|
14544
|
-
flat = false,
|
|
14545
|
-
textureColorSpace = SRGBColorSpace,
|
|
14546
|
-
legacy = false,
|
|
14547
15212
|
orthographic = false,
|
|
14548
15213
|
frameloop = "always",
|
|
14549
15214
|
dpr = [1, 2],
|
|
@@ -14554,9 +15219,12 @@ function createRoot(canvas) {
|
|
|
14554
15219
|
onDragOverMissed,
|
|
14555
15220
|
onDropMissed,
|
|
14556
15221
|
autoUpdateFrustum = true,
|
|
14557
|
-
occlusion = false
|
|
15222
|
+
occlusion = false,
|
|
15223
|
+
_sizeProps,
|
|
15224
|
+
forceEven
|
|
14558
15225
|
} = props;
|
|
14559
|
-
|
|
15226
|
+
const textureColorSpace = is.obj(glConfig) && !is.fun(glConfig) && !isRenderer(glConfig) && glConfig.textureColorSpace || is.obj(rendererConfig) && !is.fun(rendererConfig) && !isRenderer(rendererConfig) && rendererConfig.textureColorSpace || SRGBColorSpace;
|
|
15227
|
+
const state = store.getState();
|
|
14560
15228
|
const defaultGLProps = {
|
|
14561
15229
|
canvas,
|
|
14562
15230
|
powerPreference: "high-performance",
|
|
@@ -14568,22 +15236,34 @@ function createRoot(canvas) {
|
|
|
14568
15236
|
"WebGPURenderer (renderer prop) is not available in this build. Use @react-three/fiber or @react-three/fiber/webgpu instead."
|
|
14569
15237
|
);
|
|
14570
15238
|
}
|
|
14571
|
-
(state.isLegacy || glConfig || !R3F_BUILD_WEBGPU);
|
|
15239
|
+
const wantsGL = (state.isLegacy || glConfig || !R3F_BUILD_WEBGPU);
|
|
14572
15240
|
if (glConfig && rendererConfig) {
|
|
14573
15241
|
throw new Error("Cannot use both gl and renderer props at the same time");
|
|
14574
15242
|
}
|
|
14575
15243
|
let renderer = state.internal.actualRenderer;
|
|
15244
|
+
if (primaryCanvas && !R3F_BUILD_WEBGPU) {
|
|
15245
|
+
throw new Error(
|
|
15246
|
+
"The `primaryCanvas` prop for multi-canvas rendering is only available with WebGPU. Use @react-three/fiber/webgpu instead."
|
|
15247
|
+
);
|
|
15248
|
+
}
|
|
15249
|
+
if (primaryCanvas && wantsGL) {
|
|
15250
|
+
throw new Error(
|
|
15251
|
+
"The `primaryCanvas` prop for multi-canvas rendering cannot be used with WebGL. Remove the `gl` prop or use WebGPU."
|
|
15252
|
+
);
|
|
15253
|
+
}
|
|
14576
15254
|
if (!state.internal.actualRenderer) {
|
|
14577
15255
|
renderer = await resolveRenderer(glConfig, defaultGLProps, WebGLRenderer);
|
|
14578
15256
|
state.internal.actualRenderer = renderer;
|
|
14579
|
-
state.set({ isLegacy: true, gl: renderer, renderer });
|
|
15257
|
+
state.set({ isLegacy: true, gl: renderer, renderer, primaryStore: store });
|
|
14580
15258
|
}
|
|
14581
15259
|
let raycaster = state.raycaster;
|
|
14582
15260
|
if (!raycaster) state.set({ raycaster: raycaster = new Raycaster() });
|
|
14583
15261
|
const { params, ...options } = raycastOptions || {};
|
|
14584
15262
|
if (!is.equ(options, raycaster, shallowLoose)) applyProps(raycaster, { ...options });
|
|
14585
|
-
if (!is.equ(params, raycaster.params, shallowLoose))
|
|
15263
|
+
if (!is.equ(params, raycaster.params, shallowLoose)) {
|
|
14586
15264
|
applyProps(raycaster, { params: { ...raycaster.params, ...params } });
|
|
15265
|
+
}
|
|
15266
|
+
let tempCamera = state.camera;
|
|
14587
15267
|
if (!state.camera || state.camera === lastCamera && !is.equ(lastCamera, cameraOptions, shallowLoose)) {
|
|
14588
15268
|
lastCamera = cameraOptions;
|
|
14589
15269
|
const isCamera = cameraOptions?.isCamera;
|
|
@@ -14603,6 +15283,7 @@ function createRoot(canvas) {
|
|
|
14603
15283
|
if (!state.camera && !cameraOptions?.rotation) camera.lookAt(0, 0, 0);
|
|
14604
15284
|
}
|
|
14605
15285
|
state.set({ camera });
|
|
15286
|
+
tempCamera = camera;
|
|
14606
15287
|
raycaster.camera = camera;
|
|
14607
15288
|
}
|
|
14608
15289
|
if (!state.scene) {
|
|
@@ -14620,7 +15301,7 @@ function createRoot(canvas) {
|
|
|
14620
15301
|
rootScene: scene,
|
|
14621
15302
|
internal: { ...prev.internal, container: scene }
|
|
14622
15303
|
}));
|
|
14623
|
-
const camera =
|
|
15304
|
+
const camera = tempCamera;
|
|
14624
15305
|
if (camera && !camera.parent) scene.add(camera);
|
|
14625
15306
|
}
|
|
14626
15307
|
if (events && !state.events.handlers) {
|
|
@@ -14634,9 +15315,17 @@ function createRoot(canvas) {
|
|
|
14634
15315
|
wasEnabled = enabled;
|
|
14635
15316
|
});
|
|
14636
15317
|
}
|
|
15318
|
+
if (_sizeProps !== void 0) {
|
|
15319
|
+
state.set({ _sizeProps });
|
|
15320
|
+
}
|
|
15321
|
+
if (forceEven !== void 0 && state.internal.forceEven !== forceEven) {
|
|
15322
|
+
state.set((prev) => ({ internal: { ...prev.internal, forceEven } }));
|
|
15323
|
+
}
|
|
14637
15324
|
const size = computeInitialSize(canvas, propsSize);
|
|
14638
|
-
if (!is.equ(size, state.size, shallowLoose)) {
|
|
15325
|
+
if (!state._sizeImperative && !is.equ(size, state.size, shallowLoose)) {
|
|
15326
|
+
const wasImperative = state._sizeImperative;
|
|
14639
15327
|
state.setSize(size.width, size.height, size.top, size.left);
|
|
15328
|
+
if (!wasImperative) state.set({ _sizeImperative: false });
|
|
14640
15329
|
}
|
|
14641
15330
|
if (dpr !== void 0 && !is.equ(dpr, lastConfiguredProps.dpr, shallowLoose)) {
|
|
14642
15331
|
state.setDpr(dpr);
|
|
@@ -14658,10 +15347,10 @@ function createRoot(canvas) {
|
|
|
14658
15347
|
lastConfiguredProps.performance = performance;
|
|
14659
15348
|
}
|
|
14660
15349
|
if (!state.xr) {
|
|
14661
|
-
const handleXRFrame = (timestamp,
|
|
15350
|
+
const handleXRFrame = (timestamp, _frame) => {
|
|
14662
15351
|
const state2 = store.getState();
|
|
14663
15352
|
if (state2.frameloop === "never") return;
|
|
14664
|
-
advance(timestamp
|
|
15353
|
+
advance(timestamp);
|
|
14665
15354
|
};
|
|
14666
15355
|
const actualRenderer = state.internal.actualRenderer;
|
|
14667
15356
|
const handleSessionChange = () => {
|
|
@@ -14673,16 +15362,16 @@ function createRoot(canvas) {
|
|
|
14673
15362
|
};
|
|
14674
15363
|
const xr = {
|
|
14675
15364
|
connect() {
|
|
14676
|
-
const { gl, renderer: renderer2
|
|
14677
|
-
const
|
|
14678
|
-
|
|
14679
|
-
|
|
15365
|
+
const { gl, renderer: renderer2 } = store.getState();
|
|
15366
|
+
const xrManager = (renderer2 || gl).xr;
|
|
15367
|
+
xrManager.addEventListener("sessionstart", handleSessionChange);
|
|
15368
|
+
xrManager.addEventListener("sessionend", handleSessionChange);
|
|
14680
15369
|
},
|
|
14681
15370
|
disconnect() {
|
|
14682
|
-
const { gl, renderer: renderer2
|
|
14683
|
-
const
|
|
14684
|
-
|
|
14685
|
-
|
|
15371
|
+
const { gl, renderer: renderer2 } = store.getState();
|
|
15372
|
+
const xrManager = (renderer2 || gl).xr;
|
|
15373
|
+
xrManager.removeEventListener("sessionstart", handleSessionChange);
|
|
15374
|
+
xrManager.removeEventListener("sessionend", handleSessionChange);
|
|
14686
15375
|
}
|
|
14687
15376
|
};
|
|
14688
15377
|
if (typeof renderer.xr?.addEventListener === "function") xr.connect();
|
|
@@ -14694,61 +15383,92 @@ function createRoot(canvas) {
|
|
|
14694
15383
|
const oldType = renderer.shadowMap.type;
|
|
14695
15384
|
renderer.shadowMap.enabled = !!shadows;
|
|
14696
15385
|
if (is.boo(shadows)) {
|
|
14697
|
-
renderer.shadowMap.type =
|
|
15386
|
+
renderer.shadowMap.type = PCFShadowMap;
|
|
14698
15387
|
} else if (is.str(shadows)) {
|
|
15388
|
+
if (shadows === "soft") {
|
|
15389
|
+
notifyDepreciated({
|
|
15390
|
+
heading: 'shadows="soft" is deprecated',
|
|
15391
|
+
body: "Three has depreciated soft and improved basic PCFShadows, we converted for you.",
|
|
15392
|
+
link: "https://github.com/mrdoob/three.js/wiki/Migration-Guide?utm_source=chatgpt.com#181--182"
|
|
15393
|
+
});
|
|
15394
|
+
}
|
|
14699
15395
|
const types = {
|
|
14700
15396
|
basic: BasicShadowMap,
|
|
14701
15397
|
percentage: PCFShadowMap,
|
|
14702
|
-
soft:
|
|
15398
|
+
soft: PCFShadowMap,
|
|
14703
15399
|
variance: VSMShadowMap
|
|
14704
15400
|
};
|
|
14705
|
-
renderer.shadowMap.type = types[shadows] ??
|
|
15401
|
+
renderer.shadowMap.type = types[shadows] ?? PCFShadowMap;
|
|
14706
15402
|
} else if (is.obj(shadows)) {
|
|
14707
15403
|
Object.assign(renderer.shadowMap, shadows);
|
|
14708
15404
|
}
|
|
14709
|
-
if (oldEnabled !== renderer.shadowMap.enabled || oldType !== renderer.shadowMap.type)
|
|
15405
|
+
if (oldEnabled !== renderer.shadowMap.enabled || oldType !== renderer.shadowMap.type) {
|
|
14710
15406
|
renderer.shadowMap.needsUpdate = true;
|
|
14711
|
-
}
|
|
14712
|
-
{
|
|
14713
|
-
const legacyChanged = legacy !== lastConfiguredProps.legacy;
|
|
14714
|
-
const linearChanged = linear !== lastConfiguredProps.linear;
|
|
14715
|
-
const flatChanged = flat !== lastConfiguredProps.flat;
|
|
14716
|
-
if (legacyChanged) {
|
|
14717
|
-
ColorManagement.enabled = !legacy;
|
|
14718
|
-
lastConfiguredProps.legacy = legacy;
|
|
14719
15407
|
}
|
|
14720
|
-
|
|
14721
|
-
|
|
14722
|
-
|
|
14723
|
-
|
|
14724
|
-
if (!configured || flatChanged) {
|
|
14725
|
-
renderer.toneMapping = flat ? NoToneMapping : ACESFilmicToneMapping;
|
|
14726
|
-
lastConfiguredProps.flat = flat;
|
|
14727
|
-
}
|
|
14728
|
-
if (legacyChanged && state.legacy !== legacy) state.set(() => ({ legacy }));
|
|
14729
|
-
if (linearChanged && state.linear !== linear) state.set(() => ({ linear }));
|
|
14730
|
-
if (flatChanged && state.flat !== flat) state.set(() => ({ flat }));
|
|
15408
|
+
}
|
|
15409
|
+
if (!configured) {
|
|
15410
|
+
renderer.outputColorSpace = SRGBColorSpace;
|
|
15411
|
+
renderer.toneMapping = ACESFilmicToneMapping;
|
|
14731
15412
|
}
|
|
14732
15413
|
if (textureColorSpace !== lastConfiguredProps.textureColorSpace) {
|
|
14733
15414
|
if (state.textureColorSpace !== textureColorSpace) state.set(() => ({ textureColorSpace }));
|
|
14734
15415
|
lastConfiguredProps.textureColorSpace = textureColorSpace;
|
|
14735
15416
|
}
|
|
14736
|
-
|
|
14737
|
-
|
|
15417
|
+
const r3fProps = ["textureColorSpace"];
|
|
15418
|
+
const constructorOnlyProps = ["samples", "antialias", "alpha", "canvas", "powerPreference"];
|
|
15419
|
+
const nonApplyProps = [...r3fProps, ...constructorOnlyProps];
|
|
15420
|
+
if (glConfig && !is.fun(glConfig) && !isRenderer(glConfig) && !is.equ(glConfig, renderer, shallowLoose)) {
|
|
15421
|
+
const glProps = {};
|
|
15422
|
+
for (const key in glConfig) {
|
|
15423
|
+
if (!nonApplyProps.includes(key)) glProps[key] = glConfig[key];
|
|
15424
|
+
}
|
|
15425
|
+
applyProps(renderer, glProps);
|
|
15426
|
+
}
|
|
14738
15427
|
if (rendererConfig && !is.fun(rendererConfig) && !isRenderer(rendererConfig) && state.renderer) {
|
|
14739
15428
|
const currentRenderer = state.renderer;
|
|
14740
15429
|
if (!is.equ(rendererConfig, currentRenderer, shallowLoose)) {
|
|
14741
|
-
|
|
15430
|
+
const rendererProps = {};
|
|
15431
|
+
for (const key in rendererConfig) {
|
|
15432
|
+
if (!nonApplyProps.includes(key)) rendererProps[key] = rendererConfig[key];
|
|
15433
|
+
}
|
|
15434
|
+
applyProps(currentRenderer, rendererProps);
|
|
14742
15435
|
}
|
|
14743
15436
|
}
|
|
14744
15437
|
const scheduler = getScheduler();
|
|
14745
15438
|
const rootId = state.internal.rootId;
|
|
14746
15439
|
if (!rootId) {
|
|
14747
|
-
const newRootId = scheduler.generateRootId();
|
|
15440
|
+
const newRootId = canvasId || scheduler.generateRootId();
|
|
14748
15441
|
const unregisterRoot = scheduler.registerRoot(newRootId, {
|
|
14749
15442
|
getState: () => store.getState(),
|
|
14750
15443
|
onError: (err) => store.getState().setError(err)
|
|
14751
15444
|
});
|
|
15445
|
+
const unregisterCanvasTarget = scheduler.register(
|
|
15446
|
+
() => {
|
|
15447
|
+
const state2 = store.getState();
|
|
15448
|
+
if (state2.internal.isMultiCanvas && state2.internal.canvasTarget) {
|
|
15449
|
+
const renderer2 = state2.internal.actualRenderer;
|
|
15450
|
+
renderer2.setCanvasTarget(state2.internal.canvasTarget);
|
|
15451
|
+
}
|
|
15452
|
+
},
|
|
15453
|
+
{
|
|
15454
|
+
id: `${newRootId}_canvasTarget`,
|
|
15455
|
+
rootId: newRootId,
|
|
15456
|
+
phase: "start",
|
|
15457
|
+
system: true
|
|
15458
|
+
}
|
|
15459
|
+
);
|
|
15460
|
+
const unregisterEventsFlush = scheduler.register(
|
|
15461
|
+
() => {
|
|
15462
|
+
const state2 = store.getState();
|
|
15463
|
+
state2.events.flush?.();
|
|
15464
|
+
},
|
|
15465
|
+
{
|
|
15466
|
+
id: `${newRootId}_events`,
|
|
15467
|
+
rootId: newRootId,
|
|
15468
|
+
phase: "input",
|
|
15469
|
+
system: true
|
|
15470
|
+
}
|
|
15471
|
+
);
|
|
14752
15472
|
const unregisterFrustum = scheduler.register(
|
|
14753
15473
|
() => {
|
|
14754
15474
|
const state2 = store.getState();
|
|
@@ -14783,18 +15503,22 @@ function createRoot(canvas) {
|
|
|
14783
15503
|
const userHandlesRender = scheduler.hasUserJobsInPhase("render", newRootId);
|
|
14784
15504
|
if (userHandlesRender || state2.internal.priority) return;
|
|
14785
15505
|
try {
|
|
14786
|
-
if (state2.
|
|
15506
|
+
if (state2.renderPipeline?.render) state2.renderPipeline.render();
|
|
14787
15507
|
else if (renderer2?.render) renderer2.render(state2.scene, state2.camera);
|
|
14788
15508
|
} catch (error) {
|
|
14789
15509
|
state2.setError(error instanceof Error ? error : new Error(String(error)));
|
|
14790
15510
|
}
|
|
14791
15511
|
},
|
|
14792
15512
|
{
|
|
14793
|
-
|
|
15513
|
+
// Use canvas ID directly as job ID if available, otherwise use generated rootId
|
|
15514
|
+
id: canvasId || `${newRootId}_render`,
|
|
14794
15515
|
rootId: newRootId,
|
|
14795
15516
|
phase: "render",
|
|
14796
|
-
system: true
|
|
15517
|
+
system: true,
|
|
14797
15518
|
// Internal flag: this is a system job, not user-controlled
|
|
15519
|
+
// Apply scheduler config for render ordering and rate limiting
|
|
15520
|
+
...schedulerConfig?.after && { after: schedulerConfig.after },
|
|
15521
|
+
...schedulerConfig?.fps && { fps: schedulerConfig.fps }
|
|
14798
15522
|
}
|
|
14799
15523
|
);
|
|
14800
15524
|
state.set((state2) => ({
|
|
@@ -14803,6 +15527,8 @@ function createRoot(canvas) {
|
|
|
14803
15527
|
rootId: newRootId,
|
|
14804
15528
|
unregisterRoot: () => {
|
|
14805
15529
|
unregisterRoot();
|
|
15530
|
+
unregisterCanvasTarget();
|
|
15531
|
+
unregisterEventsFlush();
|
|
14806
15532
|
unregisterFrustum();
|
|
14807
15533
|
unregisterVisibility();
|
|
14808
15534
|
unregisterRender();
|
|
@@ -14861,15 +15587,24 @@ function unmountComponentAtNode(canvas, callback) {
|
|
|
14861
15587
|
const renderer = state.internal.actualRenderer;
|
|
14862
15588
|
const unregisterRoot = state.internal.unregisterRoot;
|
|
14863
15589
|
if (unregisterRoot) unregisterRoot();
|
|
15590
|
+
const unregisterPrimary = state.internal.unregisterPrimary;
|
|
15591
|
+
if (unregisterPrimary) unregisterPrimary();
|
|
15592
|
+
const canvasTarget = state.internal.canvasTarget;
|
|
15593
|
+
if (canvasTarget?.dispose) canvasTarget.dispose();
|
|
14864
15594
|
state.events.disconnect?.();
|
|
14865
15595
|
cleanupHelperGroup(root.store);
|
|
14866
|
-
renderer
|
|
14867
|
-
|
|
14868
|
-
|
|
15596
|
+
if (state.isLegacy && renderer) {
|
|
15597
|
+
;
|
|
15598
|
+
renderer.renderLists?.dispose?.();
|
|
15599
|
+
renderer.forceContextLoss?.();
|
|
15600
|
+
}
|
|
15601
|
+
if (!state.internal.isSecondary) {
|
|
15602
|
+
if (renderer?.xr) state.xr.disconnect();
|
|
15603
|
+
}
|
|
14869
15604
|
dispose(state.scene);
|
|
14870
15605
|
_roots.delete(canvas);
|
|
14871
15606
|
if (callback) callback(canvas);
|
|
14872
|
-
} catch
|
|
15607
|
+
} catch {
|
|
14873
15608
|
}
|
|
14874
15609
|
}, 500);
|
|
14875
15610
|
}
|
|
@@ -14877,36 +15612,34 @@ function unmountComponentAtNode(canvas, callback) {
|
|
|
14877
15612
|
}
|
|
14878
15613
|
}
|
|
14879
15614
|
function createPortal(children, container, state) {
|
|
14880
|
-
return /* @__PURE__ */ jsx(
|
|
15615
|
+
return /* @__PURE__ */ jsx(Portal, { children, container, state });
|
|
14881
15616
|
}
|
|
14882
|
-
function
|
|
15617
|
+
function Portal({ children, container, state }) {
|
|
14883
15618
|
const isRef = useCallback((obj) => obj && "current" in obj, []);
|
|
14884
|
-
const [resolvedContainer,
|
|
15619
|
+
const [resolvedContainer, _setResolvedContainer] = useState(() => {
|
|
14885
15620
|
if (isRef(container)) return container.current ?? null;
|
|
14886
15621
|
return container;
|
|
14887
15622
|
});
|
|
15623
|
+
const setResolvedContainer = useCallback(
|
|
15624
|
+
(newContainer) => {
|
|
15625
|
+
if (!newContainer || newContainer === resolvedContainer) return;
|
|
15626
|
+
_setResolvedContainer(isRef(newContainer) ? newContainer.current : newContainer);
|
|
15627
|
+
},
|
|
15628
|
+
[resolvedContainer, _setResolvedContainer, isRef]
|
|
15629
|
+
);
|
|
14888
15630
|
useMemo(() => {
|
|
14889
|
-
if (isRef(container)) {
|
|
14890
|
-
|
|
14891
|
-
|
|
14892
|
-
|
|
14893
|
-
const updated = container.current;
|
|
14894
|
-
if (updated && updated !== resolvedContainer) {
|
|
14895
|
-
setResolvedContainer(updated);
|
|
14896
|
-
}
|
|
14897
|
-
});
|
|
14898
|
-
} else if (current !== resolvedContainer) {
|
|
14899
|
-
setResolvedContainer(current);
|
|
14900
|
-
}
|
|
14901
|
-
} else if (container !== resolvedContainer) {
|
|
14902
|
-
setResolvedContainer(container);
|
|
15631
|
+
if (isRef(container) && !container.current) {
|
|
15632
|
+
return queueMicrotask(() => {
|
|
15633
|
+
setResolvedContainer(container.current);
|
|
15634
|
+
});
|
|
14903
15635
|
}
|
|
14904
|
-
|
|
15636
|
+
setResolvedContainer(container);
|
|
15637
|
+
}, [container, isRef, setResolvedContainer]);
|
|
14905
15638
|
if (!resolvedContainer) return /* @__PURE__ */ jsx(Fragment, {});
|
|
14906
15639
|
const portalKey = resolvedContainer.uuid ?? `portal-${resolvedContainer.id ?? "unknown"}`;
|
|
14907
|
-
return /* @__PURE__ */ jsx(
|
|
15640
|
+
return /* @__PURE__ */ jsx(PortalInner, { children, container: resolvedContainer, state }, portalKey);
|
|
14908
15641
|
}
|
|
14909
|
-
function
|
|
15642
|
+
function PortalInner({ state = {}, children, container }) {
|
|
14910
15643
|
const { events, size, injectScene = true, ...rest } = state;
|
|
14911
15644
|
const previousRoot = useStore();
|
|
14912
15645
|
const [raycaster] = useState(() => new Raycaster());
|
|
@@ -14927,11 +15660,12 @@ function Portal({ state = {}, children, container }) {
|
|
|
14927
15660
|
};
|
|
14928
15661
|
}, [portalScene, container, injectScene]);
|
|
14929
15662
|
const inject = useMutableCallback((rootState, injectState) => {
|
|
15663
|
+
const resolvedSize = { ...rootState.size, ...injectState.size, ...size };
|
|
14930
15664
|
let viewport = void 0;
|
|
14931
|
-
if (injectState.camera && size) {
|
|
15665
|
+
if (injectState.camera && (size || injectState.size)) {
|
|
14932
15666
|
const camera = injectState.camera;
|
|
14933
|
-
viewport = rootState.viewport.getCurrentViewport(camera, new Vector3(),
|
|
14934
|
-
if (camera !== rootState.camera) updateCamera(camera,
|
|
15667
|
+
viewport = rootState.viewport.getCurrentViewport(camera, new Vector3(), resolvedSize);
|
|
15668
|
+
if (camera !== rootState.camera) updateCamera(camera, resolvedSize);
|
|
14935
15669
|
}
|
|
14936
15670
|
return {
|
|
14937
15671
|
// The intersect consists of the previous root state
|
|
@@ -14948,7 +15682,7 @@ function Portal({ state = {}, children, container }) {
|
|
|
14948
15682
|
previousRoot,
|
|
14949
15683
|
// Events, size and viewport can be overridden by the inject layer
|
|
14950
15684
|
events: { ...rootState.events, ...injectState.events, ...events },
|
|
14951
|
-
size:
|
|
15685
|
+
size: resolvedSize,
|
|
14952
15686
|
viewport: { ...rootState.viewport, ...viewport },
|
|
14953
15687
|
// Layers are allowed to override events
|
|
14954
15688
|
setEvents: (events2) => injectState.set((state2) => ({ ...state2, events: { ...state2.events, ...events2 } })),
|
|
@@ -14960,9 +15694,13 @@ function Portal({ state = {}, children, container }) {
|
|
|
14960
15694
|
const store = createWithEqualityFn((set, get) => ({ ...rest, set, get }));
|
|
14961
15695
|
const onMutate = (prev) => store.setState((state2) => inject.current(prev, state2));
|
|
14962
15696
|
onMutate(previousRoot.getState());
|
|
14963
|
-
previousRoot.subscribe(onMutate);
|
|
14964
15697
|
return store;
|
|
14965
15698
|
}, [previousRoot, container]);
|
|
15699
|
+
useIsomorphicLayoutEffect(() => {
|
|
15700
|
+
const onMutate = (prev) => usePortalStore.setState((state2) => inject.current(prev, state2));
|
|
15701
|
+
const unsubscribe = previousRoot.subscribe(onMutate);
|
|
15702
|
+
return unsubscribe;
|
|
15703
|
+
}, [previousRoot, usePortalStore]);
|
|
14966
15704
|
return (
|
|
14967
15705
|
// @ts-ignore, reconciler types are not maintained
|
|
14968
15706
|
/* @__PURE__ */ jsx(Fragment, { children: reconciler.createPortal(
|
|
@@ -14982,15 +15720,13 @@ function CanvasImpl({
|
|
|
14982
15720
|
fallback,
|
|
14983
15721
|
resize,
|
|
14984
15722
|
style,
|
|
15723
|
+
id,
|
|
14985
15724
|
gl,
|
|
14986
|
-
renderer,
|
|
15725
|
+
renderer: rendererProp,
|
|
14987
15726
|
events = createPointerEvents,
|
|
14988
15727
|
eventSource,
|
|
14989
15728
|
eventPrefix,
|
|
14990
15729
|
shadows,
|
|
14991
|
-
linear,
|
|
14992
|
-
flat,
|
|
14993
|
-
legacy,
|
|
14994
15730
|
orthographic,
|
|
14995
15731
|
frameloop,
|
|
14996
15732
|
dpr,
|
|
@@ -15002,10 +15738,56 @@ function CanvasImpl({
|
|
|
15002
15738
|
onDragOverMissed,
|
|
15003
15739
|
onDropMissed,
|
|
15004
15740
|
onCreated,
|
|
15741
|
+
hmr,
|
|
15742
|
+
width,
|
|
15743
|
+
height,
|
|
15744
|
+
background,
|
|
15745
|
+
forceEven,
|
|
15005
15746
|
...props
|
|
15006
15747
|
}) {
|
|
15748
|
+
const isRendererConfig = typeof rendererProp === "object" && rendererProp !== null && !("render" in rendererProp) && ("primaryCanvas" in rendererProp || "scheduler" in rendererProp);
|
|
15749
|
+
let primaryCanvas;
|
|
15750
|
+
let scheduler;
|
|
15751
|
+
let renderer;
|
|
15752
|
+
if (isRendererConfig) {
|
|
15753
|
+
const { primaryCanvas: pc, scheduler: sc, ...rest } = rendererProp;
|
|
15754
|
+
primaryCanvas = pc;
|
|
15755
|
+
scheduler = sc;
|
|
15756
|
+
renderer = Object.keys(rest).length > 0 ? rest : rendererProp;
|
|
15757
|
+
} else {
|
|
15758
|
+
renderer = rendererProp;
|
|
15759
|
+
}
|
|
15007
15760
|
React.useMemo(() => extend(THREE), []);
|
|
15008
15761
|
const Bridge = useBridge();
|
|
15762
|
+
const backgroundProps = React.useMemo(() => {
|
|
15763
|
+
if (!background) return null;
|
|
15764
|
+
if (typeof background === "object" && !background.isColor) {
|
|
15765
|
+
const { backgroundMap, envMap, files, preset, ...rest } = background;
|
|
15766
|
+
return {
|
|
15767
|
+
...rest,
|
|
15768
|
+
preset,
|
|
15769
|
+
files: envMap || files,
|
|
15770
|
+
backgroundFiles: backgroundMap,
|
|
15771
|
+
background: true
|
|
15772
|
+
};
|
|
15773
|
+
}
|
|
15774
|
+
if (typeof background === "number") {
|
|
15775
|
+
return { color: background, background: true };
|
|
15776
|
+
}
|
|
15777
|
+
if (typeof background === "string") {
|
|
15778
|
+
if (background in presetsObj) {
|
|
15779
|
+
return { preset: background, background: true };
|
|
15780
|
+
}
|
|
15781
|
+
if (/^(https?:\/\/|\/|\.\/|\.\.\/)|\\.(hdr|exr|jpg|jpeg|png|webp|gif)$/i.test(background)) {
|
|
15782
|
+
return { files: background, background: true };
|
|
15783
|
+
}
|
|
15784
|
+
return { color: background, background: true };
|
|
15785
|
+
}
|
|
15786
|
+
if (background.isColor) {
|
|
15787
|
+
return { color: background, background: true };
|
|
15788
|
+
}
|
|
15789
|
+
return null;
|
|
15790
|
+
}, [background]);
|
|
15009
15791
|
const hasInitialSizeRef = React.useRef(false);
|
|
15010
15792
|
const measureConfig = React.useMemo(() => {
|
|
15011
15793
|
if (!hasInitialSizeRef.current) {
|
|
@@ -15022,7 +15804,21 @@ function CanvasImpl({
|
|
|
15022
15804
|
};
|
|
15023
15805
|
}, [resize, hasInitialSizeRef.current]);
|
|
15024
15806
|
const [containerRef, containerRect] = useMeasure(measureConfig);
|
|
15025
|
-
|
|
15807
|
+
const effectiveSize = React.useMemo(() => {
|
|
15808
|
+
let w = width ?? containerRect.width;
|
|
15809
|
+
let h = height ?? containerRect.height;
|
|
15810
|
+
if (forceEven) {
|
|
15811
|
+
w = Math.ceil(w / 2) * 2;
|
|
15812
|
+
h = Math.ceil(h / 2) * 2;
|
|
15813
|
+
}
|
|
15814
|
+
return {
|
|
15815
|
+
width: w,
|
|
15816
|
+
height: h,
|
|
15817
|
+
top: containerRect.top,
|
|
15818
|
+
left: containerRect.left
|
|
15819
|
+
};
|
|
15820
|
+
}, [width, height, containerRect, forceEven]);
|
|
15821
|
+
if (!hasInitialSizeRef.current && effectiveSize.width > 0 && effectiveSize.height > 0) {
|
|
15026
15822
|
hasInitialSizeRef.current = true;
|
|
15027
15823
|
}
|
|
15028
15824
|
const canvasRef = React.useRef(null);
|
|
@@ -15041,7 +15837,7 @@ function CanvasImpl({
|
|
|
15041
15837
|
useIsomorphicLayoutEffect(() => {
|
|
15042
15838
|
effectActiveRef.current = true;
|
|
15043
15839
|
const canvas = canvasRef.current;
|
|
15044
|
-
if (
|
|
15840
|
+
if (effectiveSize.width > 0 && effectiveSize.height > 0 && canvas) {
|
|
15045
15841
|
if (!root.current) {
|
|
15046
15842
|
root.current = createRoot(canvas);
|
|
15047
15843
|
notifyAlpha({
|
|
@@ -15061,21 +15857,24 @@ function CanvasImpl({
|
|
|
15061
15857
|
async function run() {
|
|
15062
15858
|
if (!effectActiveRef.current || !root.current) return;
|
|
15063
15859
|
await root.current.configure({
|
|
15860
|
+
id,
|
|
15861
|
+
primaryCanvas,
|
|
15862
|
+
scheduler,
|
|
15064
15863
|
gl,
|
|
15065
15864
|
renderer,
|
|
15066
15865
|
scene,
|
|
15067
15866
|
events,
|
|
15068
15867
|
shadows,
|
|
15069
|
-
linear,
|
|
15070
|
-
flat,
|
|
15071
|
-
legacy,
|
|
15072
15868
|
orthographic,
|
|
15073
15869
|
frameloop,
|
|
15074
15870
|
dpr,
|
|
15075
15871
|
performance,
|
|
15076
15872
|
raycaster,
|
|
15077
15873
|
camera,
|
|
15078
|
-
size:
|
|
15874
|
+
size: effectiveSize,
|
|
15875
|
+
// Store size props for reset functionality
|
|
15876
|
+
_sizeProps: width !== void 0 || height !== void 0 ? { width, height } : null,
|
|
15877
|
+
forceEven,
|
|
15079
15878
|
// Pass mutable reference to onPointerMissed so it's free to update
|
|
15080
15879
|
onPointerMissed: (...args) => handlePointerMissed.current?.(...args),
|
|
15081
15880
|
onDragOverMissed: (...args) => handleDragOverMissed.current?.(...args),
|
|
@@ -15099,7 +15898,10 @@ function CanvasImpl({
|
|
|
15099
15898
|
});
|
|
15100
15899
|
if (!effectActiveRef.current || !root.current) return;
|
|
15101
15900
|
root.current.render(
|
|
15102
|
-
/* @__PURE__ */ jsx(Bridge, { children: /* @__PURE__ */ jsx(ErrorBoundary, { set: setError, children: /* @__PURE__ */
|
|
15901
|
+
/* @__PURE__ */ jsx(Bridge, { children: /* @__PURE__ */ jsx(ErrorBoundary, { set: setError, children: /* @__PURE__ */ jsxs(React.Suspense, { fallback: /* @__PURE__ */ jsx(Block, { set: setBlock }), children: [
|
|
15902
|
+
backgroundProps && /* @__PURE__ */ jsx(Environment, { ...backgroundProps }),
|
|
15903
|
+
children ?? null
|
|
15904
|
+
] }) }) })
|
|
15103
15905
|
);
|
|
15104
15906
|
}
|
|
15105
15907
|
run();
|
|
@@ -15121,6 +15923,35 @@ function CanvasImpl({
|
|
|
15121
15923
|
};
|
|
15122
15924
|
}
|
|
15123
15925
|
}, []);
|
|
15926
|
+
React.useEffect(() => {
|
|
15927
|
+
if (hmr === false) return;
|
|
15928
|
+
const canvas = canvasRef.current;
|
|
15929
|
+
if (!canvas) return;
|
|
15930
|
+
const handleHMR = () => {
|
|
15931
|
+
queueMicrotask(() => {
|
|
15932
|
+
const rootEntry = _roots.get(canvas);
|
|
15933
|
+
if (rootEntry?.store) {
|
|
15934
|
+
console.log("[R3F] HMR detected \u2014 rebuilding nodes/uniforms");
|
|
15935
|
+
rootEntry.store.setState((state) => ({
|
|
15936
|
+
nodes: {},
|
|
15937
|
+
uniforms: {},
|
|
15938
|
+
_hmrVersion: state._hmrVersion + 1
|
|
15939
|
+
}));
|
|
15940
|
+
}
|
|
15941
|
+
});
|
|
15942
|
+
};
|
|
15943
|
+
if (typeof import.meta !== "undefined" && import.meta.hot) {
|
|
15944
|
+
const hot = import.meta.hot;
|
|
15945
|
+
hot.on("vite:afterUpdate", handleHMR);
|
|
15946
|
+
return () => hot.off?.("vite:afterUpdate", handleHMR);
|
|
15947
|
+
}
|
|
15948
|
+
if (typeof module !== "undefined" && module.hot) {
|
|
15949
|
+
const hot = module.hot;
|
|
15950
|
+
hot.addStatusHandler((status) => {
|
|
15951
|
+
if (status === "idle") handleHMR();
|
|
15952
|
+
});
|
|
15953
|
+
}
|
|
15954
|
+
}, [hmr]);
|
|
15124
15955
|
const pointerEvents = eventSource ? "none" : "auto";
|
|
15125
15956
|
return /* @__PURE__ */ jsx(
|
|
15126
15957
|
"div",
|
|
@@ -15135,7 +15966,16 @@ function CanvasImpl({
|
|
|
15135
15966
|
...style
|
|
15136
15967
|
},
|
|
15137
15968
|
...props,
|
|
15138
|
-
children: /* @__PURE__ */ jsx("div", { ref: containerRef, className: "r3f-canvas-container", style: { width: "100%", height: "100%" }, children: /* @__PURE__ */ jsx(
|
|
15969
|
+
children: /* @__PURE__ */ jsx("div", { ref: containerRef, className: "r3f-canvas-container", style: { width: "100%", height: "100%" }, children: /* @__PURE__ */ jsx(
|
|
15970
|
+
"canvas",
|
|
15971
|
+
{
|
|
15972
|
+
ref: canvasRef,
|
|
15973
|
+
id,
|
|
15974
|
+
className: "r3f-canvas",
|
|
15975
|
+
style: { display: "block", width: "100%", height: "100%" },
|
|
15976
|
+
children: fallback
|
|
15977
|
+
}
|
|
15978
|
+
) })
|
|
15139
15979
|
}
|
|
15140
15980
|
);
|
|
15141
15981
|
}
|
|
@@ -15145,4 +15985,4 @@ function Canvas(props) {
|
|
|
15145
15985
|
|
|
15146
15986
|
extend(THREE);
|
|
15147
15987
|
|
|
15148
|
-
export { Block, Canvas, ErrorBoundary, IsObject, R3F_BUILD_LEGACY, R3F_BUILD_WEBGPU, REACT_INTERNAL_PROPS, RESERVED_PROPS, Scheduler, Texture, _roots, act, addAfterEffect, addEffect, addTail, advance, applyProps, attach, buildGraph, calculateDpr, context, createEvents, createPointerEvents, createPortal, createRoot, createStore, detach, diffProps, dispose, createPointerEvents as events, extend, findInitialRoot, flushSync, getInstanceProps, getRootState, getScheduler, getUuidPrefix, hasConstructor, invalidate, invalidateInstance, is, isColorRepresentation, isCopyable, isObject3D, isOrthographicCamera, isRef, isRenderer, isTexture, isVectorLike, prepare, reconciler, removeInteractivity, resolve, unmountComponentAtNode, updateCamera, updateFrustum, useBridge, useFrame, useGraph, useInstanceHandle, useIsomorphicLayoutEffect, useLoader, useMutableCallback, useRenderTarget, useStore, useTexture, useTextures, useThree };
|
|
15988
|
+
export { Block, Canvas, Environment, EnvironmentCube, EnvironmentMap, EnvironmentPortal, ErrorBoundary, FROM_REF, IsObject, ONCE, Portal, R3F_BUILD_LEGACY, R3F_BUILD_WEBGPU, REACT_INTERNAL_PROPS, RESERVED_PROPS, Scheduler, Texture, _roots, act, addAfterEffect, addEffect, addTail, advance, applyProps, attach, buildGraph, calculateDpr, context, createEvents, createPointerEvents, createPortal, createRoot, createStore, detach, diffProps, dispose, createPointerEvents as events, extend, findInitialRoot, flushSync, fromRef, getInstanceProps, getPrimary, getPrimaryIds, getRootState, getScheduler, getUuidPrefix, hasConstructor, hasPrimary, invalidate, invalidateInstance, is, isColorRepresentation, isCopyable, isFromRef, isObject3D, isOnce, isOrthographicCamera, isRef, isRenderer, isTexture, isVectorLike, once, prepare, presetsObj, reconciler, registerPrimary, removeInteractivity, resolve, unmountComponentAtNode, unregisterPrimary, updateCamera, updateFrustum, useBridge, useEnvironment, useFrame, useGraph, useInstanceHandle, useIsomorphicLayoutEffect, useLoader, useMutableCallback, useRenderTarget, useStore, useTexture, useTextures, useThree, waitForPrimary };
|