@react-three/fiber 10.0.0-canary.8f5b4d3 → 10.0.0-canary.ac30da2
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/dist/index.cjs +49 -33
- package/dist/index.d.cts +18 -1
- package/dist/index.d.mts +18 -1
- package/dist/index.d.ts +18 -1
- package/dist/index.mjs +49 -33
- package/dist/legacy.cjs +48 -37
- package/dist/legacy.d.cts +17 -4
- package/dist/legacy.d.mts +17 -4
- package/dist/legacy.d.ts +17 -4
- package/dist/legacy.mjs +48 -37
- package/dist/webgpu/index.cjs +94 -59
- package/dist/webgpu/index.d.cts +40 -51
- package/dist/webgpu/index.d.mts +40 -51
- package/dist/webgpu/index.d.ts +40 -51
- package/dist/webgpu/index.mjs +94 -59
- package/package.json +3 -3
- package/readme.md +1 -1
- package/react-reconciler/constants.d.ts +0 -7
- package/react-reconciler/constants.js +0 -1
- package/react-reconciler/index.d.ts +0 -1044
- package/react-reconciler/index.js +0 -208
package/dist/legacy.cjs
CHANGED
|
@@ -50,11 +50,9 @@ const Tb__default = /*#__PURE__*/_interopDefaultCompat(Tb);
|
|
|
50
50
|
|
|
51
51
|
const R3F_BUILD_LEGACY = true;
|
|
52
52
|
const R3F_BUILD_WEBGPU = false;
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
57
|
-
};
|
|
53
|
+
async function loadInspector() {
|
|
54
|
+
throw new Error("Inspector is not available in legacy builds. Use @react-three/fiber/webgpu instead.");
|
|
55
|
+
}
|
|
58
56
|
const WebGPURenderer = class WebGPURenderer2 {
|
|
59
57
|
constructor() {
|
|
60
58
|
throw new Error("WebGPURenderer is not available in legacy builds. Use @react-three/fiber/webgpu instead.");
|
|
@@ -67,12 +65,12 @@ const THREE = /*#__PURE__*/_mergeNamespaces({
|
|
|
67
65
|
__proto__: null,
|
|
68
66
|
CubeRenderTarget: CubeRenderTarget,
|
|
69
67
|
CubeRenderTargetCompat: three.WebGLCubeRenderTarget,
|
|
70
|
-
Inspector: Inspector,
|
|
71
68
|
R3F_BUILD_LEGACY: R3F_BUILD_LEGACY,
|
|
72
69
|
R3F_BUILD_WEBGPU: R3F_BUILD_WEBGPU,
|
|
73
70
|
RenderTarget: RenderTarget,
|
|
74
71
|
RenderTargetCompat: three.WebGLRenderTarget,
|
|
75
|
-
WebGPURenderer: WebGPURenderer
|
|
72
|
+
WebGPURenderer: WebGPURenderer,
|
|
73
|
+
loadInspector: loadInspector
|
|
76
74
|
}, [three__namespace]);
|
|
77
75
|
|
|
78
76
|
const primaryRegistry = /* @__PURE__ */ new Map();
|
|
@@ -1070,17 +1068,10 @@ const createStore = (invalidate, advance) => {
|
|
|
1070
1068
|
oldSize = size;
|
|
1071
1069
|
oldDpr = viewport.dpr;
|
|
1072
1070
|
updateCamera(camera, size);
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
if (viewport.dpr > 0) actualRenderer.setPixelRatio(viewport.dpr);
|
|
1078
|
-
actualRenderer.setSize(size.width, size.height, false);
|
|
1079
|
-
if (canvasTarget) {
|
|
1080
|
-
if (viewport.dpr > 0) canvasTarget.setPixelRatio(viewport.dpr);
|
|
1081
|
-
canvasTarget.setSize(size.width, size.height, false);
|
|
1082
|
-
}
|
|
1083
|
-
}
|
|
1071
|
+
const resizeTarget = canvasTarget ?? actualRenderer;
|
|
1072
|
+
if (viewport.dpr > 0) resizeTarget.setPixelRatio(viewport.dpr);
|
|
1073
|
+
resizeTarget.setSize(size.width, size.height, false);
|
|
1074
|
+
internal.canvasTargetSizeDirty = true;
|
|
1084
1075
|
}
|
|
1085
1076
|
if (camera !== oldCamera) {
|
|
1086
1077
|
oldCamera = camera;
|
|
@@ -1142,7 +1133,11 @@ function useLoader(loader, input, extensions, onProgress, cacheKey) {
|
|
|
1142
1133
|
const results = cacheKeys.map(
|
|
1143
1134
|
(key, index) => suspendReact.suspend(() => fn(loader, inputs[index]), [loader, key], { equal: is.equ })
|
|
1144
1135
|
);
|
|
1145
|
-
|
|
1136
|
+
const stableRef = React.useRef(null);
|
|
1137
|
+
const previous = stableRef.current;
|
|
1138
|
+
const stable = previous !== null && previous.length === results.length && previous.every((value, i) => value === results[i]) ? previous : results;
|
|
1139
|
+
stableRef.current = stable;
|
|
1140
|
+
return Array.isArray(input) ? stable : stable[0];
|
|
1146
1141
|
}
|
|
1147
1142
|
useLoader.preload = function(loader, input, extensions, onProgress, cacheKey) {
|
|
1148
1143
|
const inputs = Array.isArray(input) ? input : [input];
|
|
@@ -1307,6 +1302,11 @@ function getUrls(input) {
|
|
|
1307
1302
|
if (Array.isArray(input)) return input;
|
|
1308
1303
|
return Object.values(input);
|
|
1309
1304
|
}
|
|
1305
|
+
function inputSignature(input) {
|
|
1306
|
+
if (typeof input === "string") return input;
|
|
1307
|
+
if (Array.isArray(input)) return input.join("\0");
|
|
1308
|
+
return Object.keys(input).sort().map((key) => `${key}\0${input[key]}`).join("");
|
|
1309
|
+
}
|
|
1310
1310
|
function allUrlsCached(urls, textureCache) {
|
|
1311
1311
|
return urls.every((url) => textureCache.has(url));
|
|
1312
1312
|
}
|
|
@@ -1332,18 +1332,19 @@ function useTexture(input, optionsOrOnLoad) {
|
|
|
1332
1332
|
const onLoadRef = React.useRef(onLoad);
|
|
1333
1333
|
onLoadRef.current = onLoad;
|
|
1334
1334
|
const onLoadCalledForRef = React.useRef(null);
|
|
1335
|
-
const
|
|
1335
|
+
const inputKey = React.useMemo(() => inputSignature(input), [input]);
|
|
1336
|
+
const stableInput = React.useMemo(() => input, [inputKey]);
|
|
1337
|
+
const urls = React.useMemo(() => getUrls(stableInput), [stableInput]);
|
|
1336
1338
|
const cachedResult = React.useMemo(() => {
|
|
1337
1339
|
if (!cache) return null;
|
|
1338
1340
|
const textures = store.getState().textures;
|
|
1339
1341
|
if (!allUrlsCached(urls, textures)) return null;
|
|
1340
|
-
return buildFromCache(
|
|
1341
|
-
}, [cache, urls,
|
|
1342
|
+
return buildFromCache(stableInput, textures);
|
|
1343
|
+
}, [cache, urls, stableInput, store]);
|
|
1342
1344
|
const loadedTextures = useLoader(
|
|
1343
1345
|
three.TextureLoader,
|
|
1344
|
-
IsObject(
|
|
1346
|
+
IsObject(stableInput) ? Object.values(stableInput) : stableInput
|
|
1345
1347
|
);
|
|
1346
|
-
const inputKey = urls.join("\0");
|
|
1347
1348
|
React.useLayoutEffect(() => {
|
|
1348
1349
|
if (cachedResult) return;
|
|
1349
1350
|
if (onLoadCalledForRef.current === inputKey) return;
|
|
@@ -1370,28 +1371,28 @@ function useTexture(input, optionsOrOnLoad) {
|
|
|
1370
1371
|
}, [renderer, loadedTextures, cachedResult]);
|
|
1371
1372
|
const mappedTextures = React.useMemo(() => {
|
|
1372
1373
|
if (cachedResult) return cachedResult;
|
|
1373
|
-
if (IsObject(
|
|
1374
|
+
if (IsObject(stableInput)) {
|
|
1374
1375
|
const keyed = {};
|
|
1375
1376
|
const textureArray = loadedTextures;
|
|
1376
1377
|
let i = 0;
|
|
1377
|
-
for (const key in
|
|
1378
|
+
for (const key in stableInput) keyed[key] = textureArray[i++];
|
|
1378
1379
|
return keyed;
|
|
1379
1380
|
} else {
|
|
1380
1381
|
return loadedTextures;
|
|
1381
1382
|
}
|
|
1382
|
-
}, [
|
|
1383
|
+
}, [stableInput, loadedTextures, cachedResult]);
|
|
1383
1384
|
React.useEffect(() => {
|
|
1384
1385
|
if (!cache) return;
|
|
1385
1386
|
const urlTextureMap = [];
|
|
1386
|
-
if (typeof
|
|
1387
|
-
urlTextureMap.push([
|
|
1388
|
-
} else if (Array.isArray(
|
|
1387
|
+
if (typeof stableInput === "string") {
|
|
1388
|
+
urlTextureMap.push([stableInput, mappedTextures]);
|
|
1389
|
+
} else if (Array.isArray(stableInput)) {
|
|
1389
1390
|
const textureArray = mappedTextures;
|
|
1390
|
-
|
|
1391
|
-
} else if (IsObject(
|
|
1391
|
+
stableInput.forEach((url, i) => urlTextureMap.push([url, textureArray[i]]));
|
|
1392
|
+
} else if (IsObject(stableInput)) {
|
|
1392
1393
|
const textureRecord = mappedTextures;
|
|
1393
|
-
for (const key in
|
|
1394
|
-
const url =
|
|
1394
|
+
for (const key in stableInput) {
|
|
1395
|
+
const url = stableInput[key];
|
|
1395
1396
|
urlTextureMap.push([url, textureRecord[key]]);
|
|
1396
1397
|
}
|
|
1397
1398
|
}
|
|
@@ -1420,7 +1421,7 @@ function useTexture(input, optionsOrOnLoad) {
|
|
|
1420
1421
|
}
|
|
1421
1422
|
return { _textureRefs: refs };
|
|
1422
1423
|
});
|
|
1423
|
-
}, [cache,
|
|
1424
|
+
}, [cache, stableInput, mappedTextures, store]);
|
|
1424
1425
|
return mappedTextures;
|
|
1425
1426
|
}
|
|
1426
1427
|
useTexture.preload = (url) => useLoader.preload(three.TextureLoader, url);
|
|
@@ -12978,7 +12979,10 @@ function releaseInternalPointerCapture(internal, obj, pointerId) {
|
|
|
12978
12979
|
const captureData = pointerState.captured.get(obj);
|
|
12979
12980
|
if (captureData) {
|
|
12980
12981
|
pointerState.captured.delete(obj);
|
|
12981
|
-
|
|
12982
|
+
try {
|
|
12983
|
+
captureData.target.releasePointerCapture?.(pointerId);
|
|
12984
|
+
} catch {
|
|
12985
|
+
}
|
|
12982
12986
|
}
|
|
12983
12987
|
}
|
|
12984
12988
|
function swapInteractivity(store, object, newObject) {
|
|
@@ -13072,7 +13076,9 @@ function createEvents(store) {
|
|
|
13072
13076
|
state2.events.compute?.(event, state2, state2.previousRoot?.getState());
|
|
13073
13077
|
if (state2.raycaster.camera === void 0) state2.raycaster.camera = null;
|
|
13074
13078
|
}
|
|
13075
|
-
|
|
13079
|
+
if (!state2.raycaster.camera) return [];
|
|
13080
|
+
obj.updateWorldMatrix(true, true);
|
|
13081
|
+
return state2.raycaster.intersectObject(obj, true);
|
|
13076
13082
|
}
|
|
13077
13083
|
let hits = eventsObjects.flatMap(handleRaycast).sort((a, b) => {
|
|
13078
13084
|
const aInteractivePriority = a.object.userData?.interactivePriority;
|
|
@@ -14400,6 +14406,10 @@ function createRoot(canvas) {
|
|
|
14400
14406
|
if (state2.internal.isMultiCanvas && state2.internal.canvasTarget) {
|
|
14401
14407
|
const renderer2 = state2.internal.actualRenderer;
|
|
14402
14408
|
renderer2.setCanvasTarget(state2.internal.canvasTarget);
|
|
14409
|
+
if (state2.internal.canvasTargetSizeDirty) {
|
|
14410
|
+
state2.internal.canvasTargetSizeDirty = false;
|
|
14411
|
+
renderer2.backend?.updateSize?.();
|
|
14412
|
+
}
|
|
14403
14413
|
}
|
|
14404
14414
|
},
|
|
14405
14415
|
{
|
|
@@ -15132,6 +15142,7 @@ function CanvasImpl({
|
|
|
15132
15142
|
const canvas = canvasRef.current;
|
|
15133
15143
|
if (canvas) {
|
|
15134
15144
|
return () => {
|
|
15145
|
+
if (canvas.isConnected) return;
|
|
15135
15146
|
unmountComponentAtNode(canvas);
|
|
15136
15147
|
root.current = null;
|
|
15137
15148
|
};
|
package/dist/legacy.d.cts
CHANGED
|
@@ -38,9 +38,9 @@ function _mergeNamespaces(n, m) {
|
|
|
38
38
|
declare const R3F_BUILD_LEGACY = true;
|
|
39
39
|
declare const R3F_BUILD_WEBGPU = false;
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
type Inspector = never;
|
|
42
|
+
/** Not available on the legacy (WebGL-only) entry. */
|
|
43
|
+
declare function loadInspector(): Promise<never>;
|
|
44
44
|
declare const WebGPURenderer: {
|
|
45
45
|
new (): {};
|
|
46
46
|
};
|
|
@@ -58,7 +58,8 @@ var THREE = /*#__PURE__*/_mergeNamespaces({
|
|
|
58
58
|
R3F_BUILD_WEBGPU: R3F_BUILD_WEBGPU,
|
|
59
59
|
RenderTarget: RenderTarget,
|
|
60
60
|
RenderTargetCompat: WebGLRenderTarget,
|
|
61
|
-
WebGPURenderer: WebGPURenderer
|
|
61
|
+
WebGPURenderer: WebGPURenderer,
|
|
62
|
+
loadInspector: loadInspector
|
|
62
63
|
}, [THREE$1]);
|
|
63
64
|
|
|
64
65
|
//* Utility Types ==============================
|
|
@@ -496,6 +497,18 @@ interface InternalState {
|
|
|
496
497
|
* @see https://threejs.org/docs/#api/en/renderers/common/CanvasTarget
|
|
497
498
|
*/
|
|
498
499
|
canvasTarget?: CanvasTarget
|
|
500
|
+
/**
|
|
501
|
+
* Set when this root's canvas target has been resized and the backend's cached render pass
|
|
502
|
+
* descriptor (which holds a depth-stencil view built once per canvas) is therefore stale.
|
|
503
|
+
*
|
|
504
|
+
* Flushed by the canvas-target job in the `start` phase, which is the only place this root's
|
|
505
|
+
* target is guaranteed to be the renderer's active one — `backend.updateSize()` operates on
|
|
506
|
+
* whatever `getCanvasTarget()` returns, so calling it from the resize subscription would
|
|
507
|
+
* invalidate some other canvas's descriptor instead.
|
|
508
|
+
*
|
|
509
|
+
* @see https://github.com/pmndrs/react-three-fiber/issues/3847
|
|
510
|
+
*/
|
|
511
|
+
canvasTargetSizeDirty?: boolean
|
|
499
512
|
/**
|
|
500
513
|
* Whether multi-canvas rendering is active.
|
|
501
514
|
* True when any canvas uses `renderer={{ primaryCanvas: 'id' }}` to share a renderer.
|
package/dist/legacy.d.mts
CHANGED
|
@@ -38,9 +38,9 @@ function _mergeNamespaces(n, m) {
|
|
|
38
38
|
declare const R3F_BUILD_LEGACY = true;
|
|
39
39
|
declare const R3F_BUILD_WEBGPU = false;
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
type Inspector = never;
|
|
42
|
+
/** Not available on the legacy (WebGL-only) entry. */
|
|
43
|
+
declare function loadInspector(): Promise<never>;
|
|
44
44
|
declare const WebGPURenderer: {
|
|
45
45
|
new (): {};
|
|
46
46
|
};
|
|
@@ -58,7 +58,8 @@ var THREE = /*#__PURE__*/_mergeNamespaces({
|
|
|
58
58
|
R3F_BUILD_WEBGPU: R3F_BUILD_WEBGPU,
|
|
59
59
|
RenderTarget: RenderTarget,
|
|
60
60
|
RenderTargetCompat: WebGLRenderTarget,
|
|
61
|
-
WebGPURenderer: WebGPURenderer
|
|
61
|
+
WebGPURenderer: WebGPURenderer,
|
|
62
|
+
loadInspector: loadInspector
|
|
62
63
|
}, [THREE$1]);
|
|
63
64
|
|
|
64
65
|
//* Utility Types ==============================
|
|
@@ -496,6 +497,18 @@ interface InternalState {
|
|
|
496
497
|
* @see https://threejs.org/docs/#api/en/renderers/common/CanvasTarget
|
|
497
498
|
*/
|
|
498
499
|
canvasTarget?: CanvasTarget
|
|
500
|
+
/**
|
|
501
|
+
* Set when this root's canvas target has been resized and the backend's cached render pass
|
|
502
|
+
* descriptor (which holds a depth-stencil view built once per canvas) is therefore stale.
|
|
503
|
+
*
|
|
504
|
+
* Flushed by the canvas-target job in the `start` phase, which is the only place this root's
|
|
505
|
+
* target is guaranteed to be the renderer's active one — `backend.updateSize()` operates on
|
|
506
|
+
* whatever `getCanvasTarget()` returns, so calling it from the resize subscription would
|
|
507
|
+
* invalidate some other canvas's descriptor instead.
|
|
508
|
+
*
|
|
509
|
+
* @see https://github.com/pmndrs/react-three-fiber/issues/3847
|
|
510
|
+
*/
|
|
511
|
+
canvasTargetSizeDirty?: boolean
|
|
499
512
|
/**
|
|
500
513
|
* Whether multi-canvas rendering is active.
|
|
501
514
|
* True when any canvas uses `renderer={{ primaryCanvas: 'id' }}` to share a renderer.
|
package/dist/legacy.d.ts
CHANGED
|
@@ -38,9 +38,9 @@ function _mergeNamespaces(n, m) {
|
|
|
38
38
|
declare const R3F_BUILD_LEGACY = true;
|
|
39
39
|
declare const R3F_BUILD_WEBGPU = false;
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
type Inspector = never;
|
|
42
|
+
/** Not available on the legacy (WebGL-only) entry. */
|
|
43
|
+
declare function loadInspector(): Promise<never>;
|
|
44
44
|
declare const WebGPURenderer: {
|
|
45
45
|
new (): {};
|
|
46
46
|
};
|
|
@@ -58,7 +58,8 @@ var THREE = /*#__PURE__*/_mergeNamespaces({
|
|
|
58
58
|
R3F_BUILD_WEBGPU: R3F_BUILD_WEBGPU,
|
|
59
59
|
RenderTarget: RenderTarget,
|
|
60
60
|
RenderTargetCompat: WebGLRenderTarget,
|
|
61
|
-
WebGPURenderer: WebGPURenderer
|
|
61
|
+
WebGPURenderer: WebGPURenderer,
|
|
62
|
+
loadInspector: loadInspector
|
|
62
63
|
}, [THREE$1]);
|
|
63
64
|
|
|
64
65
|
//* Utility Types ==============================
|
|
@@ -496,6 +497,18 @@ interface InternalState {
|
|
|
496
497
|
* @see https://threejs.org/docs/#api/en/renderers/common/CanvasTarget
|
|
497
498
|
*/
|
|
498
499
|
canvasTarget?: CanvasTarget
|
|
500
|
+
/**
|
|
501
|
+
* Set when this root's canvas target has been resized and the backend's cached render pass
|
|
502
|
+
* descriptor (which holds a depth-stencil view built once per canvas) is therefore stale.
|
|
503
|
+
*
|
|
504
|
+
* Flushed by the canvas-target job in the `start` phase, which is the only place this root's
|
|
505
|
+
* target is guaranteed to be the renderer's active one — `backend.updateSize()` operates on
|
|
506
|
+
* whatever `getCanvasTarget()` returns, so calling it from the resize subscription would
|
|
507
|
+
* invalidate some other canvas's descriptor instead.
|
|
508
|
+
*
|
|
509
|
+
* @see https://github.com/pmndrs/react-three-fiber/issues/3847
|
|
510
|
+
*/
|
|
511
|
+
canvasTargetSizeDirty?: boolean
|
|
499
512
|
/**
|
|
500
513
|
* Whether multi-canvas rendering is active.
|
|
501
514
|
* True when any canvas uses `renderer={{ primaryCanvas: 'id' }}` to share a renderer.
|
package/dist/legacy.mjs
CHANGED
|
@@ -30,11 +30,9 @@ function _mergeNamespaces(n, m) {
|
|
|
30
30
|
|
|
31
31
|
const R3F_BUILD_LEGACY = true;
|
|
32
32
|
const R3F_BUILD_WEBGPU = false;
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}
|
|
37
|
-
};
|
|
33
|
+
async function loadInspector() {
|
|
34
|
+
throw new Error("Inspector is not available in legacy builds. Use @react-three/fiber/webgpu instead.");
|
|
35
|
+
}
|
|
38
36
|
const WebGPURenderer = class WebGPURenderer2 {
|
|
39
37
|
constructor() {
|
|
40
38
|
throw new Error("WebGPURenderer is not available in legacy builds. Use @react-three/fiber/webgpu instead.");
|
|
@@ -47,12 +45,12 @@ const THREE = /*#__PURE__*/_mergeNamespaces({
|
|
|
47
45
|
__proto__: null,
|
|
48
46
|
CubeRenderTarget: CubeRenderTarget,
|
|
49
47
|
CubeRenderTargetCompat: WebGLCubeRenderTarget,
|
|
50
|
-
Inspector: Inspector,
|
|
51
48
|
R3F_BUILD_LEGACY: R3F_BUILD_LEGACY,
|
|
52
49
|
R3F_BUILD_WEBGPU: R3F_BUILD_WEBGPU,
|
|
53
50
|
RenderTarget: RenderTarget,
|
|
54
51
|
RenderTargetCompat: WebGLRenderTarget,
|
|
55
|
-
WebGPURenderer: WebGPURenderer
|
|
52
|
+
WebGPURenderer: WebGPURenderer,
|
|
53
|
+
loadInspector: loadInspector
|
|
56
54
|
}, [three]);
|
|
57
55
|
|
|
58
56
|
const primaryRegistry = /* @__PURE__ */ new Map();
|
|
@@ -1050,17 +1048,10 @@ const createStore = (invalidate, advance) => {
|
|
|
1050
1048
|
oldSize = size;
|
|
1051
1049
|
oldDpr = viewport.dpr;
|
|
1052
1050
|
updateCamera(camera, size);
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
if (viewport.dpr > 0) actualRenderer.setPixelRatio(viewport.dpr);
|
|
1058
|
-
actualRenderer.setSize(size.width, size.height, false);
|
|
1059
|
-
if (canvasTarget) {
|
|
1060
|
-
if (viewport.dpr > 0) canvasTarget.setPixelRatio(viewport.dpr);
|
|
1061
|
-
canvasTarget.setSize(size.width, size.height, false);
|
|
1062
|
-
}
|
|
1063
|
-
}
|
|
1051
|
+
const resizeTarget = canvasTarget ?? actualRenderer;
|
|
1052
|
+
if (viewport.dpr > 0) resizeTarget.setPixelRatio(viewport.dpr);
|
|
1053
|
+
resizeTarget.setSize(size.width, size.height, false);
|
|
1054
|
+
internal.canvasTargetSizeDirty = true;
|
|
1064
1055
|
}
|
|
1065
1056
|
if (camera !== oldCamera) {
|
|
1066
1057
|
oldCamera = camera;
|
|
@@ -1122,7 +1113,11 @@ function useLoader(loader, input, extensions, onProgress, cacheKey) {
|
|
|
1122
1113
|
const results = cacheKeys.map(
|
|
1123
1114
|
(key, index) => suspend(() => fn(loader, inputs[index]), [loader, key], { equal: is.equ })
|
|
1124
1115
|
);
|
|
1125
|
-
|
|
1116
|
+
const stableRef = useRef(null);
|
|
1117
|
+
const previous = stableRef.current;
|
|
1118
|
+
const stable = previous !== null && previous.length === results.length && previous.every((value, i) => value === results[i]) ? previous : results;
|
|
1119
|
+
stableRef.current = stable;
|
|
1120
|
+
return Array.isArray(input) ? stable : stable[0];
|
|
1126
1121
|
}
|
|
1127
1122
|
useLoader.preload = function(loader, input, extensions, onProgress, cacheKey) {
|
|
1128
1123
|
const inputs = Array.isArray(input) ? input : [input];
|
|
@@ -1287,6 +1282,11 @@ function getUrls(input) {
|
|
|
1287
1282
|
if (Array.isArray(input)) return input;
|
|
1288
1283
|
return Object.values(input);
|
|
1289
1284
|
}
|
|
1285
|
+
function inputSignature(input) {
|
|
1286
|
+
if (typeof input === "string") return input;
|
|
1287
|
+
if (Array.isArray(input)) return input.join("\0");
|
|
1288
|
+
return Object.keys(input).sort().map((key) => `${key}\0${input[key]}`).join("");
|
|
1289
|
+
}
|
|
1290
1290
|
function allUrlsCached(urls, textureCache) {
|
|
1291
1291
|
return urls.every((url) => textureCache.has(url));
|
|
1292
1292
|
}
|
|
@@ -1312,18 +1312,19 @@ function useTexture(input, optionsOrOnLoad) {
|
|
|
1312
1312
|
const onLoadRef = useRef(onLoad);
|
|
1313
1313
|
onLoadRef.current = onLoad;
|
|
1314
1314
|
const onLoadCalledForRef = useRef(null);
|
|
1315
|
-
const
|
|
1315
|
+
const inputKey = useMemo(() => inputSignature(input), [input]);
|
|
1316
|
+
const stableInput = useMemo(() => input, [inputKey]);
|
|
1317
|
+
const urls = useMemo(() => getUrls(stableInput), [stableInput]);
|
|
1316
1318
|
const cachedResult = useMemo(() => {
|
|
1317
1319
|
if (!cache) return null;
|
|
1318
1320
|
const textures = store.getState().textures;
|
|
1319
1321
|
if (!allUrlsCached(urls, textures)) return null;
|
|
1320
|
-
return buildFromCache(
|
|
1321
|
-
}, [cache, urls,
|
|
1322
|
+
return buildFromCache(stableInput, textures);
|
|
1323
|
+
}, [cache, urls, stableInput, store]);
|
|
1322
1324
|
const loadedTextures = useLoader(
|
|
1323
1325
|
TextureLoader,
|
|
1324
|
-
IsObject(
|
|
1326
|
+
IsObject(stableInput) ? Object.values(stableInput) : stableInput
|
|
1325
1327
|
);
|
|
1326
|
-
const inputKey = urls.join("\0");
|
|
1327
1328
|
useLayoutEffect(() => {
|
|
1328
1329
|
if (cachedResult) return;
|
|
1329
1330
|
if (onLoadCalledForRef.current === inputKey) return;
|
|
@@ -1350,28 +1351,28 @@ function useTexture(input, optionsOrOnLoad) {
|
|
|
1350
1351
|
}, [renderer, loadedTextures, cachedResult]);
|
|
1351
1352
|
const mappedTextures = useMemo(() => {
|
|
1352
1353
|
if (cachedResult) return cachedResult;
|
|
1353
|
-
if (IsObject(
|
|
1354
|
+
if (IsObject(stableInput)) {
|
|
1354
1355
|
const keyed = {};
|
|
1355
1356
|
const textureArray = loadedTextures;
|
|
1356
1357
|
let i = 0;
|
|
1357
|
-
for (const key in
|
|
1358
|
+
for (const key in stableInput) keyed[key] = textureArray[i++];
|
|
1358
1359
|
return keyed;
|
|
1359
1360
|
} else {
|
|
1360
1361
|
return loadedTextures;
|
|
1361
1362
|
}
|
|
1362
|
-
}, [
|
|
1363
|
+
}, [stableInput, loadedTextures, cachedResult]);
|
|
1363
1364
|
useEffect(() => {
|
|
1364
1365
|
if (!cache) return;
|
|
1365
1366
|
const urlTextureMap = [];
|
|
1366
|
-
if (typeof
|
|
1367
|
-
urlTextureMap.push([
|
|
1368
|
-
} else if (Array.isArray(
|
|
1367
|
+
if (typeof stableInput === "string") {
|
|
1368
|
+
urlTextureMap.push([stableInput, mappedTextures]);
|
|
1369
|
+
} else if (Array.isArray(stableInput)) {
|
|
1369
1370
|
const textureArray = mappedTextures;
|
|
1370
|
-
|
|
1371
|
-
} else if (IsObject(
|
|
1371
|
+
stableInput.forEach((url, i) => urlTextureMap.push([url, textureArray[i]]));
|
|
1372
|
+
} else if (IsObject(stableInput)) {
|
|
1372
1373
|
const textureRecord = mappedTextures;
|
|
1373
|
-
for (const key in
|
|
1374
|
-
const url =
|
|
1374
|
+
for (const key in stableInput) {
|
|
1375
|
+
const url = stableInput[key];
|
|
1375
1376
|
urlTextureMap.push([url, textureRecord[key]]);
|
|
1376
1377
|
}
|
|
1377
1378
|
}
|
|
@@ -1400,7 +1401,7 @@ function useTexture(input, optionsOrOnLoad) {
|
|
|
1400
1401
|
}
|
|
1401
1402
|
return { _textureRefs: refs };
|
|
1402
1403
|
});
|
|
1403
|
-
}, [cache,
|
|
1404
|
+
}, [cache, stableInput, mappedTextures, store]);
|
|
1404
1405
|
return mappedTextures;
|
|
1405
1406
|
}
|
|
1406
1407
|
useTexture.preload = (url) => useLoader.preload(TextureLoader, url);
|
|
@@ -12958,7 +12959,10 @@ function releaseInternalPointerCapture(internal, obj, pointerId) {
|
|
|
12958
12959
|
const captureData = pointerState.captured.get(obj);
|
|
12959
12960
|
if (captureData) {
|
|
12960
12961
|
pointerState.captured.delete(obj);
|
|
12961
|
-
|
|
12962
|
+
try {
|
|
12963
|
+
captureData.target.releasePointerCapture?.(pointerId);
|
|
12964
|
+
} catch {
|
|
12965
|
+
}
|
|
12962
12966
|
}
|
|
12963
12967
|
}
|
|
12964
12968
|
function swapInteractivity(store, object, newObject) {
|
|
@@ -13052,7 +13056,9 @@ function createEvents(store) {
|
|
|
13052
13056
|
state2.events.compute?.(event, state2, state2.previousRoot?.getState());
|
|
13053
13057
|
if (state2.raycaster.camera === void 0) state2.raycaster.camera = null;
|
|
13054
13058
|
}
|
|
13055
|
-
|
|
13059
|
+
if (!state2.raycaster.camera) return [];
|
|
13060
|
+
obj.updateWorldMatrix(true, true);
|
|
13061
|
+
return state2.raycaster.intersectObject(obj, true);
|
|
13056
13062
|
}
|
|
13057
13063
|
let hits = eventsObjects.flatMap(handleRaycast).sort((a, b) => {
|
|
13058
13064
|
const aInteractivePriority = a.object.userData?.interactivePriority;
|
|
@@ -14380,6 +14386,10 @@ function createRoot(canvas) {
|
|
|
14380
14386
|
if (state2.internal.isMultiCanvas && state2.internal.canvasTarget) {
|
|
14381
14387
|
const renderer2 = state2.internal.actualRenderer;
|
|
14382
14388
|
renderer2.setCanvasTarget(state2.internal.canvasTarget);
|
|
14389
|
+
if (state2.internal.canvasTargetSizeDirty) {
|
|
14390
|
+
state2.internal.canvasTargetSizeDirty = false;
|
|
14391
|
+
renderer2.backend?.updateSize?.();
|
|
14392
|
+
}
|
|
14383
14393
|
}
|
|
14384
14394
|
},
|
|
14385
14395
|
{
|
|
@@ -15112,6 +15122,7 @@ function CanvasImpl({
|
|
|
15112
15122
|
const canvas = canvasRef.current;
|
|
15113
15123
|
if (canvas) {
|
|
15114
15124
|
return () => {
|
|
15125
|
+
if (canvas.isConnected) return;
|
|
15115
15126
|
unmountComponentAtNode(canvas);
|
|
15116
15127
|
root.current = null;
|
|
15117
15128
|
};
|