@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
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
var React = require('react');
|
|
4
4
|
var THREE = require('three');
|
|
5
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
5
6
|
var traditional = require('zustand/traditional');
|
|
6
7
|
var suspendReact = require('suspend-react');
|
|
7
8
|
var w1 = require('scheduler');
|
|
8
|
-
var jsxRuntime = require('react/jsx-runtime');
|
|
9
9
|
var itsFine = require('its-fine');
|
|
10
10
|
|
|
11
11
|
function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
|
|
@@ -95,23 +95,29 @@ function useGate() {
|
|
|
95
95
|
}) : null;
|
|
96
96
|
return [gate, waitFor];
|
|
97
97
|
}
|
|
98
|
+
|
|
99
|
+
// Activity is optional on React 19.0/19.1. A computed key also supports strict ESM bundlers.
|
|
100
|
+
const useActivityBridge = React__namespace['Activity' + ''] ? itsFine.useActivityBridge : () => React__namespace.Fragment;
|
|
98
101
|
/**
|
|
99
|
-
* Bridges
|
|
102
|
+
* Bridges Context, StrictMode, and Activity visibility from a primary renderer.
|
|
100
103
|
*/
|
|
101
104
|
function useBridge() {
|
|
102
105
|
const fiber = itsFine.useFiber();
|
|
103
106
|
const ContextBridge = itsFine.useContextBridge();
|
|
107
|
+
const ActivityBridge = useActivityBridge();
|
|
104
108
|
return React__namespace.useMemo(() => ({
|
|
105
109
|
children
|
|
106
110
|
}) => {
|
|
107
111
|
const strict = !!itsFine.traverseFiber(fiber, true, node => node.type === React__namespace.StrictMode);
|
|
108
112
|
const Root = strict ? React__namespace.StrictMode : React__namespace.Fragment;
|
|
109
113
|
return /*#__PURE__*/jsxRuntime.jsx(Root, {
|
|
110
|
-
children: /*#__PURE__*/jsxRuntime.jsx(
|
|
111
|
-
children:
|
|
114
|
+
children: /*#__PURE__*/jsxRuntime.jsx(ActivityBridge, {
|
|
115
|
+
children: /*#__PURE__*/jsxRuntime.jsx(ContextBridge, {
|
|
116
|
+
children: children
|
|
117
|
+
})
|
|
112
118
|
})
|
|
113
119
|
});
|
|
114
|
-
}, [fiber, ContextBridge]);
|
|
120
|
+
}, [fiber, ContextBridge, ActivityBridge]);
|
|
115
121
|
}
|
|
116
122
|
function Block({
|
|
117
123
|
set
|
|
@@ -257,6 +263,7 @@ function prepare(target, root, type, props) {
|
|
|
257
263
|
object,
|
|
258
264
|
eventCount: 0,
|
|
259
265
|
handlers: {},
|
|
266
|
+
previousVisible: undefined,
|
|
260
267
|
isHidden: false
|
|
261
268
|
};
|
|
262
269
|
if (object) object.__r3f = instance;
|
|
@@ -440,6 +447,12 @@ function applyProps(object, props) {
|
|
|
440
447
|
// Ignore setting undefined props
|
|
441
448
|
// https://github.com/pmndrs/react-three-fiber/issues/274
|
|
442
449
|
if (value === undefined) continue;
|
|
450
|
+
|
|
451
|
+
// Update the visibility to restore without revealing a hidden instance.
|
|
452
|
+
if (prop === 'visible' && instance != null && instance.isHidden && instance.previousVisible !== undefined) {
|
|
453
|
+
instance.previousVisible = value;
|
|
454
|
+
continue;
|
|
455
|
+
}
|
|
443
456
|
let {
|
|
444
457
|
root,
|
|
445
458
|
key,
|
|
@@ -1364,9 +1377,326 @@ useLoader.clear = function (loader, input) {
|
|
|
1364
1377
|
e = 2,
|
|
1365
1378
|
i$1 = 268435456;
|
|
1366
1379
|
|
|
1380
|
+
// Shim for OffscreenCanvas since it was removed from DOM types
|
|
1381
|
+
// https://github.com/DefinitelyTyped/DefinitelyTyped/pull/54988
|
|
1382
|
+
|
|
1383
|
+
/** What a root has applied, so its next configuration applies only what changed */
|
|
1384
|
+
|
|
1385
|
+
const shallow = {
|
|
1386
|
+
objects: 'shallow'
|
|
1387
|
+
};
|
|
1388
|
+
|
|
1389
|
+
/** The renderer to configure, or a promise for one from an async factory */
|
|
1390
|
+
function createRenderer(canvas, gl) {
|
|
1391
|
+
const defaults = {
|
|
1392
|
+
canvas,
|
|
1393
|
+
powerPreference: 'high-performance',
|
|
1394
|
+
antialias: true,
|
|
1395
|
+
alpha: true
|
|
1396
|
+
};
|
|
1397
|
+
if (typeof gl === 'function') return gl(defaults);
|
|
1398
|
+
if (isRenderer(gl)) return gl;
|
|
1399
|
+
return new THREE__namespace.WebGLRenderer({
|
|
1400
|
+
...defaults,
|
|
1401
|
+
...gl
|
|
1402
|
+
});
|
|
1403
|
+
}
|
|
1404
|
+
function computeInitialSize(canvas, size) {
|
|
1405
|
+
if (!size && typeof HTMLCanvasElement !== 'undefined' && canvas instanceof HTMLCanvasElement && canvas.parentElement) {
|
|
1406
|
+
const {
|
|
1407
|
+
width,
|
|
1408
|
+
height,
|
|
1409
|
+
top,
|
|
1410
|
+
left
|
|
1411
|
+
} = canvas.parentElement.getBoundingClientRect();
|
|
1412
|
+
return {
|
|
1413
|
+
width,
|
|
1414
|
+
height,
|
|
1415
|
+
top,
|
|
1416
|
+
left
|
|
1417
|
+
};
|
|
1418
|
+
} else if (!size && typeof OffscreenCanvas !== 'undefined' && canvas instanceof OffscreenCanvas) {
|
|
1419
|
+
return {
|
|
1420
|
+
width: canvas.width,
|
|
1421
|
+
height: canvas.height,
|
|
1422
|
+
top: 0,
|
|
1423
|
+
left: 0
|
|
1424
|
+
};
|
|
1425
|
+
}
|
|
1426
|
+
return {
|
|
1427
|
+
width: 0,
|
|
1428
|
+
height: 0,
|
|
1429
|
+
top: 0,
|
|
1430
|
+
left: 0,
|
|
1431
|
+
...size
|
|
1432
|
+
};
|
|
1433
|
+
}
|
|
1434
|
+
|
|
1435
|
+
/**
|
|
1436
|
+
* Applies the inputs that changed since the last configuration applied in full, to a root whose
|
|
1437
|
+
* renderer is installed. A runtime change, such as setFrameloop or an edit to gl.shadowMap, lasts
|
|
1438
|
+
* until its input changes. The pixel ratio instead follows the device on every call. Objects and
|
|
1439
|
+
* arrays compare shallowly, so an equal inline value is unchanged.
|
|
1440
|
+
*/
|
|
1441
|
+
function applyRootConfiguration({
|
|
1442
|
+
store,
|
|
1443
|
+
configuration
|
|
1444
|
+
}, canvas, props) {
|
|
1445
|
+
const {
|
|
1446
|
+
gl: glConfig,
|
|
1447
|
+
scene: sceneOptions,
|
|
1448
|
+
camera: cameraOptions,
|
|
1449
|
+
shadows = false,
|
|
1450
|
+
linear = false,
|
|
1451
|
+
flat = false,
|
|
1452
|
+
legacy = false,
|
|
1453
|
+
frameloop = 'always',
|
|
1454
|
+
dpr = [1, 2],
|
|
1455
|
+
performance,
|
|
1456
|
+
onPointerMissed
|
|
1457
|
+
} = props;
|
|
1458
|
+
const size = computeInitialSize(canvas, props.size);
|
|
1459
|
+
const next = {
|
|
1460
|
+
...props,
|
|
1461
|
+
shadows,
|
|
1462
|
+
linear,
|
|
1463
|
+
flat,
|
|
1464
|
+
legacy,
|
|
1465
|
+
frameloop,
|
|
1466
|
+
size
|
|
1467
|
+
};
|
|
1468
|
+
const state = store.getState();
|
|
1469
|
+
const gl = state.gl;
|
|
1470
|
+
const last = configuration.previous;
|
|
1471
|
+
const changed = key => !last || !is.equ(next[key], last[key], shallow);
|
|
1472
|
+
// A failure can leave inputs partly applied, so the next configuration applies all of them
|
|
1473
|
+
configuration.previous = undefined;
|
|
1474
|
+
|
|
1475
|
+
// Set up raycaster (one time only!)
|
|
1476
|
+
let raycaster = state.raycaster;
|
|
1477
|
+
if (!raycaster) state.set({
|
|
1478
|
+
raycaster: raycaster = new THREE__namespace.Raycaster()
|
|
1479
|
+
});
|
|
1480
|
+
if (changed('raycaster')) {
|
|
1481
|
+
var _props$raycaster;
|
|
1482
|
+
const {
|
|
1483
|
+
params,
|
|
1484
|
+
...options
|
|
1485
|
+
} = (_props$raycaster = props.raycaster) != null ? _props$raycaster : {};
|
|
1486
|
+
applyProps(raycaster, {
|
|
1487
|
+
...options,
|
|
1488
|
+
params: {
|
|
1489
|
+
...raycaster.params,
|
|
1490
|
+
...params
|
|
1491
|
+
}
|
|
1492
|
+
});
|
|
1493
|
+
}
|
|
1494
|
+
|
|
1495
|
+
// Create default camera, don't overwrite any user-set state
|
|
1496
|
+
if (!state.camera || state.camera === configuration.camera && changed('camera')) {
|
|
1497
|
+
configuration.camera = cameraOptions;
|
|
1498
|
+
const isCamera = cameraOptions == null ? void 0 : cameraOptions.isCamera;
|
|
1499
|
+
const camera = isCamera ? cameraOptions : props.orthographic ? new THREE__namespace.OrthographicCamera(0, 0, 0, 0, 0.1, 1000) : new THREE__namespace.PerspectiveCamera(75, 0, 0.1, 1000);
|
|
1500
|
+
if (!isCamera) {
|
|
1501
|
+
camera.position.z = 5;
|
|
1502
|
+
if (cameraOptions) {
|
|
1503
|
+
applyProps(camera, cameraOptions);
|
|
1504
|
+
// Preserve user-defined frustum if possible
|
|
1505
|
+
// https://github.com/pmndrs/react-three-fiber/issues/3160
|
|
1506
|
+
if (!camera.manual) {
|
|
1507
|
+
if ('aspect' in cameraOptions || 'left' in cameraOptions || 'right' in cameraOptions || 'bottom' in cameraOptions || 'top' in cameraOptions) {
|
|
1508
|
+
camera.manual = true;
|
|
1509
|
+
camera.updateProjectionMatrix();
|
|
1510
|
+
}
|
|
1511
|
+
}
|
|
1512
|
+
}
|
|
1513
|
+
// Always look at center by default
|
|
1514
|
+
if (!state.camera && !(cameraOptions != null && cameraOptions.rotation)) camera.lookAt(0, 0, 0);
|
|
1515
|
+
}
|
|
1516
|
+
state.set({
|
|
1517
|
+
camera
|
|
1518
|
+
});
|
|
1519
|
+
|
|
1520
|
+
// Configure raycaster
|
|
1521
|
+
// https://github.com/pmndrs/react-xr/issues/300
|
|
1522
|
+
raycaster.camera = camera;
|
|
1523
|
+
}
|
|
1524
|
+
|
|
1525
|
+
// Set up scene (one time only!)
|
|
1526
|
+
if (!state.scene) {
|
|
1527
|
+
let scene;
|
|
1528
|
+
if (sceneOptions != null && sceneOptions.isScene) {
|
|
1529
|
+
scene = sceneOptions;
|
|
1530
|
+
prepare(scene, store, '', {});
|
|
1531
|
+
} else {
|
|
1532
|
+
scene = new THREE__namespace.Scene();
|
|
1533
|
+
prepare(scene, store, '', {});
|
|
1534
|
+
if (sceneOptions) applyProps(scene, sceneOptions);
|
|
1535
|
+
}
|
|
1536
|
+
state.set({
|
|
1537
|
+
scene
|
|
1538
|
+
});
|
|
1539
|
+
}
|
|
1540
|
+
|
|
1541
|
+
// Store events internally
|
|
1542
|
+
if (props.events && !state.events.handlers) state.set({
|
|
1543
|
+
events: props.events(store)
|
|
1544
|
+
});
|
|
1545
|
+
if (changed('size')) state.setSize(size.width, size.height, size.top, size.left);
|
|
1546
|
+
// The ratio follows window.devicePixelRatio, which changes with browser zoom or another display
|
|
1547
|
+
if (state.viewport.dpr !== calculateDpr(dpr)) state.setDpr(dpr);
|
|
1548
|
+
if (changed('frameloop')) state.setFrameloop(frameloop);
|
|
1549
|
+
if (changed('onPointerMissed')) state.set({
|
|
1550
|
+
onPointerMissed
|
|
1551
|
+
});
|
|
1552
|
+
// Performance options merge, so removing them keeps the current settings
|
|
1553
|
+
if (performance && changed('performance')) {
|
|
1554
|
+
state.set(state => ({
|
|
1555
|
+
performance: {
|
|
1556
|
+
...state.performance,
|
|
1557
|
+
...performance
|
|
1558
|
+
}
|
|
1559
|
+
}));
|
|
1560
|
+
}
|
|
1561
|
+
|
|
1562
|
+
// Set up XR (one time only!)
|
|
1563
|
+
if (!state.xr) {
|
|
1564
|
+
var _gl$xr;
|
|
1565
|
+
// Handle frame behavior in WebXR
|
|
1566
|
+
const handleXRFrame = (timestamp, frame) => {
|
|
1567
|
+
const state = store.getState();
|
|
1568
|
+
if (state.frameloop === 'never') return;
|
|
1569
|
+
advance(timestamp, true, state, frame);
|
|
1570
|
+
};
|
|
1571
|
+
|
|
1572
|
+
// Toggle render switching on session
|
|
1573
|
+
const handleSessionChange = () => {
|
|
1574
|
+
const state = store.getState();
|
|
1575
|
+
state.gl.xr.enabled = state.gl.xr.isPresenting;
|
|
1576
|
+
state.gl.xr.setAnimationLoop(state.gl.xr.isPresenting ? handleXRFrame : null);
|
|
1577
|
+
if (!state.gl.xr.isPresenting) invalidate(state);
|
|
1578
|
+
};
|
|
1579
|
+
|
|
1580
|
+
// WebXR session manager
|
|
1581
|
+
const xr = {
|
|
1582
|
+
connect() {
|
|
1583
|
+
const gl = store.getState().gl;
|
|
1584
|
+
gl.xr.addEventListener('sessionstart', handleSessionChange);
|
|
1585
|
+
gl.xr.addEventListener('sessionend', handleSessionChange);
|
|
1586
|
+
},
|
|
1587
|
+
disconnect() {
|
|
1588
|
+
const gl = store.getState().gl;
|
|
1589
|
+
gl.xr.removeEventListener('sessionstart', handleSessionChange);
|
|
1590
|
+
gl.xr.removeEventListener('sessionend', handleSessionChange);
|
|
1591
|
+
}
|
|
1592
|
+
};
|
|
1593
|
+
|
|
1594
|
+
// Subscribe to WebXR session events
|
|
1595
|
+
if (typeof ((_gl$xr = gl.xr) == null ? void 0 : _gl$xr.addEventListener) === 'function') xr.connect();
|
|
1596
|
+
state.set({
|
|
1597
|
+
xr
|
|
1598
|
+
});
|
|
1599
|
+
}
|
|
1600
|
+
|
|
1601
|
+
// Set shadowmap
|
|
1602
|
+
if (gl.shadowMap && changed('shadows')) {
|
|
1603
|
+
const oldEnabled = gl.shadowMap.enabled;
|
|
1604
|
+
const oldType = gl.shadowMap.type;
|
|
1605
|
+
gl.shadowMap.enabled = !!shadows;
|
|
1606
|
+
if (is.boo(shadows)) {
|
|
1607
|
+
gl.shadowMap.type = THREE__namespace.PCFSoftShadowMap;
|
|
1608
|
+
} else if (is.str(shadows)) {
|
|
1609
|
+
var _types$shadows;
|
|
1610
|
+
const types = {
|
|
1611
|
+
basic: THREE__namespace.BasicShadowMap,
|
|
1612
|
+
percentage: THREE__namespace.PCFShadowMap,
|
|
1613
|
+
soft: THREE__namespace.PCFSoftShadowMap,
|
|
1614
|
+
variance: THREE__namespace.VSMShadowMap
|
|
1615
|
+
};
|
|
1616
|
+
gl.shadowMap.type = (_types$shadows = types[shadows]) != null ? _types$shadows : THREE__namespace.PCFSoftShadowMap;
|
|
1617
|
+
} else if (is.obj(shadows)) {
|
|
1618
|
+
Object.assign(gl.shadowMap, shadows);
|
|
1619
|
+
}
|
|
1620
|
+
if (oldEnabled !== gl.shadowMap.enabled || oldType !== gl.shadowMap.type) gl.shadowMap.needsUpdate = true;
|
|
1621
|
+
}
|
|
1622
|
+
|
|
1623
|
+
// Explicit renderer options take precedence over the color shorthands
|
|
1624
|
+
const glProps = glConfig && !is.fun(glConfig) && !isRenderer(glConfig) ? glConfig : undefined;
|
|
1625
|
+
if (changed('legacy')) {
|
|
1626
|
+
THREE__namespace.ColorManagement.enabled = !legacy;
|
|
1627
|
+
state.set({
|
|
1628
|
+
legacy
|
|
1629
|
+
});
|
|
1630
|
+
}
|
|
1631
|
+
if (changed('linear')) {
|
|
1632
|
+
if ((glProps == null ? void 0 : glProps.outputColorSpace) === undefined) {
|
|
1633
|
+
gl.outputColorSpace = linear ? THREE__namespace.LinearSRGBColorSpace : THREE__namespace.SRGBColorSpace;
|
|
1634
|
+
}
|
|
1635
|
+
state.set({
|
|
1636
|
+
linear
|
|
1637
|
+
});
|
|
1638
|
+
}
|
|
1639
|
+
if (changed('flat')) {
|
|
1640
|
+
if ((glProps == null ? void 0 : glProps.toneMapping) === undefined) gl.toneMapping = flat ? THREE__namespace.NoToneMapping : THREE__namespace.ACESFilmicToneMapping;
|
|
1641
|
+
state.set({
|
|
1642
|
+
flat
|
|
1643
|
+
});
|
|
1644
|
+
}
|
|
1645
|
+
|
|
1646
|
+
// Set gl props
|
|
1647
|
+
if (glProps && changed('gl')) applyProps(gl, glProps);
|
|
1648
|
+
configuration.previous = next;
|
|
1649
|
+
}
|
|
1650
|
+
|
|
1651
|
+
const isPromiseLike = value => typeof (value == null ? void 0 : value.then) === 'function';
|
|
1652
|
+
|
|
1653
|
+
/** A promise tagged with its state, the protocol React's `use` reads */
|
|
1654
|
+
|
|
1655
|
+
const fulfilled = value => Object.assign(Promise.resolve(value), {
|
|
1656
|
+
status: 'fulfilled',
|
|
1657
|
+
value
|
|
1658
|
+
});
|
|
1659
|
+
const rejected = reason => {
|
|
1660
|
+
const promise = Promise.reject(reason);
|
|
1661
|
+
promise.catch(() => {}); // the reason is read from `status`
|
|
1662
|
+
return Object.assign(promise, {
|
|
1663
|
+
status: 'rejected',
|
|
1664
|
+
reason
|
|
1665
|
+
});
|
|
1666
|
+
};
|
|
1667
|
+
|
|
1668
|
+
/** A pending promise, settled once from outside. Its `status` updates the moment it settles */
|
|
1669
|
+
const deferred = () => {
|
|
1670
|
+
let resolve;
|
|
1671
|
+
let reject;
|
|
1672
|
+
const promise = new Promise((yes, no) => {
|
|
1673
|
+
resolve = value => {
|
|
1674
|
+
Object.assign(promise, {
|
|
1675
|
+
status: 'fulfilled',
|
|
1676
|
+
value
|
|
1677
|
+
});
|
|
1678
|
+
yes(value);
|
|
1679
|
+
};
|
|
1680
|
+
reject = reason => {
|
|
1681
|
+
Object.assign(promise, {
|
|
1682
|
+
status: 'rejected',
|
|
1683
|
+
reason
|
|
1684
|
+
});
|
|
1685
|
+
no(reason);
|
|
1686
|
+
};
|
|
1687
|
+
});
|
|
1688
|
+
promise.status = 'pending';
|
|
1689
|
+
promise.catch(() => {}); // the reason is read from `status`
|
|
1690
|
+
return {
|
|
1691
|
+
promise,
|
|
1692
|
+
resolve,
|
|
1693
|
+
reject
|
|
1694
|
+
};
|
|
1695
|
+
};
|
|
1696
|
+
|
|
1367
1697
|
var packageData = {
|
|
1368
1698
|
name: "@react-three/fiber",
|
|
1369
|
-
version: "9.8.
|
|
1699
|
+
version: "9.8.1",
|
|
1370
1700
|
description: "A React renderer for Threejs",
|
|
1371
1701
|
keywords: [
|
|
1372
1702
|
"react",
|
|
@@ -1417,7 +1747,7 @@ var packageData = {
|
|
|
1417
1747
|
"@types/webxr": "*",
|
|
1418
1748
|
"base64-js": "^1.5.1",
|
|
1419
1749
|
buffer: "^6.0.3",
|
|
1420
|
-
"its-fine": "^2.
|
|
1750
|
+
"its-fine": "^2.1.1",
|
|
1421
1751
|
"react-use-measure": "^2.1.7",
|
|
1422
1752
|
scheduler: "^0.28.0",
|
|
1423
1753
|
"suspend-react": "^0.1.3",
|
|
@@ -16195,6 +16525,7 @@ function hideInstance(instance) {
|
|
|
16195
16525
|
if (instance.props.attach && (_instance$parent = instance.parent) != null && _instance$parent.object) {
|
|
16196
16526
|
detach(instance.parent, instance);
|
|
16197
16527
|
} else if (isObject3D(instance.object)) {
|
|
16528
|
+
instance.previousVisible = instance.object.visible;
|
|
16198
16529
|
instance.object.visible = false;
|
|
16199
16530
|
}
|
|
16200
16531
|
instance.isHidden = true;
|
|
@@ -16206,9 +16537,11 @@ function unhideInstance(instance) {
|
|
|
16206
16537
|
var _instance$parent2;
|
|
16207
16538
|
if (instance.props.attach && (_instance$parent2 = instance.parent) != null && _instance$parent2.object) {
|
|
16208
16539
|
attach(instance.parent, instance);
|
|
16209
|
-
} else if (isObject3D(instance.object)
|
|
16210
|
-
|
|
16540
|
+
} else if (isObject3D(instance.object)) {
|
|
16541
|
+
var _instance$previousVis;
|
|
16542
|
+
instance.object.visible = (_instance$previousVis = instance.previousVisible) != null ? _instance$previousVis : true;
|
|
16211
16543
|
}
|
|
16544
|
+
instance.previousVisible = undefined;
|
|
16212
16545
|
instance.isHidden = false;
|
|
16213
16546
|
invalidateInstance(instance);
|
|
16214
16547
|
}
|
|
@@ -16753,76 +17086,49 @@ const reconciler = /* @__PURE__ */createReconciler({
|
|
|
16753
17086
|
getSuspendedCommitReason: (_state, _rootContainer) => null
|
|
16754
17087
|
});
|
|
16755
17088
|
|
|
16756
|
-
|
|
16757
|
-
|
|
16758
|
-
|
|
16759
|
-
|
|
16760
|
-
|
|
16761
|
-
|
|
16762
|
-
|
|
16763
|
-
|
|
16764
|
-
|
|
16765
|
-
|
|
16766
|
-
promise.catch(() => {}); // the reason is read from `status`
|
|
16767
|
-
return Object.assign(promise, {
|
|
16768
|
-
status: 'rejected',
|
|
16769
|
-
reason
|
|
16770
|
-
});
|
|
16771
|
-
};
|
|
16772
|
-
|
|
16773
|
-
/** Tags `promise` in place once it settles. */
|
|
16774
|
-
const tracked = promise => {
|
|
16775
|
-
const result = Promise.resolve(promise);
|
|
16776
|
-
result.status = 'pending';
|
|
16777
|
-
// Statement bodies: returning `result` would make this derived promise adopt its rejection
|
|
16778
|
-
result.then(value => {
|
|
16779
|
-
Object.assign(result, {
|
|
16780
|
-
status: 'fulfilled',
|
|
16781
|
-
value
|
|
16782
|
-
});
|
|
16783
|
-
}, reason => {
|
|
16784
|
-
Object.assign(result, {
|
|
16785
|
-
status: 'rejected',
|
|
16786
|
-
reason
|
|
16787
|
-
});
|
|
16788
|
-
});
|
|
16789
|
-
return result;
|
|
16790
|
-
};
|
|
17089
|
+
/**
|
|
17090
|
+
* Force React to flush any updates inside the provided callback synchronously and immediately.
|
|
17091
|
+
* All the same caveats documented for react-dom's `flushSync` apply here (see https://react.dev/reference/react-dom/flushSync).
|
|
17092
|
+
* Nevertheless, sometimes one needs to render synchronously, for example to keep DOM and 3D changes in lock-step without
|
|
17093
|
+
* having to revert to a non-React solution. Note: this will only flush updates within the `Canvas` root.
|
|
17094
|
+
*/
|
|
17095
|
+
function flushSync(fn) {
|
|
17096
|
+
// @ts-ignore - reconciler types are not maintained
|
|
17097
|
+
return reconciler.flushSyncFromReconciler(fn);
|
|
17098
|
+
}
|
|
16791
17099
|
|
|
16792
17100
|
const _roots = new Map();
|
|
16793
|
-
|
|
16794
|
-
|
|
16795
|
-
|
|
16796
|
-
|
|
16797
|
-
|
|
16798
|
-
|
|
16799
|
-
|
|
16800
|
-
|
|
16801
|
-
|
|
16802
|
-
|
|
16803
|
-
|
|
16804
|
-
|
|
16805
|
-
|
|
16806
|
-
|
|
16807
|
-
|
|
16808
|
-
|
|
16809
|
-
|
|
16810
|
-
|
|
16811
|
-
|
|
16812
|
-
|
|
16813
|
-
|
|
16814
|
-
|
|
16815
|
-
|
|
16816
|
-
|
|
16817
|
-
|
|
17101
|
+
/**
|
|
17102
|
+
* open -> closing -> disposed
|
|
17103
|
+
* | use
|
|
17104
|
+
* v
|
|
17105
|
+
* open
|
|
17106
|
+
*
|
|
17107
|
+
* Only closing can be cancelled. Each unmount carries a token, so only the latest one can dispose.
|
|
17108
|
+
*/
|
|
17109
|
+
function transitionRoot(root, event) {
|
|
17110
|
+
const state = root.state;
|
|
17111
|
+
switch (event.type) {
|
|
17112
|
+
case 'use':
|
|
17113
|
+
if (state.status === 'disposed') return false;
|
|
17114
|
+
root.state = {
|
|
17115
|
+
status: 'open'
|
|
17116
|
+
};
|
|
17117
|
+
return true;
|
|
17118
|
+
case 'unmount':
|
|
17119
|
+
if (state.status === 'disposed') return false;
|
|
17120
|
+
root.state = {
|
|
17121
|
+
status: 'closing',
|
|
17122
|
+
token: event.token
|
|
17123
|
+
};
|
|
17124
|
+
return true;
|
|
17125
|
+
case 'dispose':
|
|
17126
|
+
if (state.status !== 'closing' || state.token !== event.token) return false;
|
|
17127
|
+
root.state = {
|
|
17128
|
+
status: 'disposed'
|
|
17129
|
+
};
|
|
17130
|
+
return true;
|
|
16818
17131
|
}
|
|
16819
|
-
return {
|
|
16820
|
-
width: 0,
|
|
16821
|
-
height: 0,
|
|
16822
|
-
top: 0,
|
|
16823
|
-
left: 0,
|
|
16824
|
-
...size
|
|
16825
|
-
};
|
|
16826
17132
|
}
|
|
16827
17133
|
function createRoot(canvas) {
|
|
16828
17134
|
// Check against mistaken use of createRoot
|
|
@@ -16867,286 +17173,84 @@ function createRoot(canvas) {
|
|
|
16867
17173
|
const root = prevRoot || {
|
|
16868
17174
|
fiber,
|
|
16869
17175
|
store,
|
|
16870
|
-
|
|
16871
|
-
|
|
17176
|
+
state: {
|
|
17177
|
+
status: 'open'
|
|
17178
|
+
},
|
|
17179
|
+
ready: fulfilled(undefined),
|
|
17180
|
+
configuration: {},
|
|
17181
|
+
ownsRenderer: false
|
|
16872
17182
|
};
|
|
16873
17183
|
if (!prevRoot) _roots.set(canvas, root);
|
|
16874
|
-
|
|
16875
|
-
// Locals
|
|
16876
|
-
let onCreated;
|
|
16877
|
-
let lastCamera;
|
|
16878
17184
|
let mounted = false;
|
|
16879
17185
|
return {
|
|
16880
17186
|
get ready() {
|
|
16881
17187
|
return root.ready;
|
|
16882
17188
|
},
|
|
16883
17189
|
configure(props = {}) {
|
|
16884
|
-
root
|
|
16885
|
-
|
|
16886
|
-
|
|
16887
|
-
|
|
16888
|
-
|
|
16889
|
-
events,
|
|
16890
|
-
onCreated: onCreatedCallback,
|
|
16891
|
-
shadows = false,
|
|
16892
|
-
linear = false,
|
|
16893
|
-
flat = false,
|
|
16894
|
-
legacy = false,
|
|
16895
|
-
orthographic = false,
|
|
16896
|
-
frameloop = 'always',
|
|
16897
|
-
dpr = [1, 2],
|
|
16898
|
-
performance,
|
|
16899
|
-
raycaster: raycastOptions,
|
|
16900
|
-
camera: cameraOptions,
|
|
16901
|
-
onPointerMissed
|
|
16902
|
-
} = props;
|
|
16903
|
-
const defaultProps = {
|
|
16904
|
-
canvas: canvas,
|
|
16905
|
-
powerPreference: 'high-performance',
|
|
16906
|
-
antialias: true,
|
|
16907
|
-
alpha: true
|
|
16908
|
-
};
|
|
17190
|
+
if (!transitionRoot(root, {
|
|
17191
|
+
type: 'use'
|
|
17192
|
+
})) {
|
|
17193
|
+
return rejected(new Error('R3F: Cannot configure a root after disposal has started.'));
|
|
17194
|
+
}
|
|
16909
17195
|
|
|
16910
|
-
//
|
|
16911
|
-
const
|
|
17196
|
+
// Configuration applies in call order. Publishing first queues calls made while this one runs
|
|
17197
|
+
const previous = root.ready;
|
|
17198
|
+
const {
|
|
17199
|
+
promise,
|
|
17200
|
+
resolve,
|
|
17201
|
+
reject
|
|
17202
|
+
} = deferred();
|
|
17203
|
+
root.ready = promise;
|
|
17204
|
+
const apply = gl => {
|
|
16912
17205
|
const state = store.getState();
|
|
16913
|
-
|
|
16914
17206
|
// Set up renderer (one time only!)
|
|
16915
|
-
|
|
16916
|
-
|
|
16917
|
-
|
|
16918
|
-
|
|
16919
|
-
...defaultProps,
|
|
16920
|
-
...glConfig
|
|
16921
|
-
});
|
|
16922
|
-
state.set({
|
|
16923
|
-
gl
|
|
16924
|
-
});
|
|
16925
|
-
}
|
|
16926
|
-
|
|
16927
|
-
// Set up raycaster (one time only!)
|
|
16928
|
-
let raycaster = state.raycaster;
|
|
16929
|
-
if (!raycaster) state.set({
|
|
16930
|
-
raycaster: raycaster = new THREE__namespace.Raycaster()
|
|
16931
|
-
});
|
|
16932
|
-
|
|
16933
|
-
// Set raycaster options
|
|
16934
|
-
const {
|
|
16935
|
-
params,
|
|
16936
|
-
...options
|
|
16937
|
-
} = raycastOptions || {};
|
|
16938
|
-
if (!is.equ(options, raycaster, shallowLoose)) applyProps(raycaster, {
|
|
16939
|
-
...options
|
|
16940
|
-
});
|
|
16941
|
-
if (!is.equ(params, raycaster.params, shallowLoose)) applyProps(raycaster, {
|
|
16942
|
-
params: {
|
|
16943
|
-
...raycaster.params,
|
|
16944
|
-
...params
|
|
16945
|
-
}
|
|
16946
|
-
});
|
|
16947
|
-
|
|
16948
|
-
// Create default camera, don't overwrite any user-set state
|
|
16949
|
-
if (!state.camera || state.camera === lastCamera && !is.equ(lastCamera, cameraOptions, shallowLoose)) {
|
|
16950
|
-
lastCamera = cameraOptions;
|
|
16951
|
-
const isCamera = cameraOptions == null ? void 0 : cameraOptions.isCamera;
|
|
16952
|
-
const camera = isCamera ? cameraOptions : orthographic ? new THREE__namespace.OrthographicCamera(0, 0, 0, 0, 0.1, 1000) : new THREE__namespace.PerspectiveCamera(75, 0, 0.1, 1000);
|
|
16953
|
-
if (!isCamera) {
|
|
16954
|
-
camera.position.z = 5;
|
|
16955
|
-
if (cameraOptions) {
|
|
16956
|
-
applyProps(camera, cameraOptions);
|
|
16957
|
-
// Preserve user-defined frustum if possible
|
|
16958
|
-
// https://github.com/pmndrs/react-three-fiber/issues/3160
|
|
16959
|
-
if (!camera.manual) {
|
|
16960
|
-
if ('aspect' in cameraOptions || 'left' in cameraOptions || 'right' in cameraOptions || 'bottom' in cameraOptions || 'top' in cameraOptions) {
|
|
16961
|
-
camera.manual = true;
|
|
16962
|
-
camera.updateProjectionMatrix();
|
|
16963
|
-
}
|
|
16964
|
-
}
|
|
16965
|
-
}
|
|
16966
|
-
// Always look at center by default
|
|
16967
|
-
if (!state.camera && !(cameraOptions != null && cameraOptions.rotation)) camera.lookAt(0, 0, 0);
|
|
16968
|
-
}
|
|
16969
|
-
state.set({
|
|
16970
|
-
camera
|
|
16971
|
-
});
|
|
16972
|
-
|
|
16973
|
-
// Configure raycaster
|
|
16974
|
-
// https://github.com/pmndrs/react-xr/issues/300
|
|
16975
|
-
raycaster.camera = camera;
|
|
16976
|
-
}
|
|
16977
|
-
|
|
16978
|
-
// Set up scene (one time only!)
|
|
16979
|
-
if (!state.scene) {
|
|
16980
|
-
let scene;
|
|
16981
|
-
if (sceneOptions != null && sceneOptions.isScene) {
|
|
16982
|
-
scene = sceneOptions;
|
|
16983
|
-
prepare(scene, store, '', {});
|
|
16984
|
-
} else {
|
|
16985
|
-
scene = new THREE__namespace.Scene();
|
|
16986
|
-
prepare(scene, store, '', {});
|
|
16987
|
-
if (sceneOptions) applyProps(scene, sceneOptions);
|
|
16988
|
-
}
|
|
17207
|
+
if (!state.gl) {
|
|
17208
|
+
// R3F owns what it builds, a factory's result included, since it calls the factory
|
|
17209
|
+
// once per root. A renderer instance belongs to the caller
|
|
17210
|
+
root.ownsRenderer = !isRenderer(props.gl);
|
|
16989
17211
|
state.set({
|
|
16990
|
-
|
|
17212
|
+
gl: gl
|
|
16991
17213
|
});
|
|
16992
17214
|
}
|
|
16993
|
-
|
|
16994
|
-
|
|
16995
|
-
if (events && !state.events.handlers) state.set({
|
|
16996
|
-
events: events(store)
|
|
16997
|
-
});
|
|
16998
|
-
// Check size, allow it to take on container bounds initially
|
|
16999
|
-
const size = computeInitialSize(canvas, propsSize);
|
|
17000
|
-
if (!is.equ(size, state.size, shallowLoose)) {
|
|
17001
|
-
state.setSize(size.width, size.height, size.top, size.left);
|
|
17002
|
-
}
|
|
17003
|
-
// Check pixelratio
|
|
17004
|
-
if (dpr && state.viewport.dpr !== calculateDpr(dpr)) state.setDpr(dpr);
|
|
17005
|
-
// Check frameloop
|
|
17006
|
-
if (state.frameloop !== frameloop) state.setFrameloop(frameloop);
|
|
17007
|
-
// Check pointer missed
|
|
17008
|
-
if (!state.onPointerMissed) state.set({
|
|
17009
|
-
onPointerMissed
|
|
17010
|
-
});
|
|
17011
|
-
// Check performance
|
|
17012
|
-
if (performance && !is.equ(performance, state.performance, shallowLoose)) state.set(state => ({
|
|
17013
|
-
performance: {
|
|
17014
|
-
...state.performance,
|
|
17015
|
-
...performance
|
|
17016
|
-
}
|
|
17017
|
-
}));
|
|
17018
|
-
|
|
17019
|
-
// Set up XR (one time only!)
|
|
17020
|
-
if (!state.xr) {
|
|
17021
|
-
var _gl$xr;
|
|
17022
|
-
// Handle frame behavior in WebXR
|
|
17023
|
-
const handleXRFrame = (timestamp, frame) => {
|
|
17024
|
-
const state = store.getState();
|
|
17025
|
-
if (state.frameloop === 'never') return;
|
|
17026
|
-
advance(timestamp, true, state, frame);
|
|
17027
|
-
};
|
|
17028
|
-
|
|
17029
|
-
// Toggle render switching on session
|
|
17030
|
-
const handleSessionChange = () => {
|
|
17031
|
-
const state = store.getState();
|
|
17032
|
-
state.gl.xr.enabled = state.gl.xr.isPresenting;
|
|
17033
|
-
state.gl.xr.setAnimationLoop(state.gl.xr.isPresenting ? handleXRFrame : null);
|
|
17034
|
-
if (!state.gl.xr.isPresenting) invalidate(state);
|
|
17035
|
-
};
|
|
17036
|
-
|
|
17037
|
-
// WebXR session manager
|
|
17038
|
-
const xr = {
|
|
17039
|
-
connect() {
|
|
17040
|
-
const gl = store.getState().gl;
|
|
17041
|
-
gl.xr.addEventListener('sessionstart', handleSessionChange);
|
|
17042
|
-
gl.xr.addEventListener('sessionend', handleSessionChange);
|
|
17043
|
-
},
|
|
17044
|
-
disconnect() {
|
|
17045
|
-
const gl = store.getState().gl;
|
|
17046
|
-
gl.xr.removeEventListener('sessionstart', handleSessionChange);
|
|
17047
|
-
gl.xr.removeEventListener('sessionend', handleSessionChange);
|
|
17048
|
-
}
|
|
17049
|
-
};
|
|
17050
|
-
|
|
17051
|
-
// Subscribe to WebXR session events
|
|
17052
|
-
if (typeof ((_gl$xr = gl.xr) == null ? void 0 : _gl$xr.addEventListener) === 'function') xr.connect();
|
|
17053
|
-
state.set({
|
|
17054
|
-
xr
|
|
17055
|
-
});
|
|
17056
|
-
}
|
|
17057
|
-
|
|
17058
|
-
// Set shadowmap
|
|
17059
|
-
if (gl.shadowMap) {
|
|
17060
|
-
const oldEnabled = gl.shadowMap.enabled;
|
|
17061
|
-
const oldType = gl.shadowMap.type;
|
|
17062
|
-
gl.shadowMap.enabled = !!shadows;
|
|
17063
|
-
if (is.boo(shadows)) {
|
|
17064
|
-
gl.shadowMap.type = THREE__namespace.PCFSoftShadowMap;
|
|
17065
|
-
} else if (is.str(shadows)) {
|
|
17066
|
-
var _types$shadows;
|
|
17067
|
-
const types = {
|
|
17068
|
-
basic: THREE__namespace.BasicShadowMap,
|
|
17069
|
-
percentage: THREE__namespace.PCFShadowMap,
|
|
17070
|
-
soft: THREE__namespace.PCFSoftShadowMap,
|
|
17071
|
-
variance: THREE__namespace.VSMShadowMap
|
|
17072
|
-
};
|
|
17073
|
-
gl.shadowMap.type = (_types$shadows = types[shadows]) != null ? _types$shadows : THREE__namespace.PCFSoftShadowMap;
|
|
17074
|
-
} else if (is.obj(shadows)) {
|
|
17075
|
-
Object.assign(gl.shadowMap, shadows);
|
|
17076
|
-
}
|
|
17077
|
-
if (oldEnabled !== gl.shadowMap.enabled || oldType !== gl.shadowMap.type) gl.shadowMap.needsUpdate = true;
|
|
17078
|
-
}
|
|
17079
|
-
THREE__namespace.ColorManagement.enabled = !legacy;
|
|
17080
|
-
|
|
17081
|
-
// Set color space and tonemapping preferences
|
|
17082
|
-
if (first) {
|
|
17083
|
-
gl.outputColorSpace = linear ? THREE__namespace.LinearSRGBColorSpace : THREE__namespace.SRGBColorSpace;
|
|
17084
|
-
gl.toneMapping = flat ? THREE__namespace.NoToneMapping : THREE__namespace.ACESFilmicToneMapping;
|
|
17085
|
-
}
|
|
17086
|
-
|
|
17087
|
-
// Update color management state
|
|
17088
|
-
if (state.legacy !== legacy) state.set(() => ({
|
|
17089
|
-
legacy
|
|
17090
|
-
}));
|
|
17091
|
-
if (state.linear !== linear) state.set(() => ({
|
|
17092
|
-
linear
|
|
17093
|
-
}));
|
|
17094
|
-
if (state.flat !== flat) state.set(() => ({
|
|
17095
|
-
flat
|
|
17096
|
-
}));
|
|
17097
|
-
|
|
17098
|
-
// Set gl props
|
|
17099
|
-
if (glConfig && !is.fun(glConfig) && !isRenderer(glConfig) && !is.equ(glConfig, gl, shallowLoose)) applyProps(gl, glConfig);
|
|
17100
|
-
|
|
17101
|
-
// Set locals
|
|
17102
|
-
onCreated = onCreatedCallback;
|
|
17103
|
-
};
|
|
17104
|
-
const fail = error => {
|
|
17105
|
-
const failure = rejected(error);
|
|
17106
|
-
root.ready = failure;
|
|
17107
|
-
return failure;
|
|
17215
|
+
applyRootConfiguration(root, canvas, props);
|
|
17216
|
+
resolve(this);
|
|
17108
17217
|
};
|
|
17109
|
-
const run =
|
|
17218
|
+
const run = () => {
|
|
17110
17219
|
try {
|
|
17111
|
-
|
|
17112
|
-
|
|
17113
|
-
|
|
17220
|
+
var _store$getState$gl;
|
|
17221
|
+
const gl = (_store$getState$gl = store.getState().gl) != null ? _store$getState$gl : createRenderer(canvas, props.gl);
|
|
17222
|
+
// Only an async renderer factory makes configuration asynchronous
|
|
17223
|
+
if (isPromiseLike(gl)) Promise.resolve(gl).then(apply).catch(reject);else apply(gl);
|
|
17114
17224
|
} catch (error) {
|
|
17115
|
-
|
|
17225
|
+
reject(error);
|
|
17116
17226
|
}
|
|
17117
17227
|
};
|
|
17118
|
-
|
|
17119
|
-
|
|
17120
|
-
if (store.getState().gl) return run();
|
|
17121
|
-
|
|
17122
|
-
// Another configure is creating it. Chaining keeps them in call order
|
|
17123
|
-
if (root.ready.status === 'pending') return tracked(root.ready.then(() => run()));
|
|
17124
|
-
|
|
17125
|
-
// Only an async factory makes configure asynchronous
|
|
17126
|
-
let customRenderer;
|
|
17127
|
-
try {
|
|
17128
|
-
customRenderer = typeof glConfig === 'function' ? glConfig(defaultProps) : glConfig;
|
|
17129
|
-
} catch (error) {
|
|
17130
|
-
return fail(error);
|
|
17131
|
-
}
|
|
17132
|
-
if (!isPromiseLike(customRenderer)) return run(customRenderer);
|
|
17133
|
-
const configuring = tracked(customRenderer.then(run, fail));
|
|
17134
|
-
root.ready = configuring;
|
|
17135
|
-
return configuring;
|
|
17228
|
+
if (previous.status === 'pending') previous.then(run, reject);else run();
|
|
17229
|
+
return promise;
|
|
17136
17230
|
},
|
|
17137
17231
|
render(children) {
|
|
17138
|
-
if (
|
|
17139
|
-
|
|
17140
|
-
|
|
17141
|
-
|
|
17142
|
-
|
|
17143
|
-
|
|
17144
|
-
|
|
17145
|
-
rootElement: canvas
|
|
17146
|
-
});
|
|
17232
|
+
if (!transitionRoot(root, {
|
|
17233
|
+
type: 'use'
|
|
17234
|
+
})) return store;
|
|
17235
|
+
|
|
17236
|
+
// The root has to be configured before it can be rendered
|
|
17237
|
+
if (!store.getState().gl && root.ready.status === 'fulfilled') this.configure();
|
|
17238
|
+
if (root.ready.status === 'rejected') throw root.ready.reason;
|
|
17147
17239
|
const commit = () => {
|
|
17148
|
-
|
|
17149
|
-
if (
|
|
17240
|
+
var _root$configuration$p;
|
|
17241
|
+
if (root.state.status !== 'open' || root.ready.status === 'rejected') return;
|
|
17242
|
+
// Wait for all queued configuration, including any queued while waiting
|
|
17243
|
+
if (root.ready.status === 'pending') {
|
|
17244
|
+
root.ready.then(commit, logRecoverableError);
|
|
17245
|
+
return;
|
|
17246
|
+
}
|
|
17247
|
+
const onCreated = (_root$configuration$p = root.configuration.previous) == null ? void 0 : _root$configuration$p.onCreated;
|
|
17248
|
+
const element = /*#__PURE__*/jsxRuntime.jsx(Provider, {
|
|
17249
|
+
store: store,
|
|
17250
|
+
children: children,
|
|
17251
|
+
onCreated: onCreated,
|
|
17252
|
+
rootElement: canvas
|
|
17253
|
+
});
|
|
17150
17254
|
if (mounted) {
|
|
17151
17255
|
reconciler.updateContainer(element, fiber, null, noop);
|
|
17152
17256
|
return;
|
|
@@ -17158,22 +17262,11 @@ function createRoot(canvas) {
|
|
|
17158
17262
|
// @ts-ignore - reconciler types are not maintained
|
|
17159
17263
|
reconciler.flushSyncWork();
|
|
17160
17264
|
};
|
|
17161
|
-
|
|
17162
|
-
// The root has to be configured before it can be rendered
|
|
17163
|
-
if (!store.getState().gl && root.ready.status === 'fulfilled') this.configure();
|
|
17164
|
-
switch (root.ready.status) {
|
|
17165
|
-
case 'pending':
|
|
17166
|
-
root.ready.then(commit, logRecoverableError);
|
|
17167
|
-
break;
|
|
17168
|
-
case 'rejected':
|
|
17169
|
-
throw root.ready.reason;
|
|
17170
|
-
default:
|
|
17171
|
-
commit();
|
|
17172
|
-
}
|
|
17265
|
+
commit();
|
|
17173
17266
|
return store;
|
|
17174
17267
|
},
|
|
17175
17268
|
unmount() {
|
|
17176
|
-
unmountComponentAtNode(canvas);
|
|
17269
|
+
if (_roots.get(canvas) === root) unmountComponentAtNode(canvas);
|
|
17177
17270
|
}
|
|
17178
17271
|
};
|
|
17179
17272
|
}
|
|
@@ -17204,147 +17297,81 @@ function Provider({
|
|
|
17204
17297
|
children: children
|
|
17205
17298
|
});
|
|
17206
17299
|
}
|
|
17207
|
-
function unmountComponentAtNode(canvas, callback) {
|
|
17208
|
-
const root = _roots.get(canvas);
|
|
17209
|
-
if (!root) return;
|
|
17210
|
-
|
|
17211
|
-
// Cleared by configure and render, which cancels the teardown
|
|
17212
|
-
const claim = root.unmountClaim = Symbol('unmount');
|
|
17213
|
-
reconciler.updateContainer(null, root.fiber, null, () => {
|
|
17214
|
-
if (root.unmountClaim !== claim) return;
|
|
17215
|
-
|
|
17216
|
-
// Effect cleanups flush before the next update
|
|
17217
|
-
reconciler.updateContainer(null, root.fiber, null, () => {
|
|
17218
|
-
if (root.unmountClaim !== claim) return;
|
|
17219
|
-
const teardown = () => {
|
|
17220
|
-
if (root.unmountClaim !== claim) return;
|
|
17221
|
-
root.unmountClaim = null;
|
|
17222
|
-
const state = root.store.getState();
|
|
17223
|
-
state.internal.active = false;
|
|
17224
|
-
try {
|
|
17225
|
-
var _state$gl, _state$gl$renderLists, _state$gl2, _state$gl3;
|
|
17226
|
-
state.events.disconnect == null ? void 0 : state.events.disconnect();
|
|
17227
|
-
(_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();
|
|
17228
|
-
(_state$gl2 = state.gl) == null ? void 0 : _state$gl2.forceContextLoss == null ? void 0 : _state$gl2.forceContextLoss();
|
|
17229
|
-
if ((_state$gl3 = state.gl) != null && _state$gl3.xr) state.xr.disconnect();
|
|
17230
|
-
dispose(state.scene);
|
|
17231
|
-
} catch (e) {
|
|
17232
|
-
/* ... */
|
|
17233
|
-
}
|
|
17234
|
-
_roots.delete(canvas);
|
|
17235
|
-
if (callback) callback(canvas);
|
|
17236
|
-
};
|
|
17237
17300
|
|
|
17238
|
-
|
|
17239
|
-
|
|
17240
|
-
|
|
17301
|
+
/**
|
|
17302
|
+
* Frees a renderer R3F built. WebGLRenderer.dispose() releases programs and caches but keeps its
|
|
17303
|
+
* context until garbage collection, and browsers cap live WebGL contexts, so the context is lost
|
|
17304
|
+
* after it. A WebGPURenderer (from a factory) releases its device and context inside dispose().
|
|
17305
|
+
*/
|
|
17306
|
+
function disposeRenderer(gl) {
|
|
17307
|
+
// Avoid starting initialization through three's dispose(). A factory must await init()
|
|
17308
|
+
// before returning its renderer so readiness includes initialization and teardown can wait.
|
|
17309
|
+
if ((gl.hasInitialized == null ? void 0 : gl.hasInitialized()) === false) return;
|
|
17310
|
+
const disposed = attempt(() => {
|
|
17311
|
+
var _gl$renderLists;
|
|
17312
|
+
return gl.dispose ? gl.dispose() : (_gl$renderLists = gl.renderLists) == null ? void 0 : _gl$renderLists.dispose == null ? void 0 : _gl$renderLists.dispose();
|
|
17241
17313
|
});
|
|
17314
|
+
// WebGPURenderer.dispose() is async from three r186
|
|
17315
|
+
if (isPromiseLike(disposed)) {
|
|
17316
|
+
return Promise.resolve(disposed).catch(error => console.warn('[R3F] Error disposing renderer', error)).then(() => attempt(() => gl.forceContextLoss == null ? void 0 : gl.forceContextLoss()));
|
|
17317
|
+
}
|
|
17318
|
+
attempt(() => gl.forceContextLoss == null ? void 0 : gl.forceContextLoss());
|
|
17242
17319
|
}
|
|
17243
|
-
function
|
|
17244
|
-
|
|
17245
|
-
|
|
17246
|
-
|
|
17247
|
-
|
|
17248
|
-
}
|
|
17320
|
+
function attempt(step) {
|
|
17321
|
+
try {
|
|
17322
|
+
return step();
|
|
17323
|
+
} catch (error) {
|
|
17324
|
+
console.warn('[R3F] Error while unmounting root; teardown may be incomplete:', error);
|
|
17325
|
+
}
|
|
17249
17326
|
}
|
|
17250
|
-
function
|
|
17251
|
-
|
|
17252
|
-
|
|
17253
|
-
|
|
17254
|
-
|
|
17255
|
-
|
|
17256
|
-
|
|
17257
|
-
|
|
17258
|
-
|
|
17259
|
-
|
|
17260
|
-
|
|
17261
|
-
|
|
17262
|
-
|
|
17263
|
-
...rest
|
|
17264
|
-
} = state;
|
|
17265
|
-
const previousRoot = useStore();
|
|
17266
|
-
const [raycaster] = React__namespace.useState(() => new THREE__namespace.Raycaster());
|
|
17267
|
-
const [pointer] = React__namespace.useState(() => new THREE__namespace.Vector2());
|
|
17268
|
-
const inject = useMutableCallback((rootState, injectState) => {
|
|
17269
|
-
let viewport = undefined;
|
|
17270
|
-
if (injectState.camera && size) {
|
|
17271
|
-
const camera = injectState.camera;
|
|
17272
|
-
// Calculate the override viewport, if present
|
|
17273
|
-
viewport = rootState.viewport.getCurrentViewport(camera, new THREE__namespace.Vector3(), size);
|
|
17274
|
-
// Update the portal camera, if it differs from the previous layer
|
|
17275
|
-
if (camera !== rootState.camera) updateCamera(camera, size);
|
|
17327
|
+
function unmountComponentAtNode(canvas, callback) {
|
|
17328
|
+
const root = _roots.get(canvas);
|
|
17329
|
+
const token = Symbol('unmount');
|
|
17330
|
+
if (!root || !transitionRoot(root, {
|
|
17331
|
+
type: 'unmount',
|
|
17332
|
+
token
|
|
17333
|
+
})) return;
|
|
17334
|
+
const teardown = () => {
|
|
17335
|
+
var _state$gl;
|
|
17336
|
+
// Configuration accepted before the unmount finishes first, so a renderer it creates is released too
|
|
17337
|
+
if (root.ready.status === 'pending') {
|
|
17338
|
+
root.ready.then(teardown, teardown);
|
|
17339
|
+
return;
|
|
17276
17340
|
}
|
|
17277
|
-
|
|
17278
|
-
|
|
17279
|
-
|
|
17280
|
-
|
|
17281
|
-
|
|
17282
|
-
|
|
17283
|
-
|
|
17284
|
-
|
|
17285
|
-
|
|
17286
|
-
// Their previous root is the layer before it
|
|
17287
|
-
previousRoot,
|
|
17288
|
-
// Events, size and viewport can be overridden by the inject layer
|
|
17289
|
-
events: {
|
|
17290
|
-
...rootState.events,
|
|
17291
|
-
...injectState.events,
|
|
17292
|
-
...events
|
|
17293
|
-
},
|
|
17294
|
-
size: {
|
|
17295
|
-
...rootState.size,
|
|
17296
|
-
...size
|
|
17297
|
-
},
|
|
17298
|
-
viewport: {
|
|
17299
|
-
...rootState.viewport,
|
|
17300
|
-
...viewport
|
|
17301
|
-
},
|
|
17302
|
-
// Layers are allowed to override events
|
|
17303
|
-
setEvents: events => injectState.set(state => ({
|
|
17304
|
-
...state,
|
|
17305
|
-
events: {
|
|
17306
|
-
...state.events,
|
|
17307
|
-
...events
|
|
17308
|
-
}
|
|
17309
|
-
}))
|
|
17310
|
-
};
|
|
17311
|
-
});
|
|
17312
|
-
const usePortalStore = React__namespace.useMemo(() => {
|
|
17313
|
-
// Create a mirrored store, based on the previous root with a few overrides ...
|
|
17314
|
-
const store = traditional.createWithEqualityFn((set, get) => ({
|
|
17315
|
-
...rest,
|
|
17316
|
-
set,
|
|
17317
|
-
get
|
|
17318
|
-
}));
|
|
17319
|
-
|
|
17320
|
-
// Subscribe to previous root-state and copy changes over to the mirrored portal-state
|
|
17321
|
-
const onMutate = prev => store.setState(state => inject.current(prev, state));
|
|
17322
|
-
onMutate(previousRoot.getState());
|
|
17323
|
-
previousRoot.subscribe(onMutate);
|
|
17324
|
-
return store;
|
|
17325
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
17326
|
-
}, [previousRoot, container]);
|
|
17327
|
-
return (
|
|
17328
|
-
/*#__PURE__*/
|
|
17329
|
-
// @ts-ignore, reconciler types are not maintained
|
|
17330
|
-
jsxRuntime.jsx(jsxRuntime.Fragment, {
|
|
17331
|
-
children: reconciler.createPortal( /*#__PURE__*/jsxRuntime.jsx(context.Provider, {
|
|
17332
|
-
value: usePortalStore,
|
|
17333
|
-
children: children
|
|
17334
|
-
}), usePortalStore, null)
|
|
17335
|
-
})
|
|
17336
|
-
);
|
|
17337
|
-
}
|
|
17341
|
+
// Refused when the root was used again since this unmount
|
|
17342
|
+
if (!transitionRoot(root, {
|
|
17343
|
+
type: 'dispose',
|
|
17344
|
+
token
|
|
17345
|
+
})) return;
|
|
17346
|
+
// Close the gates before invoking user cleanup code.
|
|
17347
|
+
_roots.delete(canvas);
|
|
17348
|
+
const state = root.store.getState();
|
|
17349
|
+
state.internal.active = false;
|
|
17338
17350
|
|
|
17339
|
-
|
|
17340
|
-
|
|
17341
|
-
|
|
17342
|
-
|
|
17343
|
-
|
|
17344
|
-
|
|
17345
|
-
|
|
17346
|
-
|
|
17347
|
-
|
|
17351
|
+
// Release what uses the renderer before the renderer itself
|
|
17352
|
+
attempt(() => state.events.disconnect == null ? void 0 : state.events.disconnect());
|
|
17353
|
+
if ((_state$gl = state.gl) != null && _state$gl.xr) attempt(() => state.xr.disconnect());
|
|
17354
|
+
if (state.scene) attempt(() => dispose(state.scene));
|
|
17355
|
+
const gl = state.gl;
|
|
17356
|
+
let disposal = undefined;
|
|
17357
|
+
if (gl && root.ownsRenderer) {
|
|
17358
|
+
disposal = attempt(() => disposeRenderer(gl));
|
|
17359
|
+
} else if (gl) {
|
|
17360
|
+
// A renderer passed in keeps its 9.x teardown: its context is lost but it is not disposed
|
|
17361
|
+
attempt(() => {
|
|
17362
|
+
var _gl$renderLists2;
|
|
17363
|
+
return (_gl$renderLists2 = gl.renderLists) == null ? void 0 : _gl$renderLists2.dispose == null ? void 0 : _gl$renderLists2.dispose();
|
|
17364
|
+
});
|
|
17365
|
+
attempt(() => gl.forceContextLoss == null ? void 0 : gl.forceContextLoss());
|
|
17366
|
+
}
|
|
17367
|
+
if (isPromiseLike(disposal)) disposal.then(() => callback == null ? void 0 : callback(canvas));else callback == null ? void 0 : callback(canvas);
|
|
17368
|
+
};
|
|
17369
|
+
reconciler.updateContainer(null, root.fiber, null, () => {
|
|
17370
|
+
// A root used again since the unmount keeps its new children
|
|
17371
|
+
if (root.state.status !== 'closing' || root.state.token !== token) return;
|
|
17372
|
+
// Effect cleanups flush before the next update
|
|
17373
|
+
reconciler.updateContainer(null, root.fiber, null, teardown);
|
|
17374
|
+
});
|
|
17348
17375
|
}
|
|
17349
17376
|
|
|
17350
17377
|
function createSubs(callback, subs) {
|
|
@@ -17499,6 +17526,102 @@ function advance(timestamp, runGlobalEffects = true, state, frame) {
|
|
|
17499
17526
|
if (runGlobalEffects) flushGlobalEffects('after', timestamp);
|
|
17500
17527
|
}
|
|
17501
17528
|
|
|
17529
|
+
function createPortal(children, container, state) {
|
|
17530
|
+
return /*#__PURE__*/jsxRuntime.jsx(Portal, {
|
|
17531
|
+
children: children,
|
|
17532
|
+
container: container,
|
|
17533
|
+
state: state
|
|
17534
|
+
});
|
|
17535
|
+
}
|
|
17536
|
+
function Portal({
|
|
17537
|
+
state = {},
|
|
17538
|
+
children,
|
|
17539
|
+
container
|
|
17540
|
+
}) {
|
|
17541
|
+
/** This has to be a component because it would not be able to call useThree/useStore otherwise since
|
|
17542
|
+
* if this is our environment, then we are not in r3f's renderer but in react-dom, it would trigger
|
|
17543
|
+
* the "R3F hooks can only be used within the Canvas component!" warning:
|
|
17544
|
+
* <Canvas>
|
|
17545
|
+
* {createPortal(...)} */
|
|
17546
|
+
const {
|
|
17547
|
+
events,
|
|
17548
|
+
size,
|
|
17549
|
+
...rest
|
|
17550
|
+
} = state;
|
|
17551
|
+
const previousRoot = useStore();
|
|
17552
|
+
const [raycaster] = React__namespace.useState(() => new THREE__namespace.Raycaster());
|
|
17553
|
+
const [pointer] = React__namespace.useState(() => new THREE__namespace.Vector2());
|
|
17554
|
+
const inject = useMutableCallback((rootState, injectState) => {
|
|
17555
|
+
let viewport = undefined;
|
|
17556
|
+
if (injectState.camera && size) {
|
|
17557
|
+
const camera = injectState.camera;
|
|
17558
|
+
// Calculate the override viewport, if present
|
|
17559
|
+
viewport = rootState.viewport.getCurrentViewport(camera, new THREE__namespace.Vector3(), size);
|
|
17560
|
+
// Update the portal camera, if it differs from the previous layer
|
|
17561
|
+
if (camera !== rootState.camera) updateCamera(camera, size);
|
|
17562
|
+
}
|
|
17563
|
+
return {
|
|
17564
|
+
// The intersect consists of the previous root state
|
|
17565
|
+
...rootState,
|
|
17566
|
+
...injectState,
|
|
17567
|
+
// Portals have their own scene, which forms the root, a raycaster and a pointer
|
|
17568
|
+
scene: container,
|
|
17569
|
+
raycaster,
|
|
17570
|
+
pointer,
|
|
17571
|
+
mouse: pointer,
|
|
17572
|
+
// Their previous root is the layer before it
|
|
17573
|
+
previousRoot,
|
|
17574
|
+
// Events, size and viewport can be overridden by the inject layer
|
|
17575
|
+
events: {
|
|
17576
|
+
...rootState.events,
|
|
17577
|
+
...injectState.events,
|
|
17578
|
+
...events
|
|
17579
|
+
},
|
|
17580
|
+
size: {
|
|
17581
|
+
...rootState.size,
|
|
17582
|
+
...size
|
|
17583
|
+
},
|
|
17584
|
+
viewport: {
|
|
17585
|
+
...rootState.viewport,
|
|
17586
|
+
...viewport
|
|
17587
|
+
},
|
|
17588
|
+
// Layers are allowed to override events
|
|
17589
|
+
setEvents: events => injectState.set(state => ({
|
|
17590
|
+
...state,
|
|
17591
|
+
events: {
|
|
17592
|
+
...state.events,
|
|
17593
|
+
...events
|
|
17594
|
+
}
|
|
17595
|
+
}))
|
|
17596
|
+
};
|
|
17597
|
+
});
|
|
17598
|
+
const usePortalStore = React__namespace.useMemo(() => {
|
|
17599
|
+
// Create a mirrored store, based on the previous root with a few overrides ...
|
|
17600
|
+
const store = traditional.createWithEqualityFn((set, get) => ({
|
|
17601
|
+
...rest,
|
|
17602
|
+
set,
|
|
17603
|
+
get
|
|
17604
|
+
}));
|
|
17605
|
+
|
|
17606
|
+
// Subscribe to previous root-state and copy changes over to the mirrored portal-state
|
|
17607
|
+
const onMutate = prev => store.setState(state => inject.current(prev, state));
|
|
17608
|
+
onMutate(previousRoot.getState());
|
|
17609
|
+
previousRoot.subscribe(onMutate);
|
|
17610
|
+
return store;
|
|
17611
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
17612
|
+
}, [previousRoot, container]);
|
|
17613
|
+
return (
|
|
17614
|
+
/*#__PURE__*/
|
|
17615
|
+
// @ts-ignore, reconciler types are not maintained
|
|
17616
|
+
jsxRuntime.jsx(jsxRuntime.Fragment, {
|
|
17617
|
+
children: reconciler.createPortal( /*#__PURE__*/jsxRuntime.jsx(context.Provider, {
|
|
17618
|
+
value: usePortalStore,
|
|
17619
|
+
children: children
|
|
17620
|
+
}), usePortalStore, null)
|
|
17621
|
+
})
|
|
17622
|
+
);
|
|
17623
|
+
}
|
|
17624
|
+
|
|
17502
17625
|
const DOM_EVENTS = {
|
|
17503
17626
|
onClick: ['click', false],
|
|
17504
17627
|
onContextMenu: ['contextmenu', false],
|