@react-three/fiber 9.8.0 → 9.8.1
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/CHANGELOG.md +24 -0
- package/dist/declarations/src/core/{renderer.d.ts → configuration.d.ts} +21 -28
- package/dist/declarations/src/core/index.d.ts +6 -3
- package/dist/declarations/src/core/portal.d.ts +13 -0
- package/dist/declarations/src/core/promise.d.ts +7 -3
- package/dist/declarations/src/core/reconciler.d.ts +8 -8
- package/dist/declarations/src/core/root.d.ts +35 -0
- package/dist/declarations/src/core/utils.d.ts +1 -1
- package/dist/{events-ce5e34e8.cjs.dev.js → events-21d8cd92.cjs.dev.js} +605 -482
- package/dist/{events-803f4abc.esm.js → events-9ce18a08.esm.js} +607 -484
- package/dist/{events-a79ef12b.cjs.prod.js → events-a816cbab.cjs.prod.js} +605 -482
- package/dist/react-three-fiber.cjs.dev.js +21 -4
- package/dist/react-three-fiber.cjs.prod.js +21 -4
- package/dist/react-three-fiber.esm.js +22 -5
- package/native/dist/react-three-fiber-native.cjs.dev.js +4 -3
- package/native/dist/react-three-fiber-native.cjs.prod.js +4 -3
- package/native/dist/react-three-fiber-native.esm.js +5 -4
- package/package.json +2 -2
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import React__default from 'react';
|
|
3
3
|
import * as THREE from 'three';
|
|
4
|
+
import { jsx, Fragment } from 'react/jsx-runtime';
|
|
4
5
|
import { createWithEqualityFn } from 'zustand/traditional';
|
|
5
6
|
import { suspend, preload, clear } from 'suspend-react';
|
|
6
7
|
import w1, { unstable_getCurrentPriorityLevel, unstable_IdlePriority, unstable_LowPriority, unstable_NormalPriority, unstable_UserBlockingPriority, unstable_ImmediatePriority, unstable_scheduleCallback } from 'scheduler';
|
|
7
|
-
import {
|
|
8
|
-
import { useFiber, useContextBridge, traverseFiber } from 'its-fine';
|
|
8
|
+
import { useFiber, useContextBridge, traverseFiber, useActivityBridge as useActivityBridge$1 } from 'its-fine';
|
|
9
9
|
|
|
10
10
|
var threeTypes = /*#__PURE__*/Object.freeze({
|
|
11
11
|
__proto__: null
|
|
@@ -70,23 +70,29 @@ function useGate() {
|
|
|
70
70
|
}) : null;
|
|
71
71
|
return [gate, waitFor];
|
|
72
72
|
}
|
|
73
|
+
|
|
74
|
+
// Activity is optional on React 19.0/19.1. A computed key also supports strict ESM bundlers.
|
|
75
|
+
const useActivityBridge = React['Activity' + ''] ? useActivityBridge$1 : () => React.Fragment;
|
|
73
76
|
/**
|
|
74
|
-
* Bridges
|
|
77
|
+
* Bridges Context, StrictMode, and Activity visibility from a primary renderer.
|
|
75
78
|
*/
|
|
76
79
|
function useBridge() {
|
|
77
80
|
const fiber = useFiber();
|
|
78
81
|
const ContextBridge = useContextBridge();
|
|
82
|
+
const ActivityBridge = useActivityBridge();
|
|
79
83
|
return React.useMemo(() => ({
|
|
80
84
|
children
|
|
81
85
|
}) => {
|
|
82
86
|
const strict = !!traverseFiber(fiber, true, node => node.type === React.StrictMode);
|
|
83
87
|
const Root = strict ? React.StrictMode : React.Fragment;
|
|
84
88
|
return /*#__PURE__*/jsx(Root, {
|
|
85
|
-
children: /*#__PURE__*/jsx(
|
|
86
|
-
children:
|
|
89
|
+
children: /*#__PURE__*/jsx(ActivityBridge, {
|
|
90
|
+
children: /*#__PURE__*/jsx(ContextBridge, {
|
|
91
|
+
children: children
|
|
92
|
+
})
|
|
87
93
|
})
|
|
88
94
|
});
|
|
89
|
-
}, [fiber, ContextBridge]);
|
|
95
|
+
}, [fiber, ContextBridge, ActivityBridge]);
|
|
90
96
|
}
|
|
91
97
|
function Block({
|
|
92
98
|
set
|
|
@@ -232,6 +238,7 @@ function prepare(target, root, type, props) {
|
|
|
232
238
|
object,
|
|
233
239
|
eventCount: 0,
|
|
234
240
|
handlers: {},
|
|
241
|
+
previousVisible: undefined,
|
|
235
242
|
isHidden: false
|
|
236
243
|
};
|
|
237
244
|
if (object) object.__r3f = instance;
|
|
@@ -415,6 +422,12 @@ function applyProps(object, props) {
|
|
|
415
422
|
// Ignore setting undefined props
|
|
416
423
|
// https://github.com/pmndrs/react-three-fiber/issues/274
|
|
417
424
|
if (value === undefined) continue;
|
|
425
|
+
|
|
426
|
+
// Update the visibility to restore without revealing a hidden instance.
|
|
427
|
+
if (prop === 'visible' && instance != null && instance.isHidden && instance.previousVisible !== undefined) {
|
|
428
|
+
instance.previousVisible = value;
|
|
429
|
+
continue;
|
|
430
|
+
}
|
|
418
431
|
let {
|
|
419
432
|
root,
|
|
420
433
|
key,
|
|
@@ -1339,9 +1352,326 @@ useLoader.clear = function (loader, input) {
|
|
|
1339
1352
|
e = 2,
|
|
1340
1353
|
i$1 = 268435456;
|
|
1341
1354
|
|
|
1355
|
+
// Shim for OffscreenCanvas since it was removed from DOM types
|
|
1356
|
+
// https://github.com/DefinitelyTyped/DefinitelyTyped/pull/54988
|
|
1357
|
+
|
|
1358
|
+
/** What a root has applied, so its next configuration applies only what changed */
|
|
1359
|
+
|
|
1360
|
+
const shallow = {
|
|
1361
|
+
objects: 'shallow'
|
|
1362
|
+
};
|
|
1363
|
+
|
|
1364
|
+
/** The renderer to configure, or a promise for one from an async factory */
|
|
1365
|
+
function createRenderer(canvas, gl) {
|
|
1366
|
+
const defaults = {
|
|
1367
|
+
canvas,
|
|
1368
|
+
powerPreference: 'high-performance',
|
|
1369
|
+
antialias: true,
|
|
1370
|
+
alpha: true
|
|
1371
|
+
};
|
|
1372
|
+
if (typeof gl === 'function') return gl(defaults);
|
|
1373
|
+
if (isRenderer(gl)) return gl;
|
|
1374
|
+
return new THREE.WebGLRenderer({
|
|
1375
|
+
...defaults,
|
|
1376
|
+
...gl
|
|
1377
|
+
});
|
|
1378
|
+
}
|
|
1379
|
+
function computeInitialSize(canvas, size) {
|
|
1380
|
+
if (!size && typeof HTMLCanvasElement !== 'undefined' && canvas instanceof HTMLCanvasElement && canvas.parentElement) {
|
|
1381
|
+
const {
|
|
1382
|
+
width,
|
|
1383
|
+
height,
|
|
1384
|
+
top,
|
|
1385
|
+
left
|
|
1386
|
+
} = canvas.parentElement.getBoundingClientRect();
|
|
1387
|
+
return {
|
|
1388
|
+
width,
|
|
1389
|
+
height,
|
|
1390
|
+
top,
|
|
1391
|
+
left
|
|
1392
|
+
};
|
|
1393
|
+
} else if (!size && typeof OffscreenCanvas !== 'undefined' && canvas instanceof OffscreenCanvas) {
|
|
1394
|
+
return {
|
|
1395
|
+
width: canvas.width,
|
|
1396
|
+
height: canvas.height,
|
|
1397
|
+
top: 0,
|
|
1398
|
+
left: 0
|
|
1399
|
+
};
|
|
1400
|
+
}
|
|
1401
|
+
return {
|
|
1402
|
+
width: 0,
|
|
1403
|
+
height: 0,
|
|
1404
|
+
top: 0,
|
|
1405
|
+
left: 0,
|
|
1406
|
+
...size
|
|
1407
|
+
};
|
|
1408
|
+
}
|
|
1409
|
+
|
|
1410
|
+
/**
|
|
1411
|
+
* Applies the inputs that changed since the last configuration applied in full, to a root whose
|
|
1412
|
+
* renderer is installed. A runtime change, such as setFrameloop or an edit to gl.shadowMap, lasts
|
|
1413
|
+
* until its input changes. The pixel ratio instead follows the device on every call. Objects and
|
|
1414
|
+
* arrays compare shallowly, so an equal inline value is unchanged.
|
|
1415
|
+
*/
|
|
1416
|
+
function applyRootConfiguration({
|
|
1417
|
+
store,
|
|
1418
|
+
configuration
|
|
1419
|
+
}, canvas, props) {
|
|
1420
|
+
const {
|
|
1421
|
+
gl: glConfig,
|
|
1422
|
+
scene: sceneOptions,
|
|
1423
|
+
camera: cameraOptions,
|
|
1424
|
+
shadows = false,
|
|
1425
|
+
linear = false,
|
|
1426
|
+
flat = false,
|
|
1427
|
+
legacy = false,
|
|
1428
|
+
frameloop = 'always',
|
|
1429
|
+
dpr = [1, 2],
|
|
1430
|
+
performance,
|
|
1431
|
+
onPointerMissed
|
|
1432
|
+
} = props;
|
|
1433
|
+
const size = computeInitialSize(canvas, props.size);
|
|
1434
|
+
const next = {
|
|
1435
|
+
...props,
|
|
1436
|
+
shadows,
|
|
1437
|
+
linear,
|
|
1438
|
+
flat,
|
|
1439
|
+
legacy,
|
|
1440
|
+
frameloop,
|
|
1441
|
+
size
|
|
1442
|
+
};
|
|
1443
|
+
const state = store.getState();
|
|
1444
|
+
const gl = state.gl;
|
|
1445
|
+
const last = configuration.previous;
|
|
1446
|
+
const changed = key => !last || !is.equ(next[key], last[key], shallow);
|
|
1447
|
+
// A failure can leave inputs partly applied, so the next configuration applies all of them
|
|
1448
|
+
configuration.previous = undefined;
|
|
1449
|
+
|
|
1450
|
+
// Set up raycaster (one time only!)
|
|
1451
|
+
let raycaster = state.raycaster;
|
|
1452
|
+
if (!raycaster) state.set({
|
|
1453
|
+
raycaster: raycaster = new THREE.Raycaster()
|
|
1454
|
+
});
|
|
1455
|
+
if (changed('raycaster')) {
|
|
1456
|
+
var _props$raycaster;
|
|
1457
|
+
const {
|
|
1458
|
+
params,
|
|
1459
|
+
...options
|
|
1460
|
+
} = (_props$raycaster = props.raycaster) != null ? _props$raycaster : {};
|
|
1461
|
+
applyProps(raycaster, {
|
|
1462
|
+
...options,
|
|
1463
|
+
params: {
|
|
1464
|
+
...raycaster.params,
|
|
1465
|
+
...params
|
|
1466
|
+
}
|
|
1467
|
+
});
|
|
1468
|
+
}
|
|
1469
|
+
|
|
1470
|
+
// Create default camera, don't overwrite any user-set state
|
|
1471
|
+
if (!state.camera || state.camera === configuration.camera && changed('camera')) {
|
|
1472
|
+
configuration.camera = cameraOptions;
|
|
1473
|
+
const isCamera = cameraOptions == null ? void 0 : cameraOptions.isCamera;
|
|
1474
|
+
const camera = isCamera ? cameraOptions : props.orthographic ? new THREE.OrthographicCamera(0, 0, 0, 0, 0.1, 1000) : new THREE.PerspectiveCamera(75, 0, 0.1, 1000);
|
|
1475
|
+
if (!isCamera) {
|
|
1476
|
+
camera.position.z = 5;
|
|
1477
|
+
if (cameraOptions) {
|
|
1478
|
+
applyProps(camera, cameraOptions);
|
|
1479
|
+
// Preserve user-defined frustum if possible
|
|
1480
|
+
// https://github.com/pmndrs/react-three-fiber/issues/3160
|
|
1481
|
+
if (!camera.manual) {
|
|
1482
|
+
if ('aspect' in cameraOptions || 'left' in cameraOptions || 'right' in cameraOptions || 'bottom' in cameraOptions || 'top' in cameraOptions) {
|
|
1483
|
+
camera.manual = true;
|
|
1484
|
+
camera.updateProjectionMatrix();
|
|
1485
|
+
}
|
|
1486
|
+
}
|
|
1487
|
+
}
|
|
1488
|
+
// Always look at center by default
|
|
1489
|
+
if (!state.camera && !(cameraOptions != null && cameraOptions.rotation)) camera.lookAt(0, 0, 0);
|
|
1490
|
+
}
|
|
1491
|
+
state.set({
|
|
1492
|
+
camera
|
|
1493
|
+
});
|
|
1494
|
+
|
|
1495
|
+
// Configure raycaster
|
|
1496
|
+
// https://github.com/pmndrs/react-xr/issues/300
|
|
1497
|
+
raycaster.camera = camera;
|
|
1498
|
+
}
|
|
1499
|
+
|
|
1500
|
+
// Set up scene (one time only!)
|
|
1501
|
+
if (!state.scene) {
|
|
1502
|
+
let scene;
|
|
1503
|
+
if (sceneOptions != null && sceneOptions.isScene) {
|
|
1504
|
+
scene = sceneOptions;
|
|
1505
|
+
prepare(scene, store, '', {});
|
|
1506
|
+
} else {
|
|
1507
|
+
scene = new THREE.Scene();
|
|
1508
|
+
prepare(scene, store, '', {});
|
|
1509
|
+
if (sceneOptions) applyProps(scene, sceneOptions);
|
|
1510
|
+
}
|
|
1511
|
+
state.set({
|
|
1512
|
+
scene
|
|
1513
|
+
});
|
|
1514
|
+
}
|
|
1515
|
+
|
|
1516
|
+
// Store events internally
|
|
1517
|
+
if (props.events && !state.events.handlers) state.set({
|
|
1518
|
+
events: props.events(store)
|
|
1519
|
+
});
|
|
1520
|
+
if (changed('size')) state.setSize(size.width, size.height, size.top, size.left);
|
|
1521
|
+
// The ratio follows window.devicePixelRatio, which changes with browser zoom or another display
|
|
1522
|
+
if (state.viewport.dpr !== calculateDpr(dpr)) state.setDpr(dpr);
|
|
1523
|
+
if (changed('frameloop')) state.setFrameloop(frameloop);
|
|
1524
|
+
if (changed('onPointerMissed')) state.set({
|
|
1525
|
+
onPointerMissed
|
|
1526
|
+
});
|
|
1527
|
+
// Performance options merge, so removing them keeps the current settings
|
|
1528
|
+
if (performance && changed('performance')) {
|
|
1529
|
+
state.set(state => ({
|
|
1530
|
+
performance: {
|
|
1531
|
+
...state.performance,
|
|
1532
|
+
...performance
|
|
1533
|
+
}
|
|
1534
|
+
}));
|
|
1535
|
+
}
|
|
1536
|
+
|
|
1537
|
+
// Set up XR (one time only!)
|
|
1538
|
+
if (!state.xr) {
|
|
1539
|
+
var _gl$xr;
|
|
1540
|
+
// Handle frame behavior in WebXR
|
|
1541
|
+
const handleXRFrame = (timestamp, frame) => {
|
|
1542
|
+
const state = store.getState();
|
|
1543
|
+
if (state.frameloop === 'never') return;
|
|
1544
|
+
advance(timestamp, true, state, frame);
|
|
1545
|
+
};
|
|
1546
|
+
|
|
1547
|
+
// Toggle render switching on session
|
|
1548
|
+
const handleSessionChange = () => {
|
|
1549
|
+
const state = store.getState();
|
|
1550
|
+
state.gl.xr.enabled = state.gl.xr.isPresenting;
|
|
1551
|
+
state.gl.xr.setAnimationLoop(state.gl.xr.isPresenting ? handleXRFrame : null);
|
|
1552
|
+
if (!state.gl.xr.isPresenting) invalidate(state);
|
|
1553
|
+
};
|
|
1554
|
+
|
|
1555
|
+
// WebXR session manager
|
|
1556
|
+
const xr = {
|
|
1557
|
+
connect() {
|
|
1558
|
+
const gl = store.getState().gl;
|
|
1559
|
+
gl.xr.addEventListener('sessionstart', handleSessionChange);
|
|
1560
|
+
gl.xr.addEventListener('sessionend', handleSessionChange);
|
|
1561
|
+
},
|
|
1562
|
+
disconnect() {
|
|
1563
|
+
const gl = store.getState().gl;
|
|
1564
|
+
gl.xr.removeEventListener('sessionstart', handleSessionChange);
|
|
1565
|
+
gl.xr.removeEventListener('sessionend', handleSessionChange);
|
|
1566
|
+
}
|
|
1567
|
+
};
|
|
1568
|
+
|
|
1569
|
+
// Subscribe to WebXR session events
|
|
1570
|
+
if (typeof ((_gl$xr = gl.xr) == null ? void 0 : _gl$xr.addEventListener) === 'function') xr.connect();
|
|
1571
|
+
state.set({
|
|
1572
|
+
xr
|
|
1573
|
+
});
|
|
1574
|
+
}
|
|
1575
|
+
|
|
1576
|
+
// Set shadowmap
|
|
1577
|
+
if (gl.shadowMap && changed('shadows')) {
|
|
1578
|
+
const oldEnabled = gl.shadowMap.enabled;
|
|
1579
|
+
const oldType = gl.shadowMap.type;
|
|
1580
|
+
gl.shadowMap.enabled = !!shadows;
|
|
1581
|
+
if (is.boo(shadows)) {
|
|
1582
|
+
gl.shadowMap.type = THREE.PCFSoftShadowMap;
|
|
1583
|
+
} else if (is.str(shadows)) {
|
|
1584
|
+
var _types$shadows;
|
|
1585
|
+
const types = {
|
|
1586
|
+
basic: THREE.BasicShadowMap,
|
|
1587
|
+
percentage: THREE.PCFShadowMap,
|
|
1588
|
+
soft: THREE.PCFSoftShadowMap,
|
|
1589
|
+
variance: THREE.VSMShadowMap
|
|
1590
|
+
};
|
|
1591
|
+
gl.shadowMap.type = (_types$shadows = types[shadows]) != null ? _types$shadows : THREE.PCFSoftShadowMap;
|
|
1592
|
+
} else if (is.obj(shadows)) {
|
|
1593
|
+
Object.assign(gl.shadowMap, shadows);
|
|
1594
|
+
}
|
|
1595
|
+
if (oldEnabled !== gl.shadowMap.enabled || oldType !== gl.shadowMap.type) gl.shadowMap.needsUpdate = true;
|
|
1596
|
+
}
|
|
1597
|
+
|
|
1598
|
+
// Explicit renderer options take precedence over the color shorthands
|
|
1599
|
+
const glProps = glConfig && !is.fun(glConfig) && !isRenderer(glConfig) ? glConfig : undefined;
|
|
1600
|
+
if (changed('legacy')) {
|
|
1601
|
+
THREE.ColorManagement.enabled = !legacy;
|
|
1602
|
+
state.set({
|
|
1603
|
+
legacy
|
|
1604
|
+
});
|
|
1605
|
+
}
|
|
1606
|
+
if (changed('linear')) {
|
|
1607
|
+
if ((glProps == null ? void 0 : glProps.outputColorSpace) === undefined) {
|
|
1608
|
+
gl.outputColorSpace = linear ? THREE.LinearSRGBColorSpace : THREE.SRGBColorSpace;
|
|
1609
|
+
}
|
|
1610
|
+
state.set({
|
|
1611
|
+
linear
|
|
1612
|
+
});
|
|
1613
|
+
}
|
|
1614
|
+
if (changed('flat')) {
|
|
1615
|
+
if ((glProps == null ? void 0 : glProps.toneMapping) === undefined) gl.toneMapping = flat ? THREE.NoToneMapping : THREE.ACESFilmicToneMapping;
|
|
1616
|
+
state.set({
|
|
1617
|
+
flat
|
|
1618
|
+
});
|
|
1619
|
+
}
|
|
1620
|
+
|
|
1621
|
+
// Set gl props
|
|
1622
|
+
if (glProps && changed('gl')) applyProps(gl, glProps);
|
|
1623
|
+
configuration.previous = next;
|
|
1624
|
+
}
|
|
1625
|
+
|
|
1626
|
+
const isPromiseLike = value => typeof (value == null ? void 0 : value.then) === 'function';
|
|
1627
|
+
|
|
1628
|
+
/** A promise tagged with its state, the protocol React's `use` reads */
|
|
1629
|
+
|
|
1630
|
+
const fulfilled = value => Object.assign(Promise.resolve(value), {
|
|
1631
|
+
status: 'fulfilled',
|
|
1632
|
+
value
|
|
1633
|
+
});
|
|
1634
|
+
const rejected = reason => {
|
|
1635
|
+
const promise = Promise.reject(reason);
|
|
1636
|
+
promise.catch(() => {}); // the reason is read from `status`
|
|
1637
|
+
return Object.assign(promise, {
|
|
1638
|
+
status: 'rejected',
|
|
1639
|
+
reason
|
|
1640
|
+
});
|
|
1641
|
+
};
|
|
1642
|
+
|
|
1643
|
+
/** A pending promise, settled once from outside. Its `status` updates the moment it settles */
|
|
1644
|
+
const deferred = () => {
|
|
1645
|
+
let resolve;
|
|
1646
|
+
let reject;
|
|
1647
|
+
const promise = new Promise((yes, no) => {
|
|
1648
|
+
resolve = value => {
|
|
1649
|
+
Object.assign(promise, {
|
|
1650
|
+
status: 'fulfilled',
|
|
1651
|
+
value
|
|
1652
|
+
});
|
|
1653
|
+
yes(value);
|
|
1654
|
+
};
|
|
1655
|
+
reject = reason => {
|
|
1656
|
+
Object.assign(promise, {
|
|
1657
|
+
status: 'rejected',
|
|
1658
|
+
reason
|
|
1659
|
+
});
|
|
1660
|
+
no(reason);
|
|
1661
|
+
};
|
|
1662
|
+
});
|
|
1663
|
+
promise.status = 'pending';
|
|
1664
|
+
promise.catch(() => {}); // the reason is read from `status`
|
|
1665
|
+
return {
|
|
1666
|
+
promise,
|
|
1667
|
+
resolve,
|
|
1668
|
+
reject
|
|
1669
|
+
};
|
|
1670
|
+
};
|
|
1671
|
+
|
|
1342
1672
|
var packageData = {
|
|
1343
1673
|
name: "@react-three/fiber",
|
|
1344
|
-
version: "9.8.
|
|
1674
|
+
version: "9.8.1",
|
|
1345
1675
|
description: "A React renderer for Threejs",
|
|
1346
1676
|
keywords: [
|
|
1347
1677
|
"react",
|
|
@@ -1392,7 +1722,7 @@ var packageData = {
|
|
|
1392
1722
|
"@types/webxr": "*",
|
|
1393
1723
|
"base64-js": "^1.5.1",
|
|
1394
1724
|
buffer: "^6.0.3",
|
|
1395
|
-
"its-fine": "^2.
|
|
1725
|
+
"its-fine": "^2.1.1",
|
|
1396
1726
|
"react-use-measure": "^2.1.7",
|
|
1397
1727
|
scheduler: "^0.28.0",
|
|
1398
1728
|
"suspend-react": "^0.1.3",
|
|
@@ -16170,6 +16500,7 @@ function hideInstance(instance) {
|
|
|
16170
16500
|
if (instance.props.attach && (_instance$parent = instance.parent) != null && _instance$parent.object) {
|
|
16171
16501
|
detach(instance.parent, instance);
|
|
16172
16502
|
} else if (isObject3D(instance.object)) {
|
|
16503
|
+
instance.previousVisible = instance.object.visible;
|
|
16173
16504
|
instance.object.visible = false;
|
|
16174
16505
|
}
|
|
16175
16506
|
instance.isHidden = true;
|
|
@@ -16181,9 +16512,11 @@ function unhideInstance(instance) {
|
|
|
16181
16512
|
var _instance$parent2;
|
|
16182
16513
|
if (instance.props.attach && (_instance$parent2 = instance.parent) != null && _instance$parent2.object) {
|
|
16183
16514
|
attach(instance.parent, instance);
|
|
16184
|
-
} else if (isObject3D(instance.object)
|
|
16185
|
-
|
|
16515
|
+
} else if (isObject3D(instance.object)) {
|
|
16516
|
+
var _instance$previousVis;
|
|
16517
|
+
instance.object.visible = (_instance$previousVis = instance.previousVisible) != null ? _instance$previousVis : true;
|
|
16186
16518
|
}
|
|
16519
|
+
instance.previousVisible = undefined;
|
|
16187
16520
|
instance.isHidden = false;
|
|
16188
16521
|
invalidateInstance(instance);
|
|
16189
16522
|
}
|
|
@@ -16728,76 +17061,49 @@ const reconciler = /* @__PURE__ */createReconciler({
|
|
|
16728
17061
|
getSuspendedCommitReason: (_state, _rootContainer) => null
|
|
16729
17062
|
});
|
|
16730
17063
|
|
|
16731
|
-
|
|
16732
|
-
|
|
16733
|
-
|
|
16734
|
-
|
|
16735
|
-
|
|
16736
|
-
|
|
16737
|
-
|
|
16738
|
-
|
|
16739
|
-
|
|
16740
|
-
|
|
16741
|
-
promise.catch(() => {}); // the reason is read from `status`
|
|
16742
|
-
return Object.assign(promise, {
|
|
16743
|
-
status: 'rejected',
|
|
16744
|
-
reason
|
|
16745
|
-
});
|
|
16746
|
-
};
|
|
16747
|
-
|
|
16748
|
-
/** Tags `promise` in place once it settles. */
|
|
16749
|
-
const tracked = promise => {
|
|
16750
|
-
const result = Promise.resolve(promise);
|
|
16751
|
-
result.status = 'pending';
|
|
16752
|
-
// Statement bodies: returning `result` would make this derived promise adopt its rejection
|
|
16753
|
-
result.then(value => {
|
|
16754
|
-
Object.assign(result, {
|
|
16755
|
-
status: 'fulfilled',
|
|
16756
|
-
value
|
|
16757
|
-
});
|
|
16758
|
-
}, reason => {
|
|
16759
|
-
Object.assign(result, {
|
|
16760
|
-
status: 'rejected',
|
|
16761
|
-
reason
|
|
16762
|
-
});
|
|
16763
|
-
});
|
|
16764
|
-
return result;
|
|
16765
|
-
};
|
|
17064
|
+
/**
|
|
17065
|
+
* Force React to flush any updates inside the provided callback synchronously and immediately.
|
|
17066
|
+
* All the same caveats documented for react-dom's `flushSync` apply here (see https://react.dev/reference/react-dom/flushSync).
|
|
17067
|
+
* Nevertheless, sometimes one needs to render synchronously, for example to keep DOM and 3D changes in lock-step without
|
|
17068
|
+
* having to revert to a non-React solution. Note: this will only flush updates within the `Canvas` root.
|
|
17069
|
+
*/
|
|
17070
|
+
function flushSync(fn) {
|
|
17071
|
+
// @ts-ignore - reconciler types are not maintained
|
|
17072
|
+
return reconciler.flushSyncFromReconciler(fn);
|
|
17073
|
+
}
|
|
16766
17074
|
|
|
16767
17075
|
const _roots = new Map();
|
|
16768
|
-
|
|
16769
|
-
|
|
16770
|
-
|
|
16771
|
-
|
|
16772
|
-
|
|
16773
|
-
|
|
16774
|
-
|
|
16775
|
-
|
|
16776
|
-
|
|
16777
|
-
|
|
16778
|
-
|
|
16779
|
-
|
|
16780
|
-
|
|
16781
|
-
|
|
16782
|
-
|
|
16783
|
-
|
|
16784
|
-
|
|
16785
|
-
|
|
16786
|
-
|
|
16787
|
-
|
|
16788
|
-
|
|
16789
|
-
|
|
16790
|
-
|
|
16791
|
-
|
|
16792
|
-
|
|
17076
|
+
/**
|
|
17077
|
+
* open -> closing -> disposed
|
|
17078
|
+
* | use
|
|
17079
|
+
* v
|
|
17080
|
+
* open
|
|
17081
|
+
*
|
|
17082
|
+
* Only closing can be cancelled. Each unmount carries a token, so only the latest one can dispose.
|
|
17083
|
+
*/
|
|
17084
|
+
function transitionRoot(root, event) {
|
|
17085
|
+
const state = root.state;
|
|
17086
|
+
switch (event.type) {
|
|
17087
|
+
case 'use':
|
|
17088
|
+
if (state.status === 'disposed') return false;
|
|
17089
|
+
root.state = {
|
|
17090
|
+
status: 'open'
|
|
17091
|
+
};
|
|
17092
|
+
return true;
|
|
17093
|
+
case 'unmount':
|
|
17094
|
+
if (state.status === 'disposed') return false;
|
|
17095
|
+
root.state = {
|
|
17096
|
+
status: 'closing',
|
|
17097
|
+
token: event.token
|
|
17098
|
+
};
|
|
17099
|
+
return true;
|
|
17100
|
+
case 'dispose':
|
|
17101
|
+
if (state.status !== 'closing' || state.token !== event.token) return false;
|
|
17102
|
+
root.state = {
|
|
17103
|
+
status: 'disposed'
|
|
17104
|
+
};
|
|
17105
|
+
return true;
|
|
16793
17106
|
}
|
|
16794
|
-
return {
|
|
16795
|
-
width: 0,
|
|
16796
|
-
height: 0,
|
|
16797
|
-
top: 0,
|
|
16798
|
-
left: 0,
|
|
16799
|
-
...size
|
|
16800
|
-
};
|
|
16801
17107
|
}
|
|
16802
17108
|
function createRoot(canvas) {
|
|
16803
17109
|
// Check against mistaken use of createRoot
|
|
@@ -16842,286 +17148,84 @@ function createRoot(canvas) {
|
|
|
16842
17148
|
const root = prevRoot || {
|
|
16843
17149
|
fiber,
|
|
16844
17150
|
store,
|
|
16845
|
-
|
|
16846
|
-
|
|
17151
|
+
state: {
|
|
17152
|
+
status: 'open'
|
|
17153
|
+
},
|
|
17154
|
+
ready: fulfilled(undefined),
|
|
17155
|
+
configuration: {},
|
|
17156
|
+
ownsRenderer: false
|
|
16847
17157
|
};
|
|
16848
17158
|
if (!prevRoot) _roots.set(canvas, root);
|
|
16849
|
-
|
|
16850
|
-
// Locals
|
|
16851
|
-
let onCreated;
|
|
16852
|
-
let lastCamera;
|
|
16853
17159
|
let mounted = false;
|
|
16854
17160
|
return {
|
|
16855
17161
|
get ready() {
|
|
16856
17162
|
return root.ready;
|
|
16857
17163
|
},
|
|
16858
17164
|
configure(props = {}) {
|
|
16859
|
-
root
|
|
16860
|
-
|
|
16861
|
-
|
|
16862
|
-
|
|
16863
|
-
|
|
16864
|
-
events,
|
|
16865
|
-
onCreated: onCreatedCallback,
|
|
16866
|
-
shadows = false,
|
|
16867
|
-
linear = false,
|
|
16868
|
-
flat = false,
|
|
16869
|
-
legacy = false,
|
|
16870
|
-
orthographic = false,
|
|
16871
|
-
frameloop = 'always',
|
|
16872
|
-
dpr = [1, 2],
|
|
16873
|
-
performance,
|
|
16874
|
-
raycaster: raycastOptions,
|
|
16875
|
-
camera: cameraOptions,
|
|
16876
|
-
onPointerMissed
|
|
16877
|
-
} = props;
|
|
16878
|
-
const defaultProps = {
|
|
16879
|
-
canvas: canvas,
|
|
16880
|
-
powerPreference: 'high-performance',
|
|
16881
|
-
antialias: true,
|
|
16882
|
-
alpha: true
|
|
16883
|
-
};
|
|
17165
|
+
if (!transitionRoot(root, {
|
|
17166
|
+
type: 'use'
|
|
17167
|
+
})) {
|
|
17168
|
+
return rejected(new Error('R3F: Cannot configure a root after disposal has started.'));
|
|
17169
|
+
}
|
|
16884
17170
|
|
|
16885
|
-
//
|
|
16886
|
-
const
|
|
17171
|
+
// Configuration applies in call order. Publishing first queues calls made while this one runs
|
|
17172
|
+
const previous = root.ready;
|
|
17173
|
+
const {
|
|
17174
|
+
promise,
|
|
17175
|
+
resolve,
|
|
17176
|
+
reject
|
|
17177
|
+
} = deferred();
|
|
17178
|
+
root.ready = promise;
|
|
17179
|
+
const apply = gl => {
|
|
16887
17180
|
const state = store.getState();
|
|
16888
|
-
|
|
16889
17181
|
// Set up renderer (one time only!)
|
|
16890
|
-
|
|
16891
|
-
|
|
16892
|
-
|
|
16893
|
-
|
|
16894
|
-
...defaultProps,
|
|
16895
|
-
...glConfig
|
|
16896
|
-
});
|
|
16897
|
-
state.set({
|
|
16898
|
-
gl
|
|
16899
|
-
});
|
|
16900
|
-
}
|
|
16901
|
-
|
|
16902
|
-
// Set up raycaster (one time only!)
|
|
16903
|
-
let raycaster = state.raycaster;
|
|
16904
|
-
if (!raycaster) state.set({
|
|
16905
|
-
raycaster: raycaster = new THREE.Raycaster()
|
|
16906
|
-
});
|
|
16907
|
-
|
|
16908
|
-
// Set raycaster options
|
|
16909
|
-
const {
|
|
16910
|
-
params,
|
|
16911
|
-
...options
|
|
16912
|
-
} = raycastOptions || {};
|
|
16913
|
-
if (!is.equ(options, raycaster, shallowLoose)) applyProps(raycaster, {
|
|
16914
|
-
...options
|
|
16915
|
-
});
|
|
16916
|
-
if (!is.equ(params, raycaster.params, shallowLoose)) applyProps(raycaster, {
|
|
16917
|
-
params: {
|
|
16918
|
-
...raycaster.params,
|
|
16919
|
-
...params
|
|
16920
|
-
}
|
|
16921
|
-
});
|
|
16922
|
-
|
|
16923
|
-
// Create default camera, don't overwrite any user-set state
|
|
16924
|
-
if (!state.camera || state.camera === lastCamera && !is.equ(lastCamera, cameraOptions, shallowLoose)) {
|
|
16925
|
-
lastCamera = cameraOptions;
|
|
16926
|
-
const isCamera = cameraOptions == null ? void 0 : cameraOptions.isCamera;
|
|
16927
|
-
const camera = isCamera ? cameraOptions : orthographic ? new THREE.OrthographicCamera(0, 0, 0, 0, 0.1, 1000) : new THREE.PerspectiveCamera(75, 0, 0.1, 1000);
|
|
16928
|
-
if (!isCamera) {
|
|
16929
|
-
camera.position.z = 5;
|
|
16930
|
-
if (cameraOptions) {
|
|
16931
|
-
applyProps(camera, cameraOptions);
|
|
16932
|
-
// Preserve user-defined frustum if possible
|
|
16933
|
-
// https://github.com/pmndrs/react-three-fiber/issues/3160
|
|
16934
|
-
if (!camera.manual) {
|
|
16935
|
-
if ('aspect' in cameraOptions || 'left' in cameraOptions || 'right' in cameraOptions || 'bottom' in cameraOptions || 'top' in cameraOptions) {
|
|
16936
|
-
camera.manual = true;
|
|
16937
|
-
camera.updateProjectionMatrix();
|
|
16938
|
-
}
|
|
16939
|
-
}
|
|
16940
|
-
}
|
|
16941
|
-
// Always look at center by default
|
|
16942
|
-
if (!state.camera && !(cameraOptions != null && cameraOptions.rotation)) camera.lookAt(0, 0, 0);
|
|
16943
|
-
}
|
|
16944
|
-
state.set({
|
|
16945
|
-
camera
|
|
16946
|
-
});
|
|
16947
|
-
|
|
16948
|
-
// Configure raycaster
|
|
16949
|
-
// https://github.com/pmndrs/react-xr/issues/300
|
|
16950
|
-
raycaster.camera = camera;
|
|
16951
|
-
}
|
|
16952
|
-
|
|
16953
|
-
// Set up scene (one time only!)
|
|
16954
|
-
if (!state.scene) {
|
|
16955
|
-
let scene;
|
|
16956
|
-
if (sceneOptions != null && sceneOptions.isScene) {
|
|
16957
|
-
scene = sceneOptions;
|
|
16958
|
-
prepare(scene, store, '', {});
|
|
16959
|
-
} else {
|
|
16960
|
-
scene = new THREE.Scene();
|
|
16961
|
-
prepare(scene, store, '', {});
|
|
16962
|
-
if (sceneOptions) applyProps(scene, sceneOptions);
|
|
16963
|
-
}
|
|
17182
|
+
if (!state.gl) {
|
|
17183
|
+
// R3F owns what it builds, a factory's result included, since it calls the factory
|
|
17184
|
+
// once per root. A renderer instance belongs to the caller
|
|
17185
|
+
root.ownsRenderer = !isRenderer(props.gl);
|
|
16964
17186
|
state.set({
|
|
16965
|
-
|
|
17187
|
+
gl: gl
|
|
16966
17188
|
});
|
|
16967
17189
|
}
|
|
16968
|
-
|
|
16969
|
-
|
|
16970
|
-
if (events && !state.events.handlers) state.set({
|
|
16971
|
-
events: events(store)
|
|
16972
|
-
});
|
|
16973
|
-
// Check size, allow it to take on container bounds initially
|
|
16974
|
-
const size = computeInitialSize(canvas, propsSize);
|
|
16975
|
-
if (!is.equ(size, state.size, shallowLoose)) {
|
|
16976
|
-
state.setSize(size.width, size.height, size.top, size.left);
|
|
16977
|
-
}
|
|
16978
|
-
// Check pixelratio
|
|
16979
|
-
if (dpr && state.viewport.dpr !== calculateDpr(dpr)) state.setDpr(dpr);
|
|
16980
|
-
// Check frameloop
|
|
16981
|
-
if (state.frameloop !== frameloop) state.setFrameloop(frameloop);
|
|
16982
|
-
// Check pointer missed
|
|
16983
|
-
if (!state.onPointerMissed) state.set({
|
|
16984
|
-
onPointerMissed
|
|
16985
|
-
});
|
|
16986
|
-
// Check performance
|
|
16987
|
-
if (performance && !is.equ(performance, state.performance, shallowLoose)) state.set(state => ({
|
|
16988
|
-
performance: {
|
|
16989
|
-
...state.performance,
|
|
16990
|
-
...performance
|
|
16991
|
-
}
|
|
16992
|
-
}));
|
|
16993
|
-
|
|
16994
|
-
// Set up XR (one time only!)
|
|
16995
|
-
if (!state.xr) {
|
|
16996
|
-
var _gl$xr;
|
|
16997
|
-
// Handle frame behavior in WebXR
|
|
16998
|
-
const handleXRFrame = (timestamp, frame) => {
|
|
16999
|
-
const state = store.getState();
|
|
17000
|
-
if (state.frameloop === 'never') return;
|
|
17001
|
-
advance(timestamp, true, state, frame);
|
|
17002
|
-
};
|
|
17003
|
-
|
|
17004
|
-
// Toggle render switching on session
|
|
17005
|
-
const handleSessionChange = () => {
|
|
17006
|
-
const state = store.getState();
|
|
17007
|
-
state.gl.xr.enabled = state.gl.xr.isPresenting;
|
|
17008
|
-
state.gl.xr.setAnimationLoop(state.gl.xr.isPresenting ? handleXRFrame : null);
|
|
17009
|
-
if (!state.gl.xr.isPresenting) invalidate(state);
|
|
17010
|
-
};
|
|
17011
|
-
|
|
17012
|
-
// WebXR session manager
|
|
17013
|
-
const xr = {
|
|
17014
|
-
connect() {
|
|
17015
|
-
const gl = store.getState().gl;
|
|
17016
|
-
gl.xr.addEventListener('sessionstart', handleSessionChange);
|
|
17017
|
-
gl.xr.addEventListener('sessionend', handleSessionChange);
|
|
17018
|
-
},
|
|
17019
|
-
disconnect() {
|
|
17020
|
-
const gl = store.getState().gl;
|
|
17021
|
-
gl.xr.removeEventListener('sessionstart', handleSessionChange);
|
|
17022
|
-
gl.xr.removeEventListener('sessionend', handleSessionChange);
|
|
17023
|
-
}
|
|
17024
|
-
};
|
|
17025
|
-
|
|
17026
|
-
// Subscribe to WebXR session events
|
|
17027
|
-
if (typeof ((_gl$xr = gl.xr) == null ? void 0 : _gl$xr.addEventListener) === 'function') xr.connect();
|
|
17028
|
-
state.set({
|
|
17029
|
-
xr
|
|
17030
|
-
});
|
|
17031
|
-
}
|
|
17032
|
-
|
|
17033
|
-
// Set shadowmap
|
|
17034
|
-
if (gl.shadowMap) {
|
|
17035
|
-
const oldEnabled = gl.shadowMap.enabled;
|
|
17036
|
-
const oldType = gl.shadowMap.type;
|
|
17037
|
-
gl.shadowMap.enabled = !!shadows;
|
|
17038
|
-
if (is.boo(shadows)) {
|
|
17039
|
-
gl.shadowMap.type = THREE.PCFSoftShadowMap;
|
|
17040
|
-
} else if (is.str(shadows)) {
|
|
17041
|
-
var _types$shadows;
|
|
17042
|
-
const types = {
|
|
17043
|
-
basic: THREE.BasicShadowMap,
|
|
17044
|
-
percentage: THREE.PCFShadowMap,
|
|
17045
|
-
soft: THREE.PCFSoftShadowMap,
|
|
17046
|
-
variance: THREE.VSMShadowMap
|
|
17047
|
-
};
|
|
17048
|
-
gl.shadowMap.type = (_types$shadows = types[shadows]) != null ? _types$shadows : THREE.PCFSoftShadowMap;
|
|
17049
|
-
} else if (is.obj(shadows)) {
|
|
17050
|
-
Object.assign(gl.shadowMap, shadows);
|
|
17051
|
-
}
|
|
17052
|
-
if (oldEnabled !== gl.shadowMap.enabled || oldType !== gl.shadowMap.type) gl.shadowMap.needsUpdate = true;
|
|
17053
|
-
}
|
|
17054
|
-
THREE.ColorManagement.enabled = !legacy;
|
|
17055
|
-
|
|
17056
|
-
// Set color space and tonemapping preferences
|
|
17057
|
-
if (first) {
|
|
17058
|
-
gl.outputColorSpace = linear ? THREE.LinearSRGBColorSpace : THREE.SRGBColorSpace;
|
|
17059
|
-
gl.toneMapping = flat ? THREE.NoToneMapping : THREE.ACESFilmicToneMapping;
|
|
17060
|
-
}
|
|
17061
|
-
|
|
17062
|
-
// Update color management state
|
|
17063
|
-
if (state.legacy !== legacy) state.set(() => ({
|
|
17064
|
-
legacy
|
|
17065
|
-
}));
|
|
17066
|
-
if (state.linear !== linear) state.set(() => ({
|
|
17067
|
-
linear
|
|
17068
|
-
}));
|
|
17069
|
-
if (state.flat !== flat) state.set(() => ({
|
|
17070
|
-
flat
|
|
17071
|
-
}));
|
|
17072
|
-
|
|
17073
|
-
// Set gl props
|
|
17074
|
-
if (glConfig && !is.fun(glConfig) && !isRenderer(glConfig) && !is.equ(glConfig, gl, shallowLoose)) applyProps(gl, glConfig);
|
|
17075
|
-
|
|
17076
|
-
// Set locals
|
|
17077
|
-
onCreated = onCreatedCallback;
|
|
17078
|
-
};
|
|
17079
|
-
const fail = error => {
|
|
17080
|
-
const failure = rejected(error);
|
|
17081
|
-
root.ready = failure;
|
|
17082
|
-
return failure;
|
|
17190
|
+
applyRootConfiguration(root, canvas, props);
|
|
17191
|
+
resolve(this);
|
|
17083
17192
|
};
|
|
17084
|
-
const run =
|
|
17193
|
+
const run = () => {
|
|
17085
17194
|
try {
|
|
17086
|
-
|
|
17087
|
-
|
|
17088
|
-
|
|
17195
|
+
var _store$getState$gl;
|
|
17196
|
+
const gl = (_store$getState$gl = store.getState().gl) != null ? _store$getState$gl : createRenderer(canvas, props.gl);
|
|
17197
|
+
// Only an async renderer factory makes configuration asynchronous
|
|
17198
|
+
if (isPromiseLike(gl)) Promise.resolve(gl).then(apply).catch(reject);else apply(gl);
|
|
17089
17199
|
} catch (error) {
|
|
17090
|
-
|
|
17200
|
+
reject(error);
|
|
17091
17201
|
}
|
|
17092
17202
|
};
|
|
17093
|
-
|
|
17094
|
-
|
|
17095
|
-
if (store.getState().gl) return run();
|
|
17096
|
-
|
|
17097
|
-
// Another configure is creating it. Chaining keeps them in call order
|
|
17098
|
-
if (root.ready.status === 'pending') return tracked(root.ready.then(() => run()));
|
|
17099
|
-
|
|
17100
|
-
// Only an async factory makes configure asynchronous
|
|
17101
|
-
let customRenderer;
|
|
17102
|
-
try {
|
|
17103
|
-
customRenderer = typeof glConfig === 'function' ? glConfig(defaultProps) : glConfig;
|
|
17104
|
-
} catch (error) {
|
|
17105
|
-
return fail(error);
|
|
17106
|
-
}
|
|
17107
|
-
if (!isPromiseLike(customRenderer)) return run(customRenderer);
|
|
17108
|
-
const configuring = tracked(customRenderer.then(run, fail));
|
|
17109
|
-
root.ready = configuring;
|
|
17110
|
-
return configuring;
|
|
17203
|
+
if (previous.status === 'pending') previous.then(run, reject);else run();
|
|
17204
|
+
return promise;
|
|
17111
17205
|
},
|
|
17112
17206
|
render(children) {
|
|
17113
|
-
if (
|
|
17114
|
-
|
|
17115
|
-
|
|
17116
|
-
|
|
17117
|
-
|
|
17118
|
-
|
|
17119
|
-
|
|
17120
|
-
rootElement: canvas
|
|
17121
|
-
});
|
|
17207
|
+
if (!transitionRoot(root, {
|
|
17208
|
+
type: 'use'
|
|
17209
|
+
})) return store;
|
|
17210
|
+
|
|
17211
|
+
// The root has to be configured before it can be rendered
|
|
17212
|
+
if (!store.getState().gl && root.ready.status === 'fulfilled') this.configure();
|
|
17213
|
+
if (root.ready.status === 'rejected') throw root.ready.reason;
|
|
17122
17214
|
const commit = () => {
|
|
17123
|
-
|
|
17124
|
-
if (
|
|
17215
|
+
var _root$configuration$p;
|
|
17216
|
+
if (root.state.status !== 'open' || root.ready.status === 'rejected') return;
|
|
17217
|
+
// Wait for all queued configuration, including any queued while waiting
|
|
17218
|
+
if (root.ready.status === 'pending') {
|
|
17219
|
+
root.ready.then(commit, logRecoverableError);
|
|
17220
|
+
return;
|
|
17221
|
+
}
|
|
17222
|
+
const onCreated = (_root$configuration$p = root.configuration.previous) == null ? void 0 : _root$configuration$p.onCreated;
|
|
17223
|
+
const element = /*#__PURE__*/jsx(Provider, {
|
|
17224
|
+
store: store,
|
|
17225
|
+
children: children,
|
|
17226
|
+
onCreated: onCreated,
|
|
17227
|
+
rootElement: canvas
|
|
17228
|
+
});
|
|
17125
17229
|
if (mounted) {
|
|
17126
17230
|
reconciler.updateContainer(element, fiber, null, noop);
|
|
17127
17231
|
return;
|
|
@@ -17133,22 +17237,11 @@ function createRoot(canvas) {
|
|
|
17133
17237
|
// @ts-ignore - reconciler types are not maintained
|
|
17134
17238
|
reconciler.flushSyncWork();
|
|
17135
17239
|
};
|
|
17136
|
-
|
|
17137
|
-
// The root has to be configured before it can be rendered
|
|
17138
|
-
if (!store.getState().gl && root.ready.status === 'fulfilled') this.configure();
|
|
17139
|
-
switch (root.ready.status) {
|
|
17140
|
-
case 'pending':
|
|
17141
|
-
root.ready.then(commit, logRecoverableError);
|
|
17142
|
-
break;
|
|
17143
|
-
case 'rejected':
|
|
17144
|
-
throw root.ready.reason;
|
|
17145
|
-
default:
|
|
17146
|
-
commit();
|
|
17147
|
-
}
|
|
17240
|
+
commit();
|
|
17148
17241
|
return store;
|
|
17149
17242
|
},
|
|
17150
17243
|
unmount() {
|
|
17151
|
-
unmountComponentAtNode(canvas);
|
|
17244
|
+
if (_roots.get(canvas) === root) unmountComponentAtNode(canvas);
|
|
17152
17245
|
}
|
|
17153
17246
|
};
|
|
17154
17247
|
}
|
|
@@ -17179,147 +17272,81 @@ function Provider({
|
|
|
17179
17272
|
children: children
|
|
17180
17273
|
});
|
|
17181
17274
|
}
|
|
17182
|
-
function unmountComponentAtNode(canvas, callback) {
|
|
17183
|
-
const root = _roots.get(canvas);
|
|
17184
|
-
if (!root) return;
|
|
17185
|
-
|
|
17186
|
-
// Cleared by configure and render, which cancels the teardown
|
|
17187
|
-
const claim = root.unmountClaim = Symbol('unmount');
|
|
17188
|
-
reconciler.updateContainer(null, root.fiber, null, () => {
|
|
17189
|
-
if (root.unmountClaim !== claim) return;
|
|
17190
|
-
|
|
17191
|
-
// Effect cleanups flush before the next update
|
|
17192
|
-
reconciler.updateContainer(null, root.fiber, null, () => {
|
|
17193
|
-
if (root.unmountClaim !== claim) return;
|
|
17194
|
-
const teardown = () => {
|
|
17195
|
-
if (root.unmountClaim !== claim) return;
|
|
17196
|
-
root.unmountClaim = null;
|
|
17197
|
-
const state = root.store.getState();
|
|
17198
|
-
state.internal.active = false;
|
|
17199
|
-
try {
|
|
17200
|
-
var _state$gl, _state$gl$renderLists, _state$gl2, _state$gl3;
|
|
17201
|
-
state.events.disconnect == null ? void 0 : state.events.disconnect();
|
|
17202
|
-
(_state$gl = state.gl) == null ? void 0 : (_state$gl$renderLists = _state$gl.renderLists) == null ? void 0 : _state$gl$renderLists.dispose == null ? void 0 : _state$gl$renderLists.dispose();
|
|
17203
|
-
(_state$gl2 = state.gl) == null ? void 0 : _state$gl2.forceContextLoss == null ? void 0 : _state$gl2.forceContextLoss();
|
|
17204
|
-
if ((_state$gl3 = state.gl) != null && _state$gl3.xr) state.xr.disconnect();
|
|
17205
|
-
dispose(state.scene);
|
|
17206
|
-
} catch (e) {
|
|
17207
|
-
/* ... */
|
|
17208
|
-
}
|
|
17209
|
-
_roots.delete(canvas);
|
|
17210
|
-
if (callback) callback(canvas);
|
|
17211
|
-
};
|
|
17212
17275
|
|
|
17213
|
-
|
|
17214
|
-
|
|
17215
|
-
|
|
17276
|
+
/**
|
|
17277
|
+
* Frees a renderer R3F built. WebGLRenderer.dispose() releases programs and caches but keeps its
|
|
17278
|
+
* context until garbage collection, and browsers cap live WebGL contexts, so the context is lost
|
|
17279
|
+
* after it. A WebGPURenderer (from a factory) releases its device and context inside dispose().
|
|
17280
|
+
*/
|
|
17281
|
+
function disposeRenderer(gl) {
|
|
17282
|
+
// Avoid starting initialization through three's dispose(). A factory must await init()
|
|
17283
|
+
// before returning its renderer so readiness includes initialization and teardown can wait.
|
|
17284
|
+
if ((gl.hasInitialized == null ? void 0 : gl.hasInitialized()) === false) return;
|
|
17285
|
+
const disposed = attempt(() => {
|
|
17286
|
+
var _gl$renderLists;
|
|
17287
|
+
return gl.dispose ? gl.dispose() : (_gl$renderLists = gl.renderLists) == null ? void 0 : _gl$renderLists.dispose == null ? void 0 : _gl$renderLists.dispose();
|
|
17216
17288
|
});
|
|
17289
|
+
// WebGPURenderer.dispose() is async from three r186
|
|
17290
|
+
if (isPromiseLike(disposed)) {
|
|
17291
|
+
return Promise.resolve(disposed).catch(error => console.warn('[R3F] Error disposing renderer', error)).then(() => attempt(() => gl.forceContextLoss == null ? void 0 : gl.forceContextLoss()));
|
|
17292
|
+
}
|
|
17293
|
+
attempt(() => gl.forceContextLoss == null ? void 0 : gl.forceContextLoss());
|
|
17217
17294
|
}
|
|
17218
|
-
function
|
|
17219
|
-
|
|
17220
|
-
|
|
17221
|
-
|
|
17222
|
-
|
|
17223
|
-
}
|
|
17295
|
+
function attempt(step) {
|
|
17296
|
+
try {
|
|
17297
|
+
return step();
|
|
17298
|
+
} catch (error) {
|
|
17299
|
+
console.warn('[R3F] Error while unmounting root; teardown may be incomplete:', error);
|
|
17300
|
+
}
|
|
17224
17301
|
}
|
|
17225
|
-
function
|
|
17226
|
-
|
|
17227
|
-
|
|
17228
|
-
|
|
17229
|
-
|
|
17230
|
-
|
|
17231
|
-
|
|
17232
|
-
|
|
17233
|
-
|
|
17234
|
-
|
|
17235
|
-
|
|
17236
|
-
|
|
17237
|
-
|
|
17238
|
-
...rest
|
|
17239
|
-
} = state;
|
|
17240
|
-
const previousRoot = useStore();
|
|
17241
|
-
const [raycaster] = React.useState(() => new THREE.Raycaster());
|
|
17242
|
-
const [pointer] = React.useState(() => new THREE.Vector2());
|
|
17243
|
-
const inject = useMutableCallback((rootState, injectState) => {
|
|
17244
|
-
let viewport = undefined;
|
|
17245
|
-
if (injectState.camera && size) {
|
|
17246
|
-
const camera = injectState.camera;
|
|
17247
|
-
// Calculate the override viewport, if present
|
|
17248
|
-
viewport = rootState.viewport.getCurrentViewport(camera, new THREE.Vector3(), size);
|
|
17249
|
-
// Update the portal camera, if it differs from the previous layer
|
|
17250
|
-
if (camera !== rootState.camera) updateCamera(camera, size);
|
|
17302
|
+
function unmountComponentAtNode(canvas, callback) {
|
|
17303
|
+
const root = _roots.get(canvas);
|
|
17304
|
+
const token = Symbol('unmount');
|
|
17305
|
+
if (!root || !transitionRoot(root, {
|
|
17306
|
+
type: 'unmount',
|
|
17307
|
+
token
|
|
17308
|
+
})) return;
|
|
17309
|
+
const teardown = () => {
|
|
17310
|
+
var _state$gl;
|
|
17311
|
+
// Configuration accepted before the unmount finishes first, so a renderer it creates is released too
|
|
17312
|
+
if (root.ready.status === 'pending') {
|
|
17313
|
+
root.ready.then(teardown, teardown);
|
|
17314
|
+
return;
|
|
17251
17315
|
}
|
|
17252
|
-
|
|
17253
|
-
|
|
17254
|
-
|
|
17255
|
-
|
|
17256
|
-
|
|
17257
|
-
|
|
17258
|
-
|
|
17259
|
-
|
|
17260
|
-
|
|
17261
|
-
// Their previous root is the layer before it
|
|
17262
|
-
previousRoot,
|
|
17263
|
-
// Events, size and viewport can be overridden by the inject layer
|
|
17264
|
-
events: {
|
|
17265
|
-
...rootState.events,
|
|
17266
|
-
...injectState.events,
|
|
17267
|
-
...events
|
|
17268
|
-
},
|
|
17269
|
-
size: {
|
|
17270
|
-
...rootState.size,
|
|
17271
|
-
...size
|
|
17272
|
-
},
|
|
17273
|
-
viewport: {
|
|
17274
|
-
...rootState.viewport,
|
|
17275
|
-
...viewport
|
|
17276
|
-
},
|
|
17277
|
-
// Layers are allowed to override events
|
|
17278
|
-
setEvents: events => injectState.set(state => ({
|
|
17279
|
-
...state,
|
|
17280
|
-
events: {
|
|
17281
|
-
...state.events,
|
|
17282
|
-
...events
|
|
17283
|
-
}
|
|
17284
|
-
}))
|
|
17285
|
-
};
|
|
17286
|
-
});
|
|
17287
|
-
const usePortalStore = React.useMemo(() => {
|
|
17288
|
-
// Create a mirrored store, based on the previous root with a few overrides ...
|
|
17289
|
-
const store = createWithEqualityFn((set, get) => ({
|
|
17290
|
-
...rest,
|
|
17291
|
-
set,
|
|
17292
|
-
get
|
|
17293
|
-
}));
|
|
17294
|
-
|
|
17295
|
-
// Subscribe to previous root-state and copy changes over to the mirrored portal-state
|
|
17296
|
-
const onMutate = prev => store.setState(state => inject.current(prev, state));
|
|
17297
|
-
onMutate(previousRoot.getState());
|
|
17298
|
-
previousRoot.subscribe(onMutate);
|
|
17299
|
-
return store;
|
|
17300
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
17301
|
-
}, [previousRoot, container]);
|
|
17302
|
-
return (
|
|
17303
|
-
/*#__PURE__*/
|
|
17304
|
-
// @ts-ignore, reconciler types are not maintained
|
|
17305
|
-
jsx(Fragment, {
|
|
17306
|
-
children: reconciler.createPortal( /*#__PURE__*/jsx(context.Provider, {
|
|
17307
|
-
value: usePortalStore,
|
|
17308
|
-
children: children
|
|
17309
|
-
}), usePortalStore, null)
|
|
17310
|
-
})
|
|
17311
|
-
);
|
|
17312
|
-
}
|
|
17316
|
+
// Refused when the root was used again since this unmount
|
|
17317
|
+
if (!transitionRoot(root, {
|
|
17318
|
+
type: 'dispose',
|
|
17319
|
+
token
|
|
17320
|
+
})) return;
|
|
17321
|
+
// Close the gates before invoking user cleanup code.
|
|
17322
|
+
_roots.delete(canvas);
|
|
17323
|
+
const state = root.store.getState();
|
|
17324
|
+
state.internal.active = false;
|
|
17313
17325
|
|
|
17314
|
-
|
|
17315
|
-
|
|
17316
|
-
|
|
17317
|
-
|
|
17318
|
-
|
|
17319
|
-
|
|
17320
|
-
|
|
17321
|
-
|
|
17322
|
-
|
|
17326
|
+
// Release what uses the renderer before the renderer itself
|
|
17327
|
+
attempt(() => state.events.disconnect == null ? void 0 : state.events.disconnect());
|
|
17328
|
+
if ((_state$gl = state.gl) != null && _state$gl.xr) attempt(() => state.xr.disconnect());
|
|
17329
|
+
if (state.scene) attempt(() => dispose(state.scene));
|
|
17330
|
+
const gl = state.gl;
|
|
17331
|
+
let disposal = undefined;
|
|
17332
|
+
if (gl && root.ownsRenderer) {
|
|
17333
|
+
disposal = attempt(() => disposeRenderer(gl));
|
|
17334
|
+
} else if (gl) {
|
|
17335
|
+
// A renderer passed in keeps its 9.x teardown: its context is lost but it is not disposed
|
|
17336
|
+
attempt(() => {
|
|
17337
|
+
var _gl$renderLists2;
|
|
17338
|
+
return (_gl$renderLists2 = gl.renderLists) == null ? void 0 : _gl$renderLists2.dispose == null ? void 0 : _gl$renderLists2.dispose();
|
|
17339
|
+
});
|
|
17340
|
+
attempt(() => gl.forceContextLoss == null ? void 0 : gl.forceContextLoss());
|
|
17341
|
+
}
|
|
17342
|
+
if (isPromiseLike(disposal)) disposal.then(() => callback == null ? void 0 : callback(canvas));else callback == null ? void 0 : callback(canvas);
|
|
17343
|
+
};
|
|
17344
|
+
reconciler.updateContainer(null, root.fiber, null, () => {
|
|
17345
|
+
// A root used again since the unmount keeps its new children
|
|
17346
|
+
if (root.state.status !== 'closing' || root.state.token !== token) return;
|
|
17347
|
+
// Effect cleanups flush before the next update
|
|
17348
|
+
reconciler.updateContainer(null, root.fiber, null, teardown);
|
|
17349
|
+
});
|
|
17323
17350
|
}
|
|
17324
17351
|
|
|
17325
17352
|
function createSubs(callback, subs) {
|
|
@@ -17474,6 +17501,102 @@ function advance(timestamp, runGlobalEffects = true, state, frame) {
|
|
|
17474
17501
|
if (runGlobalEffects) flushGlobalEffects('after', timestamp);
|
|
17475
17502
|
}
|
|
17476
17503
|
|
|
17504
|
+
function createPortal(children, container, state) {
|
|
17505
|
+
return /*#__PURE__*/jsx(Portal, {
|
|
17506
|
+
children: children,
|
|
17507
|
+
container: container,
|
|
17508
|
+
state: state
|
|
17509
|
+
});
|
|
17510
|
+
}
|
|
17511
|
+
function Portal({
|
|
17512
|
+
state = {},
|
|
17513
|
+
children,
|
|
17514
|
+
container
|
|
17515
|
+
}) {
|
|
17516
|
+
/** This has to be a component because it would not be able to call useThree/useStore otherwise since
|
|
17517
|
+
* if this is our environment, then we are not in r3f's renderer but in react-dom, it would trigger
|
|
17518
|
+
* the "R3F hooks can only be used within the Canvas component!" warning:
|
|
17519
|
+
* <Canvas>
|
|
17520
|
+
* {createPortal(...)} */
|
|
17521
|
+
const {
|
|
17522
|
+
events,
|
|
17523
|
+
size,
|
|
17524
|
+
...rest
|
|
17525
|
+
} = state;
|
|
17526
|
+
const previousRoot = useStore();
|
|
17527
|
+
const [raycaster] = React.useState(() => new THREE.Raycaster());
|
|
17528
|
+
const [pointer] = React.useState(() => new THREE.Vector2());
|
|
17529
|
+
const inject = useMutableCallback((rootState, injectState) => {
|
|
17530
|
+
let viewport = undefined;
|
|
17531
|
+
if (injectState.camera && size) {
|
|
17532
|
+
const camera = injectState.camera;
|
|
17533
|
+
// Calculate the override viewport, if present
|
|
17534
|
+
viewport = rootState.viewport.getCurrentViewport(camera, new THREE.Vector3(), size);
|
|
17535
|
+
// Update the portal camera, if it differs from the previous layer
|
|
17536
|
+
if (camera !== rootState.camera) updateCamera(camera, size);
|
|
17537
|
+
}
|
|
17538
|
+
return {
|
|
17539
|
+
// The intersect consists of the previous root state
|
|
17540
|
+
...rootState,
|
|
17541
|
+
...injectState,
|
|
17542
|
+
// Portals have their own scene, which forms the root, a raycaster and a pointer
|
|
17543
|
+
scene: container,
|
|
17544
|
+
raycaster,
|
|
17545
|
+
pointer,
|
|
17546
|
+
mouse: pointer,
|
|
17547
|
+
// Their previous root is the layer before it
|
|
17548
|
+
previousRoot,
|
|
17549
|
+
// Events, size and viewport can be overridden by the inject layer
|
|
17550
|
+
events: {
|
|
17551
|
+
...rootState.events,
|
|
17552
|
+
...injectState.events,
|
|
17553
|
+
...events
|
|
17554
|
+
},
|
|
17555
|
+
size: {
|
|
17556
|
+
...rootState.size,
|
|
17557
|
+
...size
|
|
17558
|
+
},
|
|
17559
|
+
viewport: {
|
|
17560
|
+
...rootState.viewport,
|
|
17561
|
+
...viewport
|
|
17562
|
+
},
|
|
17563
|
+
// Layers are allowed to override events
|
|
17564
|
+
setEvents: events => injectState.set(state => ({
|
|
17565
|
+
...state,
|
|
17566
|
+
events: {
|
|
17567
|
+
...state.events,
|
|
17568
|
+
...events
|
|
17569
|
+
}
|
|
17570
|
+
}))
|
|
17571
|
+
};
|
|
17572
|
+
});
|
|
17573
|
+
const usePortalStore = React.useMemo(() => {
|
|
17574
|
+
// Create a mirrored store, based on the previous root with a few overrides ...
|
|
17575
|
+
const store = createWithEqualityFn((set, get) => ({
|
|
17576
|
+
...rest,
|
|
17577
|
+
set,
|
|
17578
|
+
get
|
|
17579
|
+
}));
|
|
17580
|
+
|
|
17581
|
+
// Subscribe to previous root-state and copy changes over to the mirrored portal-state
|
|
17582
|
+
const onMutate = prev => store.setState(state => inject.current(prev, state));
|
|
17583
|
+
onMutate(previousRoot.getState());
|
|
17584
|
+
previousRoot.subscribe(onMutate);
|
|
17585
|
+
return store;
|
|
17586
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
17587
|
+
}, [previousRoot, container]);
|
|
17588
|
+
return (
|
|
17589
|
+
/*#__PURE__*/
|
|
17590
|
+
// @ts-ignore, reconciler types are not maintained
|
|
17591
|
+
jsx(Fragment, {
|
|
17592
|
+
children: reconciler.createPortal( /*#__PURE__*/jsx(context.Provider, {
|
|
17593
|
+
value: usePortalStore,
|
|
17594
|
+
children: children
|
|
17595
|
+
}), usePortalStore, null)
|
|
17596
|
+
})
|
|
17597
|
+
);
|
|
17598
|
+
}
|
|
17599
|
+
|
|
17477
17600
|
const DOM_EVENTS = {
|
|
17478
17601
|
onClick: ['click', false],
|
|
17479
17602
|
onContextMenu: ['contextmenu', false],
|
|
@@ -17560,4 +17683,4 @@ function createPointerEvents(store) {
|
|
|
17560
17683
|
};
|
|
17561
17684
|
}
|
|
17562
17685
|
|
|
17563
|
-
export { useInstanceHandle as A, Block as B, useStore as C, useThree as D, ErrorBoundary as E, useFrame as F, useGraph as G, useLoader as H, _roots as _, useMutableCallback as a, useGate as b, useIsomorphicLayoutEffect as c, createRoot as d, extend as e,
|
|
17686
|
+
export { useInstanceHandle as A, Block as B, useStore as C, useThree as D, ErrorBoundary as E, useFrame as F, useGraph as G, useLoader as H, _roots as _, useMutableCallback as a, useGate as b, useIsomorphicLayoutEffect as c, createRoot as d, extend as e, createPointerEvents as f, createEvents as g, flushGlobalEffects as h, isRef as i, addEffect as j, addAfterEffect as k, addTail as l, invalidate as m, advance as n, flushSync as o, unmountComponentAtNode as p, createPortal as q, reconciler as r, context as s, threeTypes as t, useBridge as u, applyProps as v, getRootState as w, dispose as x, act as y, buildGraph as z };
|