@react-three/fiber 10.0.0-canary.8f5b4d3 → 10.0.0-canary.979dc2d
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 +120 -62
- package/dist/index.d.cts +180 -26
- package/dist/index.d.mts +180 -26
- package/dist/index.d.ts +180 -26
- package/dist/index.mjs +120 -62
- package/dist/legacy.cjs +116 -62
- package/dist/legacy.d.cts +179 -29
- package/dist/legacy.d.mts +179 -29
- package/dist/legacy.d.ts +179 -29
- package/dist/legacy.mjs +116 -62
- package/dist/webgpu/index.cjs +183 -99
- package/dist/webgpu/index.d.cts +204 -90
- package/dist/webgpu/index.d.mts +204 -90
- package/dist/webgpu/index.d.ts +204 -90
- package/dist/webgpu/index.mjs +183 -99
- package/package.json +4 -4
- 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/webgpu/index.cjs
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const webgpu = require('three/webgpu');
|
|
4
|
-
const Inspector_js = require('three/addons/inspector/Inspector.js');
|
|
5
4
|
const jsxRuntime = require('react/jsx-runtime');
|
|
6
5
|
const React = require('react');
|
|
7
6
|
const useMeasure = require('react-use-measure');
|
|
@@ -54,6 +53,10 @@ const Tb__default = /*#__PURE__*/_interopDefaultCompat(Tb);
|
|
|
54
53
|
|
|
55
54
|
const R3F_BUILD_LEGACY = false;
|
|
56
55
|
const R3F_BUILD_WEBGPU = true;
|
|
56
|
+
async function loadInspector() {
|
|
57
|
+
const { Inspector } = await import('three/addons/inspector/Inspector.js');
|
|
58
|
+
return Inspector;
|
|
59
|
+
}
|
|
57
60
|
const WebGLRenderer = class WebGLRenderer2 {
|
|
58
61
|
constructor() {
|
|
59
62
|
throw new Error(
|
|
@@ -67,13 +70,13 @@ const WebGLCubeRenderTarget = null;
|
|
|
67
70
|
const THREE = /*#__PURE__*/_mergeNamespaces({
|
|
68
71
|
__proto__: null,
|
|
69
72
|
CubeRenderTargetCompat: webgpu.CubeRenderTarget,
|
|
70
|
-
Inspector: Inspector_js.Inspector,
|
|
71
73
|
R3F_BUILD_LEGACY: R3F_BUILD_LEGACY,
|
|
72
74
|
R3F_BUILD_WEBGPU: R3F_BUILD_WEBGPU,
|
|
73
75
|
RenderTargetCompat: webgpu.RenderTarget,
|
|
74
76
|
WebGLCubeRenderTarget: WebGLCubeRenderTarget,
|
|
75
77
|
WebGLRenderTarget: WebGLRenderTarget,
|
|
76
|
-
WebGLRenderer: WebGLRenderer
|
|
78
|
+
WebGLRenderer: WebGLRenderer,
|
|
79
|
+
loadInspector: loadInspector
|
|
77
80
|
}, [webgpu__namespace]);
|
|
78
81
|
|
|
79
82
|
const primaryRegistry = /* @__PURE__ */ new Map();
|
|
@@ -932,7 +935,7 @@ const createStore = (invalidate, advance) => {
|
|
|
932
935
|
size: newSize,
|
|
933
936
|
viewport: { ...s.viewport, ...getCurrentViewport(state2.camera, defaultTarget, newSize) }
|
|
934
937
|
}));
|
|
935
|
-
|
|
938
|
+
get().invalidate();
|
|
936
939
|
}
|
|
937
940
|
}
|
|
938
941
|
return;
|
|
@@ -947,15 +950,16 @@ const createStore = (invalidate, advance) => {
|
|
|
947
950
|
viewport: { ...s.viewport, ...getCurrentViewport(state2.camera, defaultTarget, size) },
|
|
948
951
|
_sizeImperative: true
|
|
949
952
|
}));
|
|
950
|
-
|
|
953
|
+
get().invalidate();
|
|
951
954
|
},
|
|
952
955
|
setDpr: (dpr) => set((state2) => {
|
|
953
956
|
const resolved = calculateDpr(dpr);
|
|
954
957
|
return { viewport: { ...state2.viewport, dpr: resolved, initialDpr: state2.viewport.initialDpr || resolved } };
|
|
955
958
|
}),
|
|
956
959
|
setFrameloop: (frameloop = "always") => {
|
|
960
|
+
const rootId = get().internal.rootId;
|
|
961
|
+
if (rootId) scheduler.getScheduler().setRootFrameloop(rootId, frameloop);
|
|
957
962
|
set(() => ({ frameloop }));
|
|
958
|
-
scheduler.getScheduler().frameloop = frameloop;
|
|
959
963
|
},
|
|
960
964
|
setError: (error) => set(() => ({ error })),
|
|
961
965
|
error: null,
|
|
@@ -1071,17 +1075,11 @@ const createStore = (invalidate, advance) => {
|
|
|
1071
1075
|
oldSize = size;
|
|
1072
1076
|
oldDpr = viewport.dpr;
|
|
1073
1077
|
updateCamera(camera, size);
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
actualRenderer.setSize(size.width, size.height, false);
|
|
1080
|
-
if (canvasTarget) {
|
|
1081
|
-
if (viewport.dpr > 0) canvasTarget.setPixelRatio(viewport.dpr);
|
|
1082
|
-
canvasTarget.setSize(size.width, size.height, false);
|
|
1083
|
-
}
|
|
1084
|
-
}
|
|
1078
|
+
const resizeTarget = canvasTarget ?? actualRenderer;
|
|
1079
|
+
if (viewport.dpr > 0) resizeTarget.setPixelRatio(viewport.dpr);
|
|
1080
|
+
resizeTarget.setSize(size.width, size.height, false);
|
|
1081
|
+
const activeTarget = actualRenderer.getCanvasTarget?.();
|
|
1082
|
+
if (!canvasTarget || activeTarget !== canvasTarget) internal.canvasTargetSizeDirty = true;
|
|
1085
1083
|
}
|
|
1086
1084
|
if (camera !== oldCamera) {
|
|
1087
1085
|
oldCamera = camera;
|
|
@@ -1143,7 +1141,11 @@ function useLoader(loader, input, extensions, onProgress, cacheKey) {
|
|
|
1143
1141
|
const results = cacheKeys.map(
|
|
1144
1142
|
(key, index) => suspendReact.suspend(() => fn(loader, inputs[index]), [loader, key], { equal: is.equ })
|
|
1145
1143
|
);
|
|
1146
|
-
|
|
1144
|
+
const stableRef = React.useRef(null);
|
|
1145
|
+
const previous = stableRef.current;
|
|
1146
|
+
const stable = previous !== null && previous.length === results.length && previous.every((value, i) => value === results[i]) ? previous : results;
|
|
1147
|
+
stableRef.current = stable;
|
|
1148
|
+
return Array.isArray(input) ? stable : stable[0];
|
|
1147
1149
|
}
|
|
1148
1150
|
useLoader.preload = function(loader, input, extensions, onProgress, cacheKey) {
|
|
1149
1151
|
const inputs = Array.isArray(input) ? input : [input];
|
|
@@ -1158,7 +1160,7 @@ useLoader.clear = function(loader, input, cacheKey) {
|
|
|
1158
1160
|
};
|
|
1159
1161
|
useLoader.loader = getLoader$1;
|
|
1160
1162
|
|
|
1161
|
-
function useFrame(callback, priorityOrOptions) {
|
|
1163
|
+
function useFrame$1(callback, priorityOrOptions) {
|
|
1162
1164
|
const store = React__namespace.useContext(context);
|
|
1163
1165
|
const isInsideCanvas = store !== null;
|
|
1164
1166
|
const scheduler$1 = scheduler.getScheduler();
|
|
@@ -1263,6 +1265,13 @@ function useFrame(callback, priorityOrOptions) {
|
|
|
1263
1265
|
* Use for controlling the entire frame loop, adding phases, etc.
|
|
1264
1266
|
*/
|
|
1265
1267
|
scheduler: scheduler2,
|
|
1268
|
+
/**
|
|
1269
|
+
* The root that currently owns this job. Resolve on access because ambient
|
|
1270
|
+
* jobs can be adopted by a Canvas after the controls object is created.
|
|
1271
|
+
*/
|
|
1272
|
+
get rootId() {
|
|
1273
|
+
return scheduler.getScheduler().getJobRootId(id);
|
|
1274
|
+
},
|
|
1266
1275
|
/**
|
|
1267
1276
|
* Manually step this job only.
|
|
1268
1277
|
* Bypasses FPS limiting - always runs.
|
|
@@ -1279,6 +1288,14 @@ function useFrame(callback, priorityOrOptions) {
|
|
|
1279
1288
|
stepAll: (timestamp) => {
|
|
1280
1289
|
scheduler.getScheduler().step(timestamp);
|
|
1281
1290
|
},
|
|
1291
|
+
/**
|
|
1292
|
+
* Request frames for this job's owning root without waking sibling roots.
|
|
1293
|
+
*/
|
|
1294
|
+
invalidate: (frames, stackFrames) => {
|
|
1295
|
+
const scheduler3 = scheduler.getScheduler();
|
|
1296
|
+
const rootId = scheduler3.getJobRootId(id);
|
|
1297
|
+
if (rootId) scheduler3.invalidateRoot(rootId, frames, stackFrames);
|
|
1298
|
+
},
|
|
1282
1299
|
/**
|
|
1283
1300
|
* Pause this job (set enabled=false).
|
|
1284
1301
|
* Job remains registered but won't run.
|
|
@@ -1308,6 +1325,11 @@ function getUrls(input) {
|
|
|
1308
1325
|
if (Array.isArray(input)) return input;
|
|
1309
1326
|
return Object.values(input);
|
|
1310
1327
|
}
|
|
1328
|
+
function inputSignature(input) {
|
|
1329
|
+
if (typeof input === "string") return input;
|
|
1330
|
+
if (Array.isArray(input)) return input.join("\0");
|
|
1331
|
+
return Object.keys(input).sort().map((key) => `${key}\0${input[key]}`).join("");
|
|
1332
|
+
}
|
|
1311
1333
|
function allUrlsCached(urls, textureCache) {
|
|
1312
1334
|
return urls.every((url) => textureCache.has(url));
|
|
1313
1335
|
}
|
|
@@ -1326,25 +1348,26 @@ function buildFromCache(input, textureCache) {
|
|
|
1326
1348
|
}
|
|
1327
1349
|
}
|
|
1328
1350
|
function useTexture(input, optionsOrOnLoad) {
|
|
1329
|
-
const renderer = useThree((state) => state.internal.actualRenderer);
|
|
1351
|
+
const renderer = useThree$1((state) => state.internal.actualRenderer);
|
|
1330
1352
|
const store = useStore();
|
|
1331
1353
|
const options = typeof optionsOrOnLoad === "function" ? { onLoad: optionsOrOnLoad } : optionsOrOnLoad ?? {};
|
|
1332
1354
|
const { onLoad, cache = true } = options;
|
|
1333
1355
|
const onLoadRef = React.useRef(onLoad);
|
|
1334
1356
|
onLoadRef.current = onLoad;
|
|
1335
1357
|
const onLoadCalledForRef = React.useRef(null);
|
|
1336
|
-
const
|
|
1358
|
+
const inputKey = React.useMemo(() => inputSignature(input), [input]);
|
|
1359
|
+
const stableInput = React.useMemo(() => input, [inputKey]);
|
|
1360
|
+
const urls = React.useMemo(() => getUrls(stableInput), [stableInput]);
|
|
1337
1361
|
const cachedResult = React.useMemo(() => {
|
|
1338
1362
|
if (!cache) return null;
|
|
1339
1363
|
const textures = store.getState().textures;
|
|
1340
1364
|
if (!allUrlsCached(urls, textures)) return null;
|
|
1341
|
-
return buildFromCache(
|
|
1342
|
-
}, [cache, urls,
|
|
1365
|
+
return buildFromCache(stableInput, textures);
|
|
1366
|
+
}, [cache, urls, stableInput, store]);
|
|
1343
1367
|
const loadedTextures = useLoader(
|
|
1344
1368
|
webgpu.TextureLoader,
|
|
1345
|
-
IsObject(
|
|
1369
|
+
IsObject(stableInput) ? Object.values(stableInput) : stableInput
|
|
1346
1370
|
);
|
|
1347
|
-
const inputKey = urls.join("\0");
|
|
1348
1371
|
React.useLayoutEffect(() => {
|
|
1349
1372
|
if (cachedResult) return;
|
|
1350
1373
|
if (onLoadCalledForRef.current === inputKey) return;
|
|
@@ -1371,28 +1394,28 @@ function useTexture(input, optionsOrOnLoad) {
|
|
|
1371
1394
|
}, [renderer, loadedTextures, cachedResult]);
|
|
1372
1395
|
const mappedTextures = React.useMemo(() => {
|
|
1373
1396
|
if (cachedResult) return cachedResult;
|
|
1374
|
-
if (IsObject(
|
|
1397
|
+
if (IsObject(stableInput)) {
|
|
1375
1398
|
const keyed = {};
|
|
1376
1399
|
const textureArray = loadedTextures;
|
|
1377
1400
|
let i = 0;
|
|
1378
|
-
for (const key in
|
|
1401
|
+
for (const key in stableInput) keyed[key] = textureArray[i++];
|
|
1379
1402
|
return keyed;
|
|
1380
1403
|
} else {
|
|
1381
1404
|
return loadedTextures;
|
|
1382
1405
|
}
|
|
1383
|
-
}, [
|
|
1406
|
+
}, [stableInput, loadedTextures, cachedResult]);
|
|
1384
1407
|
React.useEffect(() => {
|
|
1385
1408
|
if (!cache) return;
|
|
1386
1409
|
const urlTextureMap = [];
|
|
1387
|
-
if (typeof
|
|
1388
|
-
urlTextureMap.push([
|
|
1389
|
-
} else if (Array.isArray(
|
|
1410
|
+
if (typeof stableInput === "string") {
|
|
1411
|
+
urlTextureMap.push([stableInput, mappedTextures]);
|
|
1412
|
+
} else if (Array.isArray(stableInput)) {
|
|
1390
1413
|
const textureArray = mappedTextures;
|
|
1391
|
-
|
|
1392
|
-
} else if (IsObject(
|
|
1414
|
+
stableInput.forEach((url, i) => urlTextureMap.push([url, textureArray[i]]));
|
|
1415
|
+
} else if (IsObject(stableInput)) {
|
|
1393
1416
|
const textureRecord = mappedTextures;
|
|
1394
|
-
for (const key in
|
|
1395
|
-
const url =
|
|
1417
|
+
for (const key in stableInput) {
|
|
1418
|
+
const url = stableInput[key];
|
|
1396
1419
|
urlTextureMap.push([url, textureRecord[key]]);
|
|
1397
1420
|
}
|
|
1398
1421
|
}
|
|
@@ -1421,7 +1444,7 @@ function useTexture(input, optionsOrOnLoad) {
|
|
|
1421
1444
|
}
|
|
1422
1445
|
return { _textureRefs: refs };
|
|
1423
1446
|
});
|
|
1424
|
-
}, [cache,
|
|
1447
|
+
}, [cache, stableInput, mappedTextures, store]);
|
|
1425
1448
|
return mappedTextures;
|
|
1426
1449
|
}
|
|
1427
1450
|
useTexture.preload = (url) => useLoader.preload(webgpu.TextureLoader, url);
|
|
@@ -1492,13 +1515,13 @@ function useTextures(selector) {
|
|
|
1492
1515
|
};
|
|
1493
1516
|
}, [store]);
|
|
1494
1517
|
const subscribe = selector ? () => selector(registry) : (state) => state.textures;
|
|
1495
|
-
const selected = useThree(subscribe);
|
|
1518
|
+
const selected = useThree$1(subscribe);
|
|
1496
1519
|
return selector ? selected : registry;
|
|
1497
1520
|
}
|
|
1498
1521
|
|
|
1499
1522
|
function useRenderTarget(widthOrOptions, heightOrOptions, options) {
|
|
1500
|
-
const isLegacy = useThree((s) => s.isLegacy);
|
|
1501
|
-
const size = useThree((s) => s.size);
|
|
1523
|
+
const isLegacy = useThree$1((s) => s.isLegacy);
|
|
1524
|
+
const size = useThree$1((s) => s.size);
|
|
1502
1525
|
let width;
|
|
1503
1526
|
let height;
|
|
1504
1527
|
let opts;
|
|
@@ -1555,7 +1578,7 @@ function useEnvironment({
|
|
|
1555
1578
|
const { extension, isCubemap } = getExtension(files);
|
|
1556
1579
|
const loader = getLoader(extension);
|
|
1557
1580
|
if (!loader) throw new Error("useEnvironment: Unrecognized file extension: " + files);
|
|
1558
|
-
const renderer = useThree((state) => state.renderer);
|
|
1581
|
+
const renderer = useThree$1((state) => state.renderer);
|
|
1559
1582
|
React.useLayoutEffect(() => {
|
|
1560
1583
|
if (extension !== "webp" && extension !== "jpg" && extension !== "jpeg") return;
|
|
1561
1584
|
function clearGainmapTexture() {
|
|
@@ -1648,7 +1671,7 @@ function useStore() {
|
|
|
1648
1671
|
if (!store) throw new Error("R3F: Hooks can only be used within the Canvas component!");
|
|
1649
1672
|
return store;
|
|
1650
1673
|
}
|
|
1651
|
-
function useThree(selector = (state) => state, equalityFn) {
|
|
1674
|
+
function useThree$1(selector = (state) => state, equalityFn) {
|
|
1652
1675
|
return useStore()(selector, equalityFn);
|
|
1653
1676
|
}
|
|
1654
1677
|
function useInstanceHandle(ref) {
|
|
@@ -1690,13 +1713,19 @@ function addTail(callback) {
|
|
|
1690
1713
|
return scheduler.getScheduler().onIdle(callback);
|
|
1691
1714
|
}
|
|
1692
1715
|
function invalidate(state, frames = 1, stackFrames = false) {
|
|
1693
|
-
|
|
1716
|
+
const rootId = state?.internal?.rootId;
|
|
1717
|
+
const scheduler$1 = scheduler.getScheduler();
|
|
1718
|
+
if (rootId) scheduler$1.invalidateRoot(rootId, frames, stackFrames);
|
|
1719
|
+
else scheduler$1.invalidate(frames, stackFrames);
|
|
1694
1720
|
}
|
|
1695
|
-
function advance(timestamp) {
|
|
1696
|
-
|
|
1721
|
+
function advance(timestamp, runGlobalEffects, state) {
|
|
1722
|
+
const rootId = state?.internal?.rootId;
|
|
1723
|
+
const scheduler$1 = scheduler.getScheduler();
|
|
1724
|
+
if (rootId) scheduler$1.stepRoot(rootId, timestamp);
|
|
1725
|
+
else scheduler$1.step(timestamp);
|
|
1697
1726
|
}
|
|
1698
1727
|
|
|
1699
|
-
const version = "10.0.0-alpha.
|
|
1728
|
+
const version = "10.0.0-alpha.4";
|
|
1700
1729
|
const packageData = {
|
|
1701
1730
|
version: version};
|
|
1702
1731
|
|
|
@@ -12979,7 +13008,10 @@ function releaseInternalPointerCapture(internal, obj, pointerId) {
|
|
|
12979
13008
|
const captureData = pointerState.captured.get(obj);
|
|
12980
13009
|
if (captureData) {
|
|
12981
13010
|
pointerState.captured.delete(obj);
|
|
12982
|
-
|
|
13011
|
+
try {
|
|
13012
|
+
captureData.target.releasePointerCapture?.(pointerId);
|
|
13013
|
+
} catch {
|
|
13014
|
+
}
|
|
12983
13015
|
}
|
|
12984
13016
|
}
|
|
12985
13017
|
function swapInteractivity(store, object, newObject) {
|
|
@@ -13073,7 +13105,9 @@ function createEvents(store) {
|
|
|
13073
13105
|
state2.events.compute?.(event, state2, state2.previousRoot?.getState());
|
|
13074
13106
|
if (state2.raycaster.camera === void 0) state2.raycaster.camera = null;
|
|
13075
13107
|
}
|
|
13076
|
-
|
|
13108
|
+
if (!state2.raycaster.camera) return [];
|
|
13109
|
+
obj.updateWorldMatrix(true, true);
|
|
13110
|
+
return state2.raycaster.intersectObject(obj, true);
|
|
13077
13111
|
}
|
|
13078
13112
|
let hits = eventsObjects.flatMap(handleRaycast).sort((a, b) => {
|
|
13079
13113
|
const aInteractivePriority = a.object.userData?.interactivePriority;
|
|
@@ -14207,9 +14241,8 @@ function createRoot(canvas) {
|
|
|
14207
14241
|
if (!renderer.hasInitialized?.()) {
|
|
14208
14242
|
const size2 = computeInitialSize(canvas, propsSize);
|
|
14209
14243
|
if (size2.width > 0 && size2.height > 0) {
|
|
14210
|
-
|
|
14211
|
-
|
|
14212
|
-
canvas.height = size2.height * pixelRatio;
|
|
14244
|
+
renderer.setPixelRatio(calculateDpr(dpr));
|
|
14245
|
+
renderer.setSize(size2.width, size2.height, false);
|
|
14213
14246
|
}
|
|
14214
14247
|
await renderer.init();
|
|
14215
14248
|
}
|
|
@@ -14218,7 +14251,7 @@ function createRoot(canvas) {
|
|
|
14218
14251
|
state.internal.actualRenderer = renderer;
|
|
14219
14252
|
state.set({ webGPUSupported: isWebGPUBackend, renderer, primaryStore: store });
|
|
14220
14253
|
if (canvasId && !state.internal.isSecondary) {
|
|
14221
|
-
const canvasTarget =
|
|
14254
|
+
const canvasTarget = renderer.getCanvasTarget?.();
|
|
14222
14255
|
const unregisterPrimary = registerPrimary(canvasId, renderer, store);
|
|
14223
14256
|
state.set((prev) => ({
|
|
14224
14257
|
internal: {
|
|
@@ -14332,7 +14365,7 @@ function createRoot(canvas) {
|
|
|
14332
14365
|
const handleXRFrame = (timestamp, _frame) => {
|
|
14333
14366
|
const state2 = store.getState();
|
|
14334
14367
|
if (state2.frameloop === "never") return;
|
|
14335
|
-
advance(timestamp);
|
|
14368
|
+
advance(timestamp, true, state2);
|
|
14336
14369
|
};
|
|
14337
14370
|
const actualRenderer = state.internal.actualRenderer;
|
|
14338
14371
|
const handleSessionChange = () => {
|
|
@@ -14340,7 +14373,7 @@ function createRoot(canvas) {
|
|
|
14340
14373
|
const renderer2 = state2.internal.actualRenderer;
|
|
14341
14374
|
actualRenderer.xr.enabled = actualRenderer.xr.isPresenting;
|
|
14342
14375
|
renderer2.xr.setAnimationLoop(renderer2.xr.isPresenting ? handleXRFrame : null);
|
|
14343
|
-
if (!renderer2.xr.isPresenting) invalidate();
|
|
14376
|
+
if (!renderer2.xr.isPresenting) invalidate(state2);
|
|
14344
14377
|
};
|
|
14345
14378
|
const xr = {
|
|
14346
14379
|
connect() {
|
|
@@ -14422,14 +14455,23 @@ function createRoot(canvas) {
|
|
|
14422
14455
|
const newRootId = canvasId || scheduler$1.generateRootId();
|
|
14423
14456
|
const unregisterRoot = scheduler$1.registerRoot(newRootId, {
|
|
14424
14457
|
getState: () => store.getState(),
|
|
14425
|
-
onError: (err) => store.getState().setError(err)
|
|
14458
|
+
onError: (err) => store.getState().setError(err),
|
|
14459
|
+
frameloop: store.getState().frameloop,
|
|
14460
|
+
before: schedulerConfig?.before,
|
|
14461
|
+
after: schedulerConfig?.after,
|
|
14462
|
+
order: schedulerConfig?.order
|
|
14426
14463
|
});
|
|
14427
14464
|
const unregisterCanvasTarget = scheduler$1.register(
|
|
14428
14465
|
() => {
|
|
14429
14466
|
const state2 = store.getState();
|
|
14430
|
-
|
|
14467
|
+
const canvasTarget = state2.internal.canvasTarget;
|
|
14468
|
+
if (canvasTarget) {
|
|
14431
14469
|
const renderer2 = state2.internal.actualRenderer;
|
|
14432
|
-
renderer2.setCanvasTarget(
|
|
14470
|
+
if (renderer2.getCanvasTarget() !== canvasTarget) renderer2.setCanvasTarget(canvasTarget);
|
|
14471
|
+
if (state2.internal.canvasTargetSizeDirty) {
|
|
14472
|
+
state2.internal.canvasTargetSizeDirty = false;
|
|
14473
|
+
renderer2.backend?.updateSize?.();
|
|
14474
|
+
}
|
|
14433
14475
|
}
|
|
14434
14476
|
},
|
|
14435
14477
|
{
|
|
@@ -14498,8 +14540,7 @@ function createRoot(canvas) {
|
|
|
14498
14540
|
phase: "render",
|
|
14499
14541
|
system: true,
|
|
14500
14542
|
// Internal flag: this is a system job, not user-controlled
|
|
14501
|
-
//
|
|
14502
|
-
...schedulerConfig?.after && { after: schedulerConfig.after },
|
|
14543
|
+
// FPS throttles only the default render job; Canvas ordering belongs to the root.
|
|
14503
14544
|
...schedulerConfig?.fps && { fps: schedulerConfig.fps }
|
|
14504
14545
|
}
|
|
14505
14546
|
);
|
|
@@ -14518,8 +14559,21 @@ function createRoot(canvas) {
|
|
|
14518
14559
|
scheduler: scheduler$1
|
|
14519
14560
|
}
|
|
14520
14561
|
}));
|
|
14562
|
+
} else {
|
|
14563
|
+
const constraintsChanged = !is.equ(schedulerConfig?.before, lastConfiguredProps.schedulerBefore, shallowLoose) || !is.equ(schedulerConfig?.after, lastConfiguredProps.schedulerAfter, shallowLoose);
|
|
14564
|
+
if (constraintsChanged) {
|
|
14565
|
+
scheduler$1.setRootConstraints(rootId, {
|
|
14566
|
+
before: schedulerConfig?.before,
|
|
14567
|
+
after: schedulerConfig?.after
|
|
14568
|
+
});
|
|
14569
|
+
}
|
|
14570
|
+
if (schedulerConfig?.order !== lastConfiguredProps.schedulerOrder) {
|
|
14571
|
+
scheduler$1.setRootOrder(rootId, schedulerConfig?.order ?? 0);
|
|
14572
|
+
}
|
|
14521
14573
|
}
|
|
14522
|
-
|
|
14574
|
+
lastConfiguredProps.schedulerBefore = schedulerConfig?.before;
|
|
14575
|
+
lastConfiguredProps.schedulerAfter = schedulerConfig?.after;
|
|
14576
|
+
lastConfiguredProps.schedulerOrder = schedulerConfig?.order;
|
|
14523
14577
|
onCreated = onCreatedCallback;
|
|
14524
14578
|
configured = true;
|
|
14525
14579
|
resolve();
|
|
@@ -14561,18 +14615,23 @@ function unmountComponentAtNode(canvas, callback) {
|
|
|
14561
14615
|
const fiber = root?.fiber;
|
|
14562
14616
|
if (fiber) {
|
|
14563
14617
|
const state = root?.store.getState();
|
|
14564
|
-
if (state)
|
|
14618
|
+
if (state) {
|
|
14619
|
+
state.internal.active = false;
|
|
14620
|
+
const unregisterRoot = state.internal.unregisterRoot;
|
|
14621
|
+
if (unregisterRoot) {
|
|
14622
|
+
unregisterRoot();
|
|
14623
|
+
state.internal.unregisterRoot = void 0;
|
|
14624
|
+
}
|
|
14625
|
+
}
|
|
14565
14626
|
reconciler.updateContainer(null, fiber, null, () => {
|
|
14566
14627
|
if (state) {
|
|
14567
14628
|
setTimeout(() => {
|
|
14568
14629
|
try {
|
|
14569
14630
|
const renderer = state.internal.actualRenderer;
|
|
14570
|
-
const unregisterRoot = state.internal.unregisterRoot;
|
|
14571
|
-
if (unregisterRoot) unregisterRoot();
|
|
14572
14631
|
const unregisterPrimary = state.internal.unregisterPrimary;
|
|
14573
14632
|
if (unregisterPrimary) unregisterPrimary();
|
|
14574
14633
|
const canvasTarget = state.internal.canvasTarget;
|
|
14575
|
-
if (canvasTarget?.dispose) canvasTarget.dispose();
|
|
14634
|
+
if (state.internal.isSecondary && canvasTarget?.dispose) canvasTarget.dispose();
|
|
14576
14635
|
state.events.disconnect?.();
|
|
14577
14636
|
cleanupHelperGroup(root.store);
|
|
14578
14637
|
if (state.isLegacy && renderer) {
|
|
@@ -14734,7 +14793,7 @@ function setEnvProps(background, scene, defaultScene, texture, sceneProps = {})
|
|
|
14734
14793
|
};
|
|
14735
14794
|
}
|
|
14736
14795
|
function EnvironmentMap({ scene, background = false, map, ...config }) {
|
|
14737
|
-
const defaultScene = useThree((state) => state.scene);
|
|
14796
|
+
const defaultScene = useThree$1((state) => state.scene);
|
|
14738
14797
|
React__namespace.useLayoutEffect(() => {
|
|
14739
14798
|
if (map) return setEnvProps(background, scene, defaultScene, map, config);
|
|
14740
14799
|
});
|
|
@@ -14752,7 +14811,7 @@ function EnvironmentCube({
|
|
|
14752
14811
|
...rest
|
|
14753
14812
|
}) {
|
|
14754
14813
|
const texture = useEnvironment(rest);
|
|
14755
|
-
const defaultScene = useThree((state) => state.scene);
|
|
14814
|
+
const defaultScene = useThree$1((state) => state.scene);
|
|
14756
14815
|
React__namespace.useLayoutEffect(() => {
|
|
14757
14816
|
return setEnvProps(background, scene, defaultScene, texture, {
|
|
14758
14817
|
backgroundBlurriness: blur ?? backgroundBlurriness,
|
|
@@ -14789,9 +14848,9 @@ function EnvironmentPortal({
|
|
|
14789
14848
|
preset = void 0,
|
|
14790
14849
|
extensions
|
|
14791
14850
|
}) {
|
|
14792
|
-
const renderer = useThree((state) => state.renderer);
|
|
14793
|
-
const isLegacy = useThree((state) => state.isLegacy);
|
|
14794
|
-
const defaultScene = useThree((state) => state.scene);
|
|
14851
|
+
const renderer = useThree$1((state) => state.renderer);
|
|
14852
|
+
const isLegacy = useThree$1((state) => state.isLegacy);
|
|
14853
|
+
const defaultScene = useThree$1((state) => state.scene);
|
|
14795
14854
|
const camera = React__namespace.useRef(null);
|
|
14796
14855
|
const [virtualScene] = React__namespace.useState(() => new webgpu.Scene());
|
|
14797
14856
|
const fbo = React__namespace.useMemo(() => {
|
|
@@ -14835,7 +14894,7 @@ function EnvironmentPortal({
|
|
|
14835
14894
|
environmentRotation
|
|
14836
14895
|
]);
|
|
14837
14896
|
let count = 1;
|
|
14838
|
-
useFrame(() => {
|
|
14897
|
+
useFrame$1(() => {
|
|
14839
14898
|
if (frames === Infinity || count < frames) {
|
|
14840
14899
|
const autoClear = renderer.autoClear;
|
|
14841
14900
|
renderer.autoClear = true;
|
|
@@ -14875,7 +14934,7 @@ function EnvironmentGround(props) {
|
|
|
14875
14934
|
] });
|
|
14876
14935
|
}
|
|
14877
14936
|
function EnvironmentColor({ color, scene }) {
|
|
14878
|
-
const defaultScene = useThree((state) => state.scene);
|
|
14937
|
+
const defaultScene = useThree$1((state) => state.scene);
|
|
14879
14938
|
React__namespace.useLayoutEffect(() => {
|
|
14880
14939
|
if (color === void 0) return;
|
|
14881
14940
|
const target = resolveScene(scene || defaultScene);
|
|
@@ -15113,9 +15172,9 @@ function CanvasImpl({
|
|
|
15113
15172
|
React__namespace.useMemo(() => extend(THREE), []);
|
|
15114
15173
|
const Bridge = useBridge();
|
|
15115
15174
|
const backgroundProps = React__namespace.useMemo(() => parseBackground(background), [background]);
|
|
15116
|
-
const
|
|
15175
|
+
const [hasInitialSize, setHasInitialSize] = React__namespace.useState(false);
|
|
15117
15176
|
const measureConfig = React__namespace.useMemo(() => {
|
|
15118
|
-
if (!
|
|
15177
|
+
if (!hasInitialSize) {
|
|
15119
15178
|
return {
|
|
15120
15179
|
...resize,
|
|
15121
15180
|
scroll: resize?.scroll ?? true,
|
|
@@ -15127,7 +15186,7 @@ function CanvasImpl({
|
|
|
15127
15186
|
debounce: { scroll: 50, resize: 0 },
|
|
15128
15187
|
...resize
|
|
15129
15188
|
};
|
|
15130
|
-
}, [
|
|
15189
|
+
}, [hasInitialSize, resize]);
|
|
15131
15190
|
const [containerRef, containerRect] = useMeasure__default(measureConfig);
|
|
15132
15191
|
const effectiveSize = React__namespace.useMemo(() => {
|
|
15133
15192
|
let w = width ?? containerRect.width;
|
|
@@ -15143,9 +15202,7 @@ function CanvasImpl({
|
|
|
15143
15202
|
left: containerRect.left
|
|
15144
15203
|
};
|
|
15145
15204
|
}, [width, height, containerRect, forceEven]);
|
|
15146
|
-
if (!
|
|
15147
|
-
hasInitialSizeRef.current = true;
|
|
15148
|
-
}
|
|
15205
|
+
if (!hasInitialSize && effectiveSize.width > 0 && effectiveSize.height > 0) setHasInitialSize(true);
|
|
15149
15206
|
const canvasRef = React__namespace.useRef(null);
|
|
15150
15207
|
const divRef = React__namespace.useRef(null);
|
|
15151
15208
|
React__namespace.useImperativeHandle(ref, () => canvasRef.current);
|
|
@@ -15259,6 +15316,7 @@ function CanvasImpl({
|
|
|
15259
15316
|
const canvas = canvasRef.current;
|
|
15260
15317
|
if (canvas) {
|
|
15261
15318
|
return () => {
|
|
15319
|
+
if (canvas.isConnected) return;
|
|
15262
15320
|
unmountComponentAtNode(canvas);
|
|
15263
15321
|
root.current = null;
|
|
15264
15322
|
};
|
|
@@ -15469,6 +15527,11 @@ function createTextureOperations(set) {
|
|
|
15469
15527
|
removeMultiple: (keys) => removeTextures(set, keys)
|
|
15470
15528
|
};
|
|
15471
15529
|
}
|
|
15530
|
+
function scopedNodeName(scope, name) {
|
|
15531
|
+
const raw = scope ? `${scope}_${name}` : name;
|
|
15532
|
+
const safe = raw.replace(/[^A-Za-z0-9_]/g, "_");
|
|
15533
|
+
return /^[A-Za-z_]/.test(safe) ? safe : `_${safe}`;
|
|
15534
|
+
}
|
|
15472
15535
|
function extractTSLValue(value) {
|
|
15473
15536
|
if (value === null || value === void 0) return value;
|
|
15474
15537
|
if (typeof value !== "object") return value;
|
|
@@ -15667,8 +15730,7 @@ function createUniform(inName, node, scope) {
|
|
|
15667
15730
|
const inValue = vectorize(node);
|
|
15668
15731
|
const newUniform = tsl.uniform(inValue);
|
|
15669
15732
|
if (typeof newUniform.setName === "function") {
|
|
15670
|
-
|
|
15671
|
-
newUniform.setName(name);
|
|
15733
|
+
newUniform.setName(scopedNodeName(scope, inName));
|
|
15672
15734
|
}
|
|
15673
15735
|
return newUniform;
|
|
15674
15736
|
}
|
|
@@ -15767,7 +15829,7 @@ function useNodes(creatorOrScope, scope) {
|
|
|
15767
15829
|
return creatorOrScope(createLazyCreatorState(store.getState(), store));
|
|
15768
15830
|
},
|
|
15769
15831
|
prepare: (name, node) => {
|
|
15770
|
-
node.setName?.(scope
|
|
15832
|
+
node.setName?.(scopedNodeName(scope, name));
|
|
15771
15833
|
return node;
|
|
15772
15834
|
}
|
|
15773
15835
|
});
|
|
@@ -15876,7 +15938,7 @@ function useBuffers(creatorOrScope, scope) {
|
|
|
15876
15938
|
},
|
|
15877
15939
|
prepare: (name, buffer) => {
|
|
15878
15940
|
if ("setName" in buffer && typeof buffer.setName === "function") {
|
|
15879
|
-
buffer.setName(scope
|
|
15941
|
+
buffer.setName(scopedNodeName(scope, name));
|
|
15880
15942
|
}
|
|
15881
15943
|
return buffer;
|
|
15882
15944
|
}
|
|
@@ -15947,7 +16009,7 @@ function useGPUStorage(creatorOrScope, scope) {
|
|
|
15947
16009
|
return creatorOrScope(createLazyCreatorState(store.getState(), store));
|
|
15948
16010
|
},
|
|
15949
16011
|
prepare: (name, storage) => {
|
|
15950
|
-
const label = scope
|
|
16012
|
+
const label = scopedNodeName(scope, name);
|
|
15951
16013
|
if ("setName" in storage && typeof storage.setName === "function") {
|
|
15952
16014
|
storage.setName(label);
|
|
15953
16015
|
}
|
|
@@ -15978,9 +16040,10 @@ function rebuildAllStorage(store, scope) {
|
|
|
15978
16040
|
|
|
15979
16041
|
function useRenderPipeline(mainCB, setupCB) {
|
|
15980
16042
|
const store = useStore();
|
|
15981
|
-
const { scene, camera, renderer, isLegacy } = useThree();
|
|
16043
|
+
const { scene, camera, renderer, isLegacy } = useThree$1();
|
|
15982
16044
|
const callbacksRanRef = React.useRef(false);
|
|
15983
16045
|
const scenePassCacheRef = React.useRef(null);
|
|
16046
|
+
const forceScenePassRebuildRef = React.useRef(false);
|
|
15984
16047
|
const mainCBRef = React.useRef(mainCB);
|
|
15985
16048
|
const setupCBRef = React.useRef(setupCB);
|
|
15986
16049
|
mainCBRef.current = mainCB;
|
|
@@ -15988,7 +16051,7 @@ function useRenderPipeline(mainCB, setupCB) {
|
|
|
15988
16051
|
const [rebuildVersion, setRebuildVersion] = React.useState(0);
|
|
15989
16052
|
React.useEffect(() => {
|
|
15990
16053
|
callbacksRanRef.current = false;
|
|
15991
|
-
|
|
16054
|
+
forceScenePassRebuildRef.current = true;
|
|
15992
16055
|
}, []);
|
|
15993
16056
|
const clearPasses = React.useCallback(() => {
|
|
15994
16057
|
store.setState({ passes: {} });
|
|
@@ -15998,12 +16061,14 @@ function useRenderPipeline(mainCB, setupCB) {
|
|
|
15998
16061
|
renderPipeline: null,
|
|
15999
16062
|
passes: {}
|
|
16000
16063
|
});
|
|
16064
|
+
scenePassCacheRef.current?.scenePass.dispose();
|
|
16001
16065
|
callbacksRanRef.current = false;
|
|
16002
16066
|
scenePassCacheRef.current = null;
|
|
16067
|
+
forceScenePassRebuildRef.current = false;
|
|
16003
16068
|
}, [store]);
|
|
16004
16069
|
const rebuild = React.useCallback(() => {
|
|
16005
16070
|
callbacksRanRef.current = false;
|
|
16006
|
-
|
|
16071
|
+
forceScenePassRebuildRef.current = true;
|
|
16007
16072
|
setRebuildVersion((v) => v + 1);
|
|
16008
16073
|
}, []);
|
|
16009
16074
|
React.useLayoutEffect(() => {
|
|
@@ -16011,6 +16076,9 @@ function useRenderPipeline(mainCB, setupCB) {
|
|
|
16011
16076
|
throw new Error("useRenderPipeline is only available with WebGPU renderer. Set renderer prop on Canvas.");
|
|
16012
16077
|
}
|
|
16013
16078
|
if (!renderer || !scene || !camera) return;
|
|
16079
|
+
if (!("isWebGPURenderer" in renderer)) {
|
|
16080
|
+
throw new Error("useRenderPipeline: renderer is not a WebGPURenderer but isLegacy is false.");
|
|
16081
|
+
}
|
|
16014
16082
|
const state = store.getState();
|
|
16015
16083
|
const set = store.setState;
|
|
16016
16084
|
try {
|
|
@@ -16021,21 +16089,33 @@ function useRenderPipeline(mainCB, setupCB) {
|
|
|
16021
16089
|
pipeline = new webgpu.RenderPipeline(renderer);
|
|
16022
16090
|
justCreatedPipeline = true;
|
|
16023
16091
|
}
|
|
16024
|
-
const cacheValid = scenePassCacheRef.current && scenePassCacheRef.current.sceneUuid === scene.uuid && scenePassCacheRef.current.cameraUuid === camera.uuid;
|
|
16092
|
+
const cacheValid = !forceScenePassRebuildRef.current && scenePassCacheRef.current && scenePassCacheRef.current.sceneUuid === scene.uuid && scenePassCacheRef.current.cameraUuid === camera.uuid;
|
|
16093
|
+
let outgoingScenePass = null;
|
|
16025
16094
|
let scenePass;
|
|
16026
16095
|
if (cacheValid) {
|
|
16027
16096
|
scenePass = scenePassCacheRef.current.scenePass;
|
|
16028
16097
|
} else {
|
|
16098
|
+
outgoingScenePass = scenePassCacheRef.current?.scenePass ?? null;
|
|
16029
16099
|
scenePass = tsl.pass(scene, camera);
|
|
16030
16100
|
scenePassCacheRef.current = { sceneUuid: scene.uuid, cameraUuid: camera.uuid, scenePass };
|
|
16101
|
+
forceScenePassRebuildRef.current = false;
|
|
16031
16102
|
}
|
|
16032
16103
|
currentPasses.scenePass = scenePass;
|
|
16033
|
-
|
|
16104
|
+
let outputNodeChanged = false;
|
|
16105
|
+
if (!pipeline.outputNode || justCreatedPipeline || pipeline.outputNode === outgoingScenePass) {
|
|
16106
|
+
pipeline.outputNode = scenePass;
|
|
16107
|
+
outputNodeChanged = true;
|
|
16108
|
+
}
|
|
16034
16109
|
set({ renderPipeline: pipeline, passes: currentPasses });
|
|
16035
16110
|
const shouldRunCallbacks = justCreatedPipeline || !callbacksRanRef.current || !cacheValid;
|
|
16036
16111
|
if (shouldRunCallbacks) {
|
|
16037
16112
|
if (setupCBRef.current) {
|
|
16038
|
-
const freshState = store.getState()
|
|
16113
|
+
const freshState = Object.assign({}, store.getState(), {
|
|
16114
|
+
renderPipeline: pipeline,
|
|
16115
|
+
passes: { ...currentPasses, scenePass },
|
|
16116
|
+
renderer,
|
|
16117
|
+
isLegacy: false
|
|
16118
|
+
});
|
|
16039
16119
|
const setupResult = setupCBRef.current(freshState);
|
|
16040
16120
|
if (setupResult && typeof setupResult === "object") {
|
|
16041
16121
|
currentPasses = { ...currentPasses, ...setupResult };
|
|
@@ -16043,33 +16123,37 @@ function useRenderPipeline(mainCB, setupCB) {
|
|
|
16043
16123
|
}
|
|
16044
16124
|
}
|
|
16045
16125
|
if (mainCBRef.current) {
|
|
16046
|
-
const freshState = store.getState()
|
|
16126
|
+
const freshState = Object.assign({}, store.getState(), {
|
|
16127
|
+
renderPipeline: pipeline,
|
|
16128
|
+
passes: { ...currentPasses, scenePass },
|
|
16129
|
+
renderer,
|
|
16130
|
+
isLegacy: false
|
|
16131
|
+
});
|
|
16047
16132
|
const mainResult = mainCBRef.current(freshState);
|
|
16048
16133
|
if (mainResult && typeof mainResult === "object") {
|
|
16049
16134
|
currentPasses = { ...currentPasses, ...mainResult };
|
|
16050
16135
|
set({ passes: currentPasses });
|
|
16051
16136
|
}
|
|
16052
16137
|
}
|
|
16138
|
+
outputNodeChanged = true;
|
|
16053
16139
|
callbacksRanRef.current = true;
|
|
16054
16140
|
}
|
|
16141
|
+
if (outputNodeChanged) pipeline.needsUpdate = true;
|
|
16142
|
+
if (outgoingScenePass && outgoingScenePass !== scenePass) outgoingScenePass.dispose();
|
|
16055
16143
|
} catch (error) {
|
|
16056
16144
|
console.warn("[useRenderPipeline] Setup failed; the render pipeline was not configured:", error);
|
|
16057
16145
|
}
|
|
16058
16146
|
}, [store, renderer, scene, camera, isLegacy, rebuildVersion]);
|
|
16059
|
-
const passes = useThree((s) => s.passes);
|
|
16060
|
-
const renderPipeline = useThree((s) => s.renderPipeline);
|
|
16061
|
-
|
|
16062
|
-
|
|
16063
|
-
|
|
16064
|
-
clearPasses,
|
|
16065
|
-
reset,
|
|
16066
|
-
rebuild,
|
|
16067
|
-
// isReady indicates if RenderPipeline is configured and ready for rendering
|
|
16068
|
-
isReady: renderPipeline !== null
|
|
16069
|
-
};
|
|
16147
|
+
const passes = useThree$1((s) => s.passes);
|
|
16148
|
+
const renderPipeline = useThree$1((s) => s.renderPipeline);
|
|
16149
|
+
const actions = { passes, clearPasses, reset, rebuild };
|
|
16150
|
+
if (renderPipeline) return { ...actions, isReady: true, renderPipeline };
|
|
16151
|
+
return { ...actions, isReady: false, renderPipeline: null };
|
|
16070
16152
|
}
|
|
16071
16153
|
|
|
16072
16154
|
extend(THREE);
|
|
16155
|
+
const useThree = useThree$1;
|
|
16156
|
+
const useFrame = useFrame$1;
|
|
16073
16157
|
|
|
16074
16158
|
exports.Scheduler = scheduler.Scheduler;
|
|
16075
16159
|
exports.getScheduler = scheduler.getScheduler;
|