@react-three/fiber 10.0.0-canary.6eb9584 → 10.0.0-canary.7a50545
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 +94 -43
- package/dist/index.d.cts +40 -11
- package/dist/index.d.mts +40 -11
- package/dist/index.d.ts +40 -11
- package/dist/index.mjs +94 -43
- package/dist/legacy.cjs +94 -43
- package/dist/legacy.d.cts +40 -11
- package/dist/legacy.d.mts +40 -11
- package/dist/legacy.d.ts +40 -11
- package/dist/legacy.mjs +94 -43
- package/dist/webgpu/index.cjs +119 -49
- package/dist/webgpu/index.d.cts +43 -10
- package/dist/webgpu/index.d.mts +43 -10
- package/dist/webgpu/index.d.ts +43 -10
- package/dist/webgpu/index.mjs +119 -49
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -925,7 +925,7 @@ const createStore = (invalidate, advance) => {
|
|
|
925
925
|
size: newSize,
|
|
926
926
|
viewport: { ...s.viewport, ...getCurrentViewport(state2.camera, defaultTarget, newSize) }
|
|
927
927
|
}));
|
|
928
|
-
|
|
928
|
+
get().invalidate();
|
|
929
929
|
}
|
|
930
930
|
}
|
|
931
931
|
return;
|
|
@@ -940,15 +940,16 @@ const createStore = (invalidate, advance) => {
|
|
|
940
940
|
viewport: { ...s.viewport, ...getCurrentViewport(state2.camera, defaultTarget, size) },
|
|
941
941
|
_sizeImperative: true
|
|
942
942
|
}));
|
|
943
|
-
|
|
943
|
+
get().invalidate();
|
|
944
944
|
},
|
|
945
945
|
setDpr: (dpr) => set((state2) => {
|
|
946
946
|
const resolved = calculateDpr(dpr);
|
|
947
947
|
return { viewport: { ...state2.viewport, dpr: resolved, initialDpr: state2.viewport.initialDpr || resolved } };
|
|
948
948
|
}),
|
|
949
949
|
setFrameloop: (frameloop = "always") => {
|
|
950
|
+
const rootId = get().internal.rootId;
|
|
951
|
+
if (rootId) scheduler.getScheduler().setRootFrameloop(rootId, frameloop);
|
|
950
952
|
set(() => ({ frameloop }));
|
|
951
|
-
scheduler.getScheduler().frameloop = frameloop;
|
|
952
953
|
},
|
|
953
954
|
setError: (error) => set(() => ({ error })),
|
|
954
955
|
error: null,
|
|
@@ -1064,17 +1065,10 @@ const createStore = (invalidate, advance) => {
|
|
|
1064
1065
|
oldSize = size;
|
|
1065
1066
|
oldDpr = viewport.dpr;
|
|
1066
1067
|
updateCamera(camera, size);
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
if (viewport.dpr > 0) actualRenderer.setPixelRatio(viewport.dpr);
|
|
1072
|
-
actualRenderer.setSize(size.width, size.height, false);
|
|
1073
|
-
if (canvasTarget) {
|
|
1074
|
-
if (viewport.dpr > 0) canvasTarget.setPixelRatio(viewport.dpr);
|
|
1075
|
-
canvasTarget.setSize(size.width, size.height, false);
|
|
1076
|
-
}
|
|
1077
|
-
}
|
|
1068
|
+
const resizeTarget = canvasTarget ?? actualRenderer;
|
|
1069
|
+
if (viewport.dpr > 0) resizeTarget.setPixelRatio(viewport.dpr);
|
|
1070
|
+
resizeTarget.setSize(size.width, size.height, false);
|
|
1071
|
+
internal.canvasTargetSizeDirty = true;
|
|
1078
1072
|
}
|
|
1079
1073
|
if (camera !== oldCamera) {
|
|
1080
1074
|
oldCamera = camera;
|
|
@@ -1136,7 +1130,11 @@ function useLoader(loader, input, extensions, onProgress, cacheKey) {
|
|
|
1136
1130
|
const results = cacheKeys.map(
|
|
1137
1131
|
(key, index) => suspendReact.suspend(() => fn(loader, inputs[index]), [loader, key], { equal: is.equ })
|
|
1138
1132
|
);
|
|
1139
|
-
|
|
1133
|
+
const stableRef = React.useRef(null);
|
|
1134
|
+
const previous = stableRef.current;
|
|
1135
|
+
const stable = previous !== null && previous.length === results.length && previous.every((value, i) => value === results[i]) ? previous : results;
|
|
1136
|
+
stableRef.current = stable;
|
|
1137
|
+
return Array.isArray(input) ? stable : stable[0];
|
|
1140
1138
|
}
|
|
1141
1139
|
useLoader.preload = function(loader, input, extensions, onProgress, cacheKey) {
|
|
1142
1140
|
const inputs = Array.isArray(input) ? input : [input];
|
|
@@ -1256,6 +1254,13 @@ function useFrame(callback, priorityOrOptions) {
|
|
|
1256
1254
|
* Use for controlling the entire frame loop, adding phases, etc.
|
|
1257
1255
|
*/
|
|
1258
1256
|
scheduler: scheduler2,
|
|
1257
|
+
/**
|
|
1258
|
+
* The root that currently owns this job. Resolve on access because ambient
|
|
1259
|
+
* jobs can be adopted by a Canvas after the controls object is created.
|
|
1260
|
+
*/
|
|
1261
|
+
get rootId() {
|
|
1262
|
+
return scheduler.getScheduler().getJobRootId(id);
|
|
1263
|
+
},
|
|
1259
1264
|
/**
|
|
1260
1265
|
* Manually step this job only.
|
|
1261
1266
|
* Bypasses FPS limiting - always runs.
|
|
@@ -1272,6 +1277,14 @@ function useFrame(callback, priorityOrOptions) {
|
|
|
1272
1277
|
stepAll: (timestamp) => {
|
|
1273
1278
|
scheduler.getScheduler().step(timestamp);
|
|
1274
1279
|
},
|
|
1280
|
+
/**
|
|
1281
|
+
* Request frames for this job's owning root without waking sibling roots.
|
|
1282
|
+
*/
|
|
1283
|
+
invalidate: (frames, stackFrames) => {
|
|
1284
|
+
const scheduler3 = scheduler.getScheduler();
|
|
1285
|
+
const rootId = scheduler3.getJobRootId(id);
|
|
1286
|
+
if (rootId) scheduler3.invalidateRoot(rootId, frames, stackFrames);
|
|
1287
|
+
},
|
|
1275
1288
|
/**
|
|
1276
1289
|
* Pause this job (set enabled=false).
|
|
1277
1290
|
* Job remains registered but won't run.
|
|
@@ -1301,6 +1314,11 @@ function getUrls(input) {
|
|
|
1301
1314
|
if (Array.isArray(input)) return input;
|
|
1302
1315
|
return Object.values(input);
|
|
1303
1316
|
}
|
|
1317
|
+
function inputSignature(input) {
|
|
1318
|
+
if (typeof input === "string") return input;
|
|
1319
|
+
if (Array.isArray(input)) return input.join("\0");
|
|
1320
|
+
return Object.keys(input).sort().map((key) => `${key}\0${input[key]}`).join("");
|
|
1321
|
+
}
|
|
1304
1322
|
function allUrlsCached(urls, textureCache) {
|
|
1305
1323
|
return urls.every((url) => textureCache.has(url));
|
|
1306
1324
|
}
|
|
@@ -1326,18 +1344,19 @@ function useTexture(input, optionsOrOnLoad) {
|
|
|
1326
1344
|
const onLoadRef = React.useRef(onLoad);
|
|
1327
1345
|
onLoadRef.current = onLoad;
|
|
1328
1346
|
const onLoadCalledForRef = React.useRef(null);
|
|
1329
|
-
const
|
|
1347
|
+
const inputKey = React.useMemo(() => inputSignature(input), [input]);
|
|
1348
|
+
const stableInput = React.useMemo(() => input, [inputKey]);
|
|
1349
|
+
const urls = React.useMemo(() => getUrls(stableInput), [stableInput]);
|
|
1330
1350
|
const cachedResult = React.useMemo(() => {
|
|
1331
1351
|
if (!cache) return null;
|
|
1332
1352
|
const textures = store.getState().textures;
|
|
1333
1353
|
if (!allUrlsCached(urls, textures)) return null;
|
|
1334
|
-
return buildFromCache(
|
|
1335
|
-
}, [cache, urls,
|
|
1354
|
+
return buildFromCache(stableInput, textures);
|
|
1355
|
+
}, [cache, urls, stableInput, store]);
|
|
1336
1356
|
const loadedTextures = useLoader(
|
|
1337
1357
|
webgpu.TextureLoader,
|
|
1338
|
-
IsObject(
|
|
1358
|
+
IsObject(stableInput) ? Object.values(stableInput) : stableInput
|
|
1339
1359
|
);
|
|
1340
|
-
const inputKey = urls.join("\0");
|
|
1341
1360
|
React.useLayoutEffect(() => {
|
|
1342
1361
|
if (cachedResult) return;
|
|
1343
1362
|
if (onLoadCalledForRef.current === inputKey) return;
|
|
@@ -1364,28 +1383,28 @@ function useTexture(input, optionsOrOnLoad) {
|
|
|
1364
1383
|
}, [renderer, loadedTextures, cachedResult]);
|
|
1365
1384
|
const mappedTextures = React.useMemo(() => {
|
|
1366
1385
|
if (cachedResult) return cachedResult;
|
|
1367
|
-
if (IsObject(
|
|
1386
|
+
if (IsObject(stableInput)) {
|
|
1368
1387
|
const keyed = {};
|
|
1369
1388
|
const textureArray = loadedTextures;
|
|
1370
1389
|
let i = 0;
|
|
1371
|
-
for (const key in
|
|
1390
|
+
for (const key in stableInput) keyed[key] = textureArray[i++];
|
|
1372
1391
|
return keyed;
|
|
1373
1392
|
} else {
|
|
1374
1393
|
return loadedTextures;
|
|
1375
1394
|
}
|
|
1376
|
-
}, [
|
|
1395
|
+
}, [stableInput, loadedTextures, cachedResult]);
|
|
1377
1396
|
React.useEffect(() => {
|
|
1378
1397
|
if (!cache) return;
|
|
1379
1398
|
const urlTextureMap = [];
|
|
1380
|
-
if (typeof
|
|
1381
|
-
urlTextureMap.push([
|
|
1382
|
-
} else if (Array.isArray(
|
|
1399
|
+
if (typeof stableInput === "string") {
|
|
1400
|
+
urlTextureMap.push([stableInput, mappedTextures]);
|
|
1401
|
+
} else if (Array.isArray(stableInput)) {
|
|
1383
1402
|
const textureArray = mappedTextures;
|
|
1384
|
-
|
|
1385
|
-
} else if (IsObject(
|
|
1403
|
+
stableInput.forEach((url, i) => urlTextureMap.push([url, textureArray[i]]));
|
|
1404
|
+
} else if (IsObject(stableInput)) {
|
|
1386
1405
|
const textureRecord = mappedTextures;
|
|
1387
|
-
for (const key in
|
|
1388
|
-
const url =
|
|
1406
|
+
for (const key in stableInput) {
|
|
1407
|
+
const url = stableInput[key];
|
|
1389
1408
|
urlTextureMap.push([url, textureRecord[key]]);
|
|
1390
1409
|
}
|
|
1391
1410
|
}
|
|
@@ -1414,7 +1433,7 @@ function useTexture(input, optionsOrOnLoad) {
|
|
|
1414
1433
|
}
|
|
1415
1434
|
return { _textureRefs: refs };
|
|
1416
1435
|
});
|
|
1417
|
-
}, [cache,
|
|
1436
|
+
}, [cache, stableInput, mappedTextures, store]);
|
|
1418
1437
|
return mappedTextures;
|
|
1419
1438
|
}
|
|
1420
1439
|
useTexture.preload = (url) => useLoader.preload(webgpu.TextureLoader, url);
|
|
@@ -1685,10 +1704,16 @@ function addTail(callback) {
|
|
|
1685
1704
|
return scheduler.getScheduler().onIdle(callback);
|
|
1686
1705
|
}
|
|
1687
1706
|
function invalidate(state, frames = 1, stackFrames = false) {
|
|
1688
|
-
|
|
1707
|
+
const rootId = state?.internal?.rootId;
|
|
1708
|
+
const scheduler$1 = scheduler.getScheduler();
|
|
1709
|
+
if (rootId) scheduler$1.invalidateRoot(rootId, frames, stackFrames);
|
|
1710
|
+
else scheduler$1.invalidate(frames, stackFrames);
|
|
1689
1711
|
}
|
|
1690
|
-
function advance(timestamp) {
|
|
1691
|
-
|
|
1712
|
+
function advance(timestamp, runGlobalEffects, state) {
|
|
1713
|
+
const rootId = state?.internal?.rootId;
|
|
1714
|
+
const scheduler$1 = scheduler.getScheduler();
|
|
1715
|
+
if (rootId) scheduler$1.stepRoot(rootId, timestamp);
|
|
1716
|
+
else scheduler$1.step(timestamp);
|
|
1692
1717
|
}
|
|
1693
1718
|
|
|
1694
1719
|
const version = "10.0.0-alpha.3";
|
|
@@ -14350,7 +14375,7 @@ function createRoot(canvas) {
|
|
|
14350
14375
|
const handleXRFrame = (timestamp, _frame) => {
|
|
14351
14376
|
const state2 = store.getState();
|
|
14352
14377
|
if (state2.frameloop === "never") return;
|
|
14353
|
-
advance(timestamp);
|
|
14378
|
+
advance(timestamp, true, state2);
|
|
14354
14379
|
};
|
|
14355
14380
|
const actualRenderer = state.internal.actualRenderer;
|
|
14356
14381
|
const handleSessionChange = () => {
|
|
@@ -14358,7 +14383,7 @@ function createRoot(canvas) {
|
|
|
14358
14383
|
const renderer2 = state2.internal.actualRenderer;
|
|
14359
14384
|
actualRenderer.xr.enabled = actualRenderer.xr.isPresenting;
|
|
14360
14385
|
renderer2.xr.setAnimationLoop(renderer2.xr.isPresenting ? handleXRFrame : null);
|
|
14361
|
-
if (!renderer2.xr.isPresenting) invalidate();
|
|
14386
|
+
if (!renderer2.xr.isPresenting) invalidate(state2);
|
|
14362
14387
|
};
|
|
14363
14388
|
const xr = {
|
|
14364
14389
|
connect() {
|
|
@@ -14440,7 +14465,11 @@ function createRoot(canvas) {
|
|
|
14440
14465
|
const newRootId = canvasId || scheduler$1.generateRootId();
|
|
14441
14466
|
const unregisterRoot = scheduler$1.registerRoot(newRootId, {
|
|
14442
14467
|
getState: () => store.getState(),
|
|
14443
|
-
onError: (err) => store.getState().setError(err)
|
|
14468
|
+
onError: (err) => store.getState().setError(err),
|
|
14469
|
+
frameloop: store.getState().frameloop,
|
|
14470
|
+
before: schedulerConfig?.before,
|
|
14471
|
+
after: schedulerConfig?.after,
|
|
14472
|
+
order: schedulerConfig?.order
|
|
14444
14473
|
});
|
|
14445
14474
|
const unregisterCanvasTarget = scheduler$1.register(
|
|
14446
14475
|
() => {
|
|
@@ -14448,6 +14477,10 @@ function createRoot(canvas) {
|
|
|
14448
14477
|
if (state2.internal.isMultiCanvas && state2.internal.canvasTarget) {
|
|
14449
14478
|
const renderer2 = state2.internal.actualRenderer;
|
|
14450
14479
|
renderer2.setCanvasTarget(state2.internal.canvasTarget);
|
|
14480
|
+
if (state2.internal.canvasTargetSizeDirty) {
|
|
14481
|
+
state2.internal.canvasTargetSizeDirty = false;
|
|
14482
|
+
renderer2.backend?.updateSize?.();
|
|
14483
|
+
}
|
|
14451
14484
|
}
|
|
14452
14485
|
},
|
|
14453
14486
|
{
|
|
@@ -14516,8 +14549,7 @@ function createRoot(canvas) {
|
|
|
14516
14549
|
phase: "render",
|
|
14517
14550
|
system: true,
|
|
14518
14551
|
// Internal flag: this is a system job, not user-controlled
|
|
14519
|
-
//
|
|
14520
|
-
...schedulerConfig?.after && { after: schedulerConfig.after },
|
|
14552
|
+
// FPS throttles only the default render job; Canvas ordering belongs to the root.
|
|
14521
14553
|
...schedulerConfig?.fps && { fps: schedulerConfig.fps }
|
|
14522
14554
|
}
|
|
14523
14555
|
);
|
|
@@ -14536,8 +14568,21 @@ function createRoot(canvas) {
|
|
|
14536
14568
|
scheduler: scheduler$1
|
|
14537
14569
|
}
|
|
14538
14570
|
}));
|
|
14571
|
+
} else {
|
|
14572
|
+
const constraintsChanged = !is.equ(schedulerConfig?.before, lastConfiguredProps.schedulerBefore, shallowLoose) || !is.equ(schedulerConfig?.after, lastConfiguredProps.schedulerAfter, shallowLoose);
|
|
14573
|
+
if (constraintsChanged) {
|
|
14574
|
+
scheduler$1.setRootConstraints(rootId, {
|
|
14575
|
+
before: schedulerConfig?.before,
|
|
14576
|
+
after: schedulerConfig?.after
|
|
14577
|
+
});
|
|
14578
|
+
}
|
|
14579
|
+
if (schedulerConfig?.order !== lastConfiguredProps.schedulerOrder) {
|
|
14580
|
+
scheduler$1.setRootOrder(rootId, schedulerConfig?.order ?? 0);
|
|
14581
|
+
}
|
|
14539
14582
|
}
|
|
14540
|
-
|
|
14583
|
+
lastConfiguredProps.schedulerBefore = schedulerConfig?.before;
|
|
14584
|
+
lastConfiguredProps.schedulerAfter = schedulerConfig?.after;
|
|
14585
|
+
lastConfiguredProps.schedulerOrder = schedulerConfig?.order;
|
|
14541
14586
|
onCreated = onCreatedCallback;
|
|
14542
14587
|
configured = true;
|
|
14543
14588
|
resolve();
|
|
@@ -14579,14 +14624,19 @@ function unmountComponentAtNode(canvas, callback) {
|
|
|
14579
14624
|
const fiber = root?.fiber;
|
|
14580
14625
|
if (fiber) {
|
|
14581
14626
|
const state = root?.store.getState();
|
|
14582
|
-
if (state)
|
|
14627
|
+
if (state) {
|
|
14628
|
+
state.internal.active = false;
|
|
14629
|
+
const unregisterRoot = state.internal.unregisterRoot;
|
|
14630
|
+
if (unregisterRoot) {
|
|
14631
|
+
unregisterRoot();
|
|
14632
|
+
state.internal.unregisterRoot = void 0;
|
|
14633
|
+
}
|
|
14634
|
+
}
|
|
14583
14635
|
reconciler.updateContainer(null, fiber, null, () => {
|
|
14584
14636
|
if (state) {
|
|
14585
14637
|
setTimeout(() => {
|
|
14586
14638
|
try {
|
|
14587
14639
|
const renderer = state.internal.actualRenderer;
|
|
14588
|
-
const unregisterRoot = state.internal.unregisterRoot;
|
|
14589
|
-
if (unregisterRoot) unregisterRoot();
|
|
14590
14640
|
const unregisterPrimary = state.internal.unregisterPrimary;
|
|
14591
14641
|
if (unregisterPrimary) unregisterPrimary();
|
|
14592
14642
|
const canvasTarget = state.internal.canvasTarget;
|
|
@@ -15180,6 +15230,7 @@ function CanvasImpl({
|
|
|
15180
15230
|
const canvas = canvasRef.current;
|
|
15181
15231
|
if (canvas) {
|
|
15182
15232
|
return () => {
|
|
15233
|
+
if (canvas.isConnected) return;
|
|
15183
15234
|
unmountComponentAtNode(canvas);
|
|
15184
15235
|
root.current = null;
|
|
15185
15236
|
};
|
package/dist/index.d.cts
CHANGED
|
@@ -501,6 +501,18 @@ interface InternalState {
|
|
|
501
501
|
* @see https://threejs.org/docs/#api/en/renderers/common/CanvasTarget
|
|
502
502
|
*/
|
|
503
503
|
canvasTarget?: CanvasTarget
|
|
504
|
+
/**
|
|
505
|
+
* Set when this root's canvas target has been resized and the backend's cached render pass
|
|
506
|
+
* descriptor (which holds a depth-stencil view built once per canvas) is therefore stale.
|
|
507
|
+
*
|
|
508
|
+
* Flushed by the canvas-target job in the `start` phase, which is the only place this root's
|
|
509
|
+
* target is guaranteed to be the renderer's active one — `backend.updateSize()` operates on
|
|
510
|
+
* whatever `getCanvasTarget()` returns, so calling it from the resize subscription would
|
|
511
|
+
* invalidate some other canvas's descriptor instead.
|
|
512
|
+
*
|
|
513
|
+
* @see https://github.com/pmndrs/react-three-fiber/issues/3847
|
|
514
|
+
*/
|
|
515
|
+
canvasTargetSizeDirty?: boolean
|
|
504
516
|
/**
|
|
505
517
|
* Whether multi-canvas rendering is active.
|
|
506
518
|
* True when any canvas uses `renderer={{ primaryCanvas: 'id' }}` to share a renderer.
|
|
@@ -710,12 +722,19 @@ type DefaultRendererProps = {
|
|
|
710
722
|
*/
|
|
711
723
|
interface CanvasSchedulerConfig {
|
|
712
724
|
/**
|
|
713
|
-
*
|
|
714
|
-
|
|
725
|
+
* Run this Canvas root before the referenced Canvas root id(s).
|
|
726
|
+
*/
|
|
727
|
+
before?: string | string[]
|
|
728
|
+
/**
|
|
729
|
+
* Run this Canvas root after the referenced Canvas root id(s).
|
|
715
730
|
*/
|
|
716
|
-
after?: string
|
|
731
|
+
after?: string | string[]
|
|
717
732
|
/**
|
|
718
|
-
*
|
|
733
|
+
* Numeric root order. Lower values run first.
|
|
734
|
+
*/
|
|
735
|
+
order?: number
|
|
736
|
+
/**
|
|
737
|
+
* Limit this Canvas's default render job (frames per second).
|
|
719
738
|
*/
|
|
720
739
|
fps?: number
|
|
721
740
|
}
|
|
@@ -1319,11 +1338,16 @@ declare global {
|
|
|
1319
1338
|
/** Pass record - stores TSL pass nodes for render pipeline */
|
|
1320
1339
|
type PassRecord = Record<string, any>
|
|
1321
1340
|
|
|
1341
|
+
/** State passed to pipeline callbacks after the active pipeline has been created */
|
|
1342
|
+
type RenderPipelineCallbackState = RootState & {
|
|
1343
|
+
renderPipeline: ThreeRenderPipeline
|
|
1344
|
+
}
|
|
1345
|
+
|
|
1322
1346
|
/** Setup callback - runs first to configure MRT, create additional passes */
|
|
1323
|
-
type RenderPipelineSetupCallback = (state:
|
|
1347
|
+
type RenderPipelineSetupCallback = (state: RenderPipelineCallbackState) => PassRecord | void
|
|
1324
1348
|
|
|
1325
1349
|
/** Main callback - runs second to configure outputNode, create effect passes */
|
|
1326
|
-
type RenderPipelineMainCallback = (state:
|
|
1350
|
+
type RenderPipelineMainCallback = (state: RenderPipelineCallbackState) => PassRecord | void
|
|
1327
1351
|
|
|
1328
1352
|
/** Return type for useRenderPipeline hook */
|
|
1329
1353
|
interface UseRenderPipelineReturn {
|
|
@@ -1883,7 +1907,7 @@ declare namespace useLoader {
|
|
|
1883
1907
|
*
|
|
1884
1908
|
* @param callback - Function called each frame with (state, delta). Optional if you only need scheduler access.
|
|
1885
1909
|
* @param priorityOrOptions - Either a priority number (backwards compat) or options object
|
|
1886
|
-
* @returns Controls object with step(), stepAll(), pause(), resume(), isPaused, id, scheduler
|
|
1910
|
+
* @returns Controls object with step(), stepAll(), invalidate(), pause(), resume(), isPaused, id, rootId, scheduler
|
|
1887
1911
|
*
|
|
1888
1912
|
* @example
|
|
1889
1913
|
* // Simple priority (backwards compat)
|
|
@@ -2179,7 +2203,10 @@ declare function addTail(callback: GlobalRenderCallback): () => void;
|
|
|
2179
2203
|
* Invalidates the view, requesting a frame to be rendered.
|
|
2180
2204
|
* In demand mode, this triggers the scheduler to run frames.
|
|
2181
2205
|
*
|
|
2182
|
-
*
|
|
2206
|
+
* With a state argument, only that root's jobs run on the requested frames; other
|
|
2207
|
+
* roots on 'demand' stay idle. Without one, every registered root is invalidated.
|
|
2208
|
+
*
|
|
2209
|
+
* @param state - Optional root state; targets the invalidation at that root
|
|
2183
2210
|
* @param frames - Number of frames to request (default: 1)
|
|
2184
2211
|
* @param stackFrames - If false, sets pendingFrames to frames. If true, adds to existing pendingFrames (default: false)
|
|
2185
2212
|
*
|
|
@@ -2190,14 +2217,16 @@ declare function invalidate(state?: RootState, frames?: number, stackFrames?: bo
|
|
|
2190
2217
|
* Advances the frameloop and runs render effects.
|
|
2191
2218
|
* Useful for when manually rendering via `frameloop="never"`.
|
|
2192
2219
|
*
|
|
2220
|
+
* With a state argument, only that root is stepped. Without one, every
|
|
2221
|
+
* registered root is stepped for backwards compatibility.
|
|
2222
|
+
*
|
|
2193
2223
|
* @param timestamp - The timestamp to use for this frame
|
|
2194
2224
|
* @param runGlobalEffects - Ignored (kept for backwards compat, global effects always run)
|
|
2195
|
-
* @param state -
|
|
2196
|
-
* @param frame - Ignored (kept for backwards compat)
|
|
2225
|
+
* @param state - Optional root state; targets the manual step at that root
|
|
2197
2226
|
*
|
|
2198
2227
|
* @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#advance
|
|
2199
2228
|
*/
|
|
2200
|
-
declare function advance(timestamp: number): void;
|
|
2229
|
+
declare function advance(timestamp: number, runGlobalEffects?: boolean, state?: RootState): void;
|
|
2201
2230
|
|
|
2202
2231
|
/* eslint-disable @definitelytyped/no-unnecessary-generics */
|
|
2203
2232
|
declare function ReactReconciler<
|
package/dist/index.d.mts
CHANGED
|
@@ -501,6 +501,18 @@ interface InternalState {
|
|
|
501
501
|
* @see https://threejs.org/docs/#api/en/renderers/common/CanvasTarget
|
|
502
502
|
*/
|
|
503
503
|
canvasTarget?: CanvasTarget
|
|
504
|
+
/**
|
|
505
|
+
* Set when this root's canvas target has been resized and the backend's cached render pass
|
|
506
|
+
* descriptor (which holds a depth-stencil view built once per canvas) is therefore stale.
|
|
507
|
+
*
|
|
508
|
+
* Flushed by the canvas-target job in the `start` phase, which is the only place this root's
|
|
509
|
+
* target is guaranteed to be the renderer's active one — `backend.updateSize()` operates on
|
|
510
|
+
* whatever `getCanvasTarget()` returns, so calling it from the resize subscription would
|
|
511
|
+
* invalidate some other canvas's descriptor instead.
|
|
512
|
+
*
|
|
513
|
+
* @see https://github.com/pmndrs/react-three-fiber/issues/3847
|
|
514
|
+
*/
|
|
515
|
+
canvasTargetSizeDirty?: boolean
|
|
504
516
|
/**
|
|
505
517
|
* Whether multi-canvas rendering is active.
|
|
506
518
|
* True when any canvas uses `renderer={{ primaryCanvas: 'id' }}` to share a renderer.
|
|
@@ -710,12 +722,19 @@ type DefaultRendererProps = {
|
|
|
710
722
|
*/
|
|
711
723
|
interface CanvasSchedulerConfig {
|
|
712
724
|
/**
|
|
713
|
-
*
|
|
714
|
-
|
|
725
|
+
* Run this Canvas root before the referenced Canvas root id(s).
|
|
726
|
+
*/
|
|
727
|
+
before?: string | string[]
|
|
728
|
+
/**
|
|
729
|
+
* Run this Canvas root after the referenced Canvas root id(s).
|
|
715
730
|
*/
|
|
716
|
-
after?: string
|
|
731
|
+
after?: string | string[]
|
|
717
732
|
/**
|
|
718
|
-
*
|
|
733
|
+
* Numeric root order. Lower values run first.
|
|
734
|
+
*/
|
|
735
|
+
order?: number
|
|
736
|
+
/**
|
|
737
|
+
* Limit this Canvas's default render job (frames per second).
|
|
719
738
|
*/
|
|
720
739
|
fps?: number
|
|
721
740
|
}
|
|
@@ -1319,11 +1338,16 @@ declare global {
|
|
|
1319
1338
|
/** Pass record - stores TSL pass nodes for render pipeline */
|
|
1320
1339
|
type PassRecord = Record<string, any>
|
|
1321
1340
|
|
|
1341
|
+
/** State passed to pipeline callbacks after the active pipeline has been created */
|
|
1342
|
+
type RenderPipelineCallbackState = RootState & {
|
|
1343
|
+
renderPipeline: ThreeRenderPipeline
|
|
1344
|
+
}
|
|
1345
|
+
|
|
1322
1346
|
/** Setup callback - runs first to configure MRT, create additional passes */
|
|
1323
|
-
type RenderPipelineSetupCallback = (state:
|
|
1347
|
+
type RenderPipelineSetupCallback = (state: RenderPipelineCallbackState) => PassRecord | void
|
|
1324
1348
|
|
|
1325
1349
|
/** Main callback - runs second to configure outputNode, create effect passes */
|
|
1326
|
-
type RenderPipelineMainCallback = (state:
|
|
1350
|
+
type RenderPipelineMainCallback = (state: RenderPipelineCallbackState) => PassRecord | void
|
|
1327
1351
|
|
|
1328
1352
|
/** Return type for useRenderPipeline hook */
|
|
1329
1353
|
interface UseRenderPipelineReturn {
|
|
@@ -1883,7 +1907,7 @@ declare namespace useLoader {
|
|
|
1883
1907
|
*
|
|
1884
1908
|
* @param callback - Function called each frame with (state, delta). Optional if you only need scheduler access.
|
|
1885
1909
|
* @param priorityOrOptions - Either a priority number (backwards compat) or options object
|
|
1886
|
-
* @returns Controls object with step(), stepAll(), pause(), resume(), isPaused, id, scheduler
|
|
1910
|
+
* @returns Controls object with step(), stepAll(), invalidate(), pause(), resume(), isPaused, id, rootId, scheduler
|
|
1887
1911
|
*
|
|
1888
1912
|
* @example
|
|
1889
1913
|
* // Simple priority (backwards compat)
|
|
@@ -2179,7 +2203,10 @@ declare function addTail(callback: GlobalRenderCallback): () => void;
|
|
|
2179
2203
|
* Invalidates the view, requesting a frame to be rendered.
|
|
2180
2204
|
* In demand mode, this triggers the scheduler to run frames.
|
|
2181
2205
|
*
|
|
2182
|
-
*
|
|
2206
|
+
* With a state argument, only that root's jobs run on the requested frames; other
|
|
2207
|
+
* roots on 'demand' stay idle. Without one, every registered root is invalidated.
|
|
2208
|
+
*
|
|
2209
|
+
* @param state - Optional root state; targets the invalidation at that root
|
|
2183
2210
|
* @param frames - Number of frames to request (default: 1)
|
|
2184
2211
|
* @param stackFrames - If false, sets pendingFrames to frames. If true, adds to existing pendingFrames (default: false)
|
|
2185
2212
|
*
|
|
@@ -2190,14 +2217,16 @@ declare function invalidate(state?: RootState, frames?: number, stackFrames?: bo
|
|
|
2190
2217
|
* Advances the frameloop and runs render effects.
|
|
2191
2218
|
* Useful for when manually rendering via `frameloop="never"`.
|
|
2192
2219
|
*
|
|
2220
|
+
* With a state argument, only that root is stepped. Without one, every
|
|
2221
|
+
* registered root is stepped for backwards compatibility.
|
|
2222
|
+
*
|
|
2193
2223
|
* @param timestamp - The timestamp to use for this frame
|
|
2194
2224
|
* @param runGlobalEffects - Ignored (kept for backwards compat, global effects always run)
|
|
2195
|
-
* @param state -
|
|
2196
|
-
* @param frame - Ignored (kept for backwards compat)
|
|
2225
|
+
* @param state - Optional root state; targets the manual step at that root
|
|
2197
2226
|
*
|
|
2198
2227
|
* @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#advance
|
|
2199
2228
|
*/
|
|
2200
|
-
declare function advance(timestamp: number): void;
|
|
2229
|
+
declare function advance(timestamp: number, runGlobalEffects?: boolean, state?: RootState): void;
|
|
2201
2230
|
|
|
2202
2231
|
/* eslint-disable @definitelytyped/no-unnecessary-generics */
|
|
2203
2232
|
declare function ReactReconciler<
|
package/dist/index.d.ts
CHANGED
|
@@ -501,6 +501,18 @@ interface InternalState {
|
|
|
501
501
|
* @see https://threejs.org/docs/#api/en/renderers/common/CanvasTarget
|
|
502
502
|
*/
|
|
503
503
|
canvasTarget?: CanvasTarget
|
|
504
|
+
/**
|
|
505
|
+
* Set when this root's canvas target has been resized and the backend's cached render pass
|
|
506
|
+
* descriptor (which holds a depth-stencil view built once per canvas) is therefore stale.
|
|
507
|
+
*
|
|
508
|
+
* Flushed by the canvas-target job in the `start` phase, which is the only place this root's
|
|
509
|
+
* target is guaranteed to be the renderer's active one — `backend.updateSize()` operates on
|
|
510
|
+
* whatever `getCanvasTarget()` returns, so calling it from the resize subscription would
|
|
511
|
+
* invalidate some other canvas's descriptor instead.
|
|
512
|
+
*
|
|
513
|
+
* @see https://github.com/pmndrs/react-three-fiber/issues/3847
|
|
514
|
+
*/
|
|
515
|
+
canvasTargetSizeDirty?: boolean
|
|
504
516
|
/**
|
|
505
517
|
* Whether multi-canvas rendering is active.
|
|
506
518
|
* True when any canvas uses `renderer={{ primaryCanvas: 'id' }}` to share a renderer.
|
|
@@ -710,12 +722,19 @@ type DefaultRendererProps = {
|
|
|
710
722
|
*/
|
|
711
723
|
interface CanvasSchedulerConfig {
|
|
712
724
|
/**
|
|
713
|
-
*
|
|
714
|
-
|
|
725
|
+
* Run this Canvas root before the referenced Canvas root id(s).
|
|
726
|
+
*/
|
|
727
|
+
before?: string | string[]
|
|
728
|
+
/**
|
|
729
|
+
* Run this Canvas root after the referenced Canvas root id(s).
|
|
715
730
|
*/
|
|
716
|
-
after?: string
|
|
731
|
+
after?: string | string[]
|
|
717
732
|
/**
|
|
718
|
-
*
|
|
733
|
+
* Numeric root order. Lower values run first.
|
|
734
|
+
*/
|
|
735
|
+
order?: number
|
|
736
|
+
/**
|
|
737
|
+
* Limit this Canvas's default render job (frames per second).
|
|
719
738
|
*/
|
|
720
739
|
fps?: number
|
|
721
740
|
}
|
|
@@ -1319,11 +1338,16 @@ declare global {
|
|
|
1319
1338
|
/** Pass record - stores TSL pass nodes for render pipeline */
|
|
1320
1339
|
type PassRecord = Record<string, any>
|
|
1321
1340
|
|
|
1341
|
+
/** State passed to pipeline callbacks after the active pipeline has been created */
|
|
1342
|
+
type RenderPipelineCallbackState = RootState & {
|
|
1343
|
+
renderPipeline: ThreeRenderPipeline
|
|
1344
|
+
}
|
|
1345
|
+
|
|
1322
1346
|
/** Setup callback - runs first to configure MRT, create additional passes */
|
|
1323
|
-
type RenderPipelineSetupCallback = (state:
|
|
1347
|
+
type RenderPipelineSetupCallback = (state: RenderPipelineCallbackState) => PassRecord | void
|
|
1324
1348
|
|
|
1325
1349
|
/** Main callback - runs second to configure outputNode, create effect passes */
|
|
1326
|
-
type RenderPipelineMainCallback = (state:
|
|
1350
|
+
type RenderPipelineMainCallback = (state: RenderPipelineCallbackState) => PassRecord | void
|
|
1327
1351
|
|
|
1328
1352
|
/** Return type for useRenderPipeline hook */
|
|
1329
1353
|
interface UseRenderPipelineReturn {
|
|
@@ -1883,7 +1907,7 @@ declare namespace useLoader {
|
|
|
1883
1907
|
*
|
|
1884
1908
|
* @param callback - Function called each frame with (state, delta). Optional if you only need scheduler access.
|
|
1885
1909
|
* @param priorityOrOptions - Either a priority number (backwards compat) or options object
|
|
1886
|
-
* @returns Controls object with step(), stepAll(), pause(), resume(), isPaused, id, scheduler
|
|
1910
|
+
* @returns Controls object with step(), stepAll(), invalidate(), pause(), resume(), isPaused, id, rootId, scheduler
|
|
1887
1911
|
*
|
|
1888
1912
|
* @example
|
|
1889
1913
|
* // Simple priority (backwards compat)
|
|
@@ -2179,7 +2203,10 @@ declare function addTail(callback: GlobalRenderCallback): () => void;
|
|
|
2179
2203
|
* Invalidates the view, requesting a frame to be rendered.
|
|
2180
2204
|
* In demand mode, this triggers the scheduler to run frames.
|
|
2181
2205
|
*
|
|
2182
|
-
*
|
|
2206
|
+
* With a state argument, only that root's jobs run on the requested frames; other
|
|
2207
|
+
* roots on 'demand' stay idle. Without one, every registered root is invalidated.
|
|
2208
|
+
*
|
|
2209
|
+
* @param state - Optional root state; targets the invalidation at that root
|
|
2183
2210
|
* @param frames - Number of frames to request (default: 1)
|
|
2184
2211
|
* @param stackFrames - If false, sets pendingFrames to frames. If true, adds to existing pendingFrames (default: false)
|
|
2185
2212
|
*
|
|
@@ -2190,14 +2217,16 @@ declare function invalidate(state?: RootState, frames?: number, stackFrames?: bo
|
|
|
2190
2217
|
* Advances the frameloop and runs render effects.
|
|
2191
2218
|
* Useful for when manually rendering via `frameloop="never"`.
|
|
2192
2219
|
*
|
|
2220
|
+
* With a state argument, only that root is stepped. Without one, every
|
|
2221
|
+
* registered root is stepped for backwards compatibility.
|
|
2222
|
+
*
|
|
2193
2223
|
* @param timestamp - The timestamp to use for this frame
|
|
2194
2224
|
* @param runGlobalEffects - Ignored (kept for backwards compat, global effects always run)
|
|
2195
|
-
* @param state -
|
|
2196
|
-
* @param frame - Ignored (kept for backwards compat)
|
|
2225
|
+
* @param state - Optional root state; targets the manual step at that root
|
|
2197
2226
|
*
|
|
2198
2227
|
* @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#advance
|
|
2199
2228
|
*/
|
|
2200
|
-
declare function advance(timestamp: number): void;
|
|
2229
|
+
declare function advance(timestamp: number, runGlobalEffects?: boolean, state?: RootState): void;
|
|
2201
2230
|
|
|
2202
2231
|
/* eslint-disable @definitelytyped/no-unnecessary-generics */
|
|
2203
2232
|
declare function ReactReconciler<
|