@react-three/fiber 8.0.0-beta.0 → 8.0.0-beta.3

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.
@@ -41,29 +41,38 @@ const pick = (obj, keys) => filterKeys(obj, false, ...keys);
41
41
  * Clones an object and prunes or omits keys.
42
42
  */
43
43
 
44
- const omit = (obj, keys) => filterKeys(obj, true, ...keys); // A collection of compare functions
45
-
44
+ const omit = (obj, keys) => filterKeys(obj, true, ...keys);
45
+ // A collection of compare functions
46
46
  const is = {
47
47
  obj: a => a === Object(a) && !is.arr(a) && typeof a !== 'function',
48
48
  fun: a => typeof a === 'function',
49
49
  str: a => typeof a === 'string',
50
50
  num: a => typeof a === 'number',
51
+ boo: a => typeof a === 'boolean',
51
52
  und: a => a === void 0,
52
53
  arr: a => Array.isArray(a),
53
54
 
54
- equ(a, b) {
55
+ equ(a, b, {
56
+ arrays = 'shallow',
57
+ objects = 'reference',
58
+ strict = true
59
+ } = {}) {
55
60
  // Wrong type or one of the two undefined, doesn't match
56
61
  if (typeof a !== typeof b || !!a !== !!b) return false; // Atomic, just compare a against b
57
62
 
58
- if (is.str(a) || is.num(a) || is.obj(a)) return a === b; // Array, shallow compare first to see if it's a match
63
+ if (is.str(a) || is.num(a)) return a === b;
64
+ const isObj = is.obj(a);
65
+ if (isObj && objects === 'reference') return a === b;
66
+ const isArr = is.arr(a);
67
+ if (isArr && arrays === 'reference') return a === b; // Array or Object, shallow compare first to see if it's a match
59
68
 
60
- if (is.arr(a) && a == b) return true; // Last resort, go through keys
69
+ if ((isArr || isObj) && a == b) return true; // Last resort, go through keys
61
70
 
62
71
  let i;
63
72
 
64
73
  for (i in a) if (!(i in b)) return false;
65
74
 
66
- for (i in b) if (a[i] !== b[i]) return false;
75
+ for (i in strict ? b : a) if (a[i] !== b[i]) return false;
67
76
 
68
77
  return is.und(i) ? a === b : true;
69
78
  }
@@ -154,15 +163,8 @@ function detach(parent, child, type) {
154
163
  const [, detach] = type;
155
164
  if (is.str(detach)) parent[detach](child);else if (is.fun(detach)) detach(parent, child);
156
165
  }
157
- } // Shallow check arrays, but check objects atomically
158
-
159
- function checkShallow(a, b) {
160
- if (is.arr(a) && is.equ(a, b)) return true;
161
- if (a === b) return true;
162
- return false;
163
166
  } // This function prepares a set of changes to be applied to the instance
164
167
 
165
-
166
168
  function diffProps(instance, {
167
169
  children: cN,
168
170
  key: kN,
@@ -194,7 +196,7 @@ function diffProps(instance, {
194
196
  // Bail out on primitive object
195
197
  if ((_instance$__r3f2 = instance.__r3f) != null && _instance$__r3f2.primitive && key === 'object') return; // When props match bail out
196
198
 
197
- if (checkShallow(value, previous[key])) return; // Collect handlers and bail out
199
+ if (is.equ(value, previous[key])) return; // Collect handlers and bail out
198
200
 
199
201
  if (/^on(Pointer|Click|DoubleClick|ContextMenu|Wheel)/.test(key)) return changes.push([key, value, true, []]); // Split dashed props
200
202
 
@@ -1123,63 +1125,8 @@ const isRenderer = def => !!(def != null && def.render);
1123
1125
  const isOrthographicCamera = def => def && def.isOrthographicCamera;
1124
1126
  const context = /*#__PURE__*/React.createContext(null);
1125
1127
 
1126
- const createStore = (applyProps, invalidate, advance, props) => {
1127
- const {
1128
- gl,
1129
- size,
1130
- shadows = false,
1131
- linear = false,
1132
- flat = false,
1133
- orthographic = false,
1134
- frameloop = 'always',
1135
- dpr = [1, 2],
1136
- performance,
1137
- clock = new THREE.Clock(),
1138
- raycaster: raycastOptions,
1139
- camera: cameraOptions,
1140
- onPointerMissed
1141
- } = props; // Set shadowmap
1142
-
1143
- if (shadows) {
1144
- gl.shadowMap.enabled = true;
1145
- if (typeof shadows === 'object') Object.assign(gl.shadowMap, shadows);else gl.shadowMap.type = THREE.PCFSoftShadowMap;
1146
- } // Set color preferences
1147
-
1148
-
1149
- if (linear) gl.outputEncoding = THREE.LinearEncoding;
1150
- if (flat) gl.toneMapping = THREE.NoToneMapping; // clock.elapsedTime is updated using advance(timestamp)
1151
-
1152
- if (frameloop === 'never') {
1153
- clock.stop();
1154
- clock.elapsedTime = 0;
1155
- }
1156
-
1128
+ const createStore = (invalidate, advance) => {
1157
1129
  const rootState = create((set, get) => {
1158
- // Create custom raycaster
1159
- const raycaster = new THREE.Raycaster();
1160
- const {
1161
- params,
1162
- ...options
1163
- } = raycastOptions || {};
1164
- applyProps(raycaster, {
1165
- enabled: true,
1166
- ...options,
1167
- params: { ...raycaster.params,
1168
- ...params
1169
- }
1170
- }); // Create default camera
1171
-
1172
- const isCamera = cameraOptions instanceof THREE.Camera;
1173
- const camera = isCamera ? cameraOptions : orthographic ? new THREE.OrthographicCamera(0, 0, 0, 0, 0.1, 1000) : new THREE.PerspectiveCamera(75, 0, 0.1, 1000);
1174
-
1175
- if (!isCamera) {
1176
- camera.position.z = 5;
1177
- if (cameraOptions) applyProps(camera, cameraOptions); // Always look at center by default
1178
-
1179
- if (!(cameraOptions != null && cameraOptions.rotation)) camera.lookAt(0, 0, 0);
1180
- }
1181
-
1182
- const initialDpr = calculateDpr(dpr);
1183
1130
  const position = new THREE.Vector3();
1184
1131
  const defaultTarget = new THREE.Vector3();
1185
1132
  const tempTarget = new THREE.Vector3();
@@ -1223,61 +1170,34 @@ const createStore = (applyProps, invalidate, advance, props) => {
1223
1170
  performance: { ...state.performance,
1224
1171
  current
1225
1172
  }
1226
- })); // Handle frame behavior in WebXR
1227
-
1228
-
1229
- const handleXRFrame = (timestamp, frame) => {
1230
- const state = get();
1231
- if (state.frameloop === 'never') return;
1232
- advance(timestamp, true, state, frame);
1233
- }; // Toggle render switching on session
1234
-
1235
-
1236
- const handleSessionChange = () => {
1237
- gl.xr.enabled = gl.xr.isPresenting; // @ts-expect-error
1238
- // WebXRManager's signature is incorrect.
1239
- // See: https://github.com/pmndrs/react-three-fiber/pull/2017#discussion_r790134505
1240
-
1241
- gl.xr.setAnimationLoop(gl.xr.isPresenting ? handleXRFrame : null);
1242
- }; // WebXR session manager
1243
-
1244
-
1245
- const xr = {
1246
- connect() {
1247
- gl.xr.addEventListener('sessionstart', handleSessionChange);
1248
- gl.xr.addEventListener('sessionend', handleSessionChange);
1249
- },
1250
-
1251
- disconnect() {
1252
- gl.xr.removeEventListener('sessionstart', handleSessionChange);
1253
- gl.xr.removeEventListener('sessionend', handleSessionChange);
1254
- }
1255
-
1256
- }; // Subscribe to WebXR session events
1173
+ }));
1257
1174
 
1258
- if (gl.xr) xr.connect();
1259
1175
  return {
1260
- gl,
1176
+ // Mock objects that have to be configured
1177
+ gl: null,
1178
+ camera: null,
1179
+ raycaster: null,
1180
+ events: {
1181
+ connected: false
1182
+ },
1183
+ xr: null,
1261
1184
  set,
1262
1185
  get,
1263
1186
  invalidate: () => invalidate(get()),
1264
1187
  advance: (timestamp, runGlobalEffects) => advance(timestamp, runGlobalEffects, get()),
1265
- linear,
1266
- flat,
1188
+ linear: false,
1189
+ flat: false,
1267
1190
  scene: prepare(new THREE.Scene()),
1268
- camera,
1269
1191
  controls: null,
1270
- raycaster,
1271
- clock,
1192
+ clock: new THREE.Clock(),
1272
1193
  mouse: new THREE.Vector2(),
1273
- frameloop,
1274
- onPointerMissed,
1194
+ frameloop: 'always',
1195
+ onPointerMissed: undefined,
1275
1196
  performance: {
1276
1197
  current: 1,
1277
1198
  min: 0.5,
1278
1199
  max: 1,
1279
1200
  debounce: 200,
1280
- ...performance,
1281
1201
  regress: () => {
1282
1202
  const state = get(); // Clear timeout
1283
1203
 
@@ -1293,8 +1213,8 @@ const createStore = (applyProps, invalidate, advance, props) => {
1293
1213
  height: 0
1294
1214
  },
1295
1215
  viewport: {
1296
- initialDpr,
1297
- dpr: initialDpr,
1216
+ initialDpr: 0,
1217
+ dpr: 0,
1298
1218
  width: 0,
1299
1219
  height: 0,
1300
1220
  aspect: 0,
@@ -1303,6 +1223,7 @@ const createStore = (applyProps, invalidate, advance, props) => {
1303
1223
  getCurrentViewport
1304
1224
  },
1305
1225
  setSize: (width, height) => {
1226
+ const camera = get().camera;
1306
1227
  const size = {
1307
1228
  width,
1308
1229
  height
@@ -1314,22 +1235,34 @@ const createStore = (applyProps, invalidate, advance, props) => {
1314
1235
  }
1315
1236
  }));
1316
1237
  },
1317
- setDpr: dpr => set(state => ({
1318
- viewport: { ...state.viewport,
1319
- dpr: calculateDpr(dpr)
1238
+ setDpr: dpr => set(state => {
1239
+ const resolved = calculateDpr(dpr);
1240
+ return {
1241
+ viewport: { ...state.viewport,
1242
+ dpr: resolved,
1243
+ initialDpr: state.viewport.initialDpr || resolved
1244
+ }
1245
+ };
1246
+ }),
1247
+ setFrameloop: (frameloop = 'always') => {
1248
+ const clock = get().clock; // if frameloop === "never" clock.elapsedTime is updated using advance(timestamp)
1249
+
1250
+ clock.stop();
1251
+ clock.elapsedTime = 0;
1252
+
1253
+ if (frameloop !== 'never') {
1254
+ clock.start();
1255
+ clock.elapsedTime = 0;
1320
1256
  }
1321
- })),
1322
- setFrameloop: (frameloop = 'always') => set(() => ({
1323
- frameloop
1324
- })),
1325
- events: {
1326
- connected: false
1257
+
1258
+ set(() => ({
1259
+ frameloop
1260
+ }));
1327
1261
  },
1328
1262
  internal: {
1329
1263
  active: false,
1330
1264
  priority: 0,
1331
1265
  frames: 0,
1332
- lastProps: props,
1333
1266
  lastEvent: /*#__PURE__*/React.createRef(),
1334
1267
  interaction: [],
1335
1268
  hovered: new Map(),
@@ -1337,7 +1270,6 @@ const createStore = (applyProps, invalidate, advance, props) => {
1337
1270
  initialClick: [0, 0],
1338
1271
  initialHits: [],
1339
1272
  capturedMap: new Map(),
1340
- xr,
1341
1273
  subscribe: (ref, priority = 0) => {
1342
1274
  set(({
1343
1275
  internal
@@ -1381,13 +1313,14 @@ const createStore = (applyProps, invalidate, advance, props) => {
1381
1313
  camera,
1382
1314
  size,
1383
1315
  viewport,
1384
- internal
1316
+ internal,
1317
+ gl
1385
1318
  } = rootState.getState();
1386
1319
 
1387
1320
  if (size !== oldSize || viewport.dpr !== oldDpr) {
1388
1321
  // https://github.com/pmndrs/react-three-fiber/issues/92
1389
1322
  // Do not mess with the camera if it belongs to the user
1390
- if (!camera.manual && !(internal.lastProps.camera instanceof THREE.Camera)) {
1323
+ if (!camera.manual) {
1391
1324
  if (isOrthographicCamera(camera)) {
1392
1325
  camera.left = size.width / -2;
1393
1326
  camera.right = size.width / 2;
@@ -1409,9 +1342,7 @@ const createStore = (applyProps, invalidate, advance, props) => {
1409
1342
  oldSize = size;
1410
1343
  oldDpr = viewport.dpr;
1411
1344
  }
1412
- }); // Update size
1413
-
1414
- if (size) state.setSize(size.width, size.height); // Invalidate on any change
1345
+ }); // Invalidate on any change
1415
1346
 
1416
1347
  rootState.subscribe(state => invalidate(state)); // Return root state
1417
1348
 
@@ -1436,6 +1367,8 @@ function run(effects, timestamp) {
1436
1367
  for (i = 0; i < effects.length; i++) effects[i](timestamp);
1437
1368
  }
1438
1369
 
1370
+ let subscribers;
1371
+
1439
1372
  function render$1(timestamp, state, frame) {
1440
1373
  // Run local effects
1441
1374
  let delta = state.clock.getDelta(); // In frameloop='never' mode, clock times are updated using the provided timestamp
@@ -1447,7 +1380,9 @@ function render$1(timestamp, state, frame) {
1447
1380
  } // Call subscribers (useFrame)
1448
1381
 
1449
1382
 
1450
- for (i = 0; i < state.internal.subscribers.length; i++) state.internal.subscribers[i].ref.current(state, delta, frame); // Render content
1383
+ subscribers = state.internal.subscribers;
1384
+
1385
+ for (i = 0; i < subscribers.length; i++) subscribers[i].ref.current(state, delta, frame); // Render content
1451
1386
 
1452
1387
 
1453
1388
  if (!state.internal.priority && state.gl.render) state.gl.render(state.scene, state.camera); // Decrease frame count
@@ -1459,29 +1394,35 @@ function render$1(timestamp, state, frame) {
1459
1394
  function createLoop(roots) {
1460
1395
  let running = false;
1461
1396
  let repeat;
1397
+ let frame;
1398
+ let state;
1462
1399
 
1463
1400
  function loop(timestamp) {
1401
+ frame = requestAnimationFrame(loop);
1464
1402
  running = true;
1465
1403
  repeat = 0; // Run effects
1466
1404
 
1467
- run(globalEffects, timestamp); // Render all roots
1405
+ if (globalEffects.length) run(globalEffects, timestamp); // Render all roots
1468
1406
 
1469
1407
  roots.forEach(root => {
1470
1408
  var _state$gl$xr;
1471
1409
 
1472
- const state = root.store.getState(); // If the frameloop is invalidated, do not run another frame
1410
+ state = root.store.getState(); // If the frameloop is invalidated, do not run another frame
1473
1411
 
1474
1412
  if (state.internal.active && (state.frameloop === 'always' || state.internal.frames > 0) && !((_state$gl$xr = state.gl.xr) != null && _state$gl$xr.isPresenting)) {
1475
1413
  repeat += render$1(timestamp, state);
1476
1414
  }
1477
1415
  }); // Run after-effects
1478
1416
 
1479
- run(globalAfterEffects, timestamp); // Keep on looping if anything invalidates the frameloop
1417
+ if (globalAfterEffects.length) run(globalAfterEffects, timestamp); // Stop the loop if nothing invalidates it
1480
1418
 
1481
- if (repeat > 0) return requestAnimationFrame(loop); // Tail call effects, they are called when rendering stops
1482
- else run(globalTailEffects, timestamp); // Flag end of operation
1419
+ if (repeat === 0) {
1420
+ // Tail call effects, they are called when rendering stops
1421
+ if (globalTailEffects.length) run(globalTailEffects, timestamp); // Flag end of operation
1483
1422
 
1484
- running = false;
1423
+ running = false;
1424
+ return cancelAnimationFrame(frame);
1425
+ }
1485
1426
  }
1486
1427
 
1487
1428
  function invalidate(state) {
@@ -1574,113 +1515,216 @@ const {
1574
1515
  reconciler,
1575
1516
  applyProps
1576
1517
  } = createRenderer(roots, getEventPriority);
1518
+ const shallowLoose = {
1519
+ objects: 'shallow',
1520
+ strict: false
1521
+ };
1577
1522
 
1578
1523
  const createRendererInstance = (gl, canvas) => {
1579
1524
  const customRenderer = typeof gl === 'function' ? gl(canvas) : gl;
1580
- if (isRenderer(customRenderer)) return customRenderer;
1581
- const renderer = new THREE.WebGLRenderer({
1525
+ if (isRenderer(customRenderer)) return customRenderer;else return new THREE.WebGLRenderer({
1582
1526
  powerPreference: 'high-performance',
1583
1527
  canvas: canvas,
1584
1528
  antialias: true,
1585
1529
  alpha: true,
1586
1530
  ...gl
1587
- }); // Set color management
1531
+ });
1532
+ };
1588
1533
 
1589
- renderer.outputEncoding = THREE.sRGBEncoding;
1590
- renderer.toneMapping = THREE.ACESFilmicToneMapping; // Set gl props
1534
+ function createRoot(canvas) {
1535
+ // Check against mistaken use of createRoot
1536
+ let prevRoot = roots.get(canvas);
1537
+ let prevFiber = prevRoot == null ? void 0 : prevRoot.fiber;
1538
+ let prevStore = prevRoot == null ? void 0 : prevRoot.store;
1539
+ if (prevRoot) console.warn('R3F.createRoot should only be called once!'); // Create store
1591
1540
 
1592
- if (gl) applyProps(renderer, gl);
1593
- return renderer;
1594
- };
1541
+ const store = prevStore || createStore(invalidate, advance); // Create renderer
1542
+
1543
+ const fiber = prevFiber || reconciler.createContainer(store, ConcurrentRoot, false, null); // Map it
1544
+
1545
+ if (!prevRoot) roots.set(canvas, {
1546
+ fiber,
1547
+ store
1548
+ }); // Locals
1595
1549
 
1596
- function createRoot(canvas, config) {
1550
+ let onCreated;
1551
+ let configured = false;
1597
1552
  return {
1598
- render: element => {
1599
- var _store;
1553
+ configure(props = {}) {
1554
+ var _canvas$parentElement, _canvas$parentElement2, _canvas$parentElement3, _canvas$parentElement4;
1600
1555
 
1601
1556
  let {
1602
- gl,
1557
+ gl: glConfig,
1603
1558
  size,
1604
1559
  events,
1605
- onCreated,
1606
- ...props
1607
- } = config || {}; // Allow size to take on container bounds initially
1560
+ onCreated: onCreatedCallback,
1561
+ shadows = false,
1562
+ linear = false,
1563
+ flat = false,
1564
+ orthographic = false,
1565
+ frameloop = 'always',
1566
+ dpr = [1, 2],
1567
+ performance,
1568
+ raycaster: raycastOptions,
1569
+ camera: cameraOptions,
1570
+ onPointerMissed
1571
+ } = props;
1572
+ let state = store.getState(); // Set up renderer (one time only!)
1573
+
1574
+ let gl = state.gl;
1575
+ if (!state.gl) state.set({
1576
+ gl: gl = createRendererInstance(glConfig, canvas)
1577
+ }); // Set up raycaster (one time only!)
1578
+
1579
+ let raycaster = state.raycaster;
1580
+ if (!raycaster) state.set({
1581
+ raycaster: raycaster = new THREE.Raycaster()
1582
+ }); // Set raycaster options
1608
1583
 
1609
- if (!size) {
1610
- var _canvas$parentElement, _canvas$parentElement2, _canvas$parentElement3, _canvas$parentElement4;
1584
+ const {
1585
+ params,
1586
+ ...options
1587
+ } = raycastOptions || {};
1588
+ if (!is.equ(options, raycaster, shallowLoose)) applyProps(raycaster, {
1589
+ enabled: true,
1590
+ ...options
1591
+ });
1592
+ if (!is.equ(params, raycaster.params, shallowLoose)) applyProps(raycaster, {
1593
+ params: { ...raycaster.params,
1594
+ ...params
1595
+ }
1596
+ }); // Create default camera (one time only!)
1611
1597
 
1612
- size = {
1613
- width: (_canvas$parentElement = (_canvas$parentElement2 = canvas.parentElement) == null ? void 0 : _canvas$parentElement2.clientWidth) != null ? _canvas$parentElement : 0,
1614
- height: (_canvas$parentElement3 = (_canvas$parentElement4 = canvas.parentElement) == null ? void 0 : _canvas$parentElement4.clientHeight) != null ? _canvas$parentElement3 : 0
1615
- };
1616
- }
1598
+ if (!state.camera) {
1599
+ const isCamera = cameraOptions instanceof THREE.Camera;
1600
+ const camera = isCamera ? cameraOptions : orthographic ? new THREE.OrthographicCamera(0, 0, 0, 0, 0.1, 1000) : new THREE.PerspectiveCamera(75, 0, 0.1, 1000);
1617
1601
 
1618
- let root = roots.get(canvas);
1619
- let fiber = root == null ? void 0 : root.fiber;
1620
- let store = root == null ? void 0 : root.store;
1621
- let state = (_store = store) == null ? void 0 : _store.getState();
1602
+ if (!isCamera) {
1603
+ camera.position.z = 5;
1604
+ if (cameraOptions) applyProps(camera, cameraOptions); // Always look at center by default
1622
1605
 
1623
- if (fiber && state) {
1624
- // When a root was found, see if any fundamental props must be changed or exchanged
1625
- // Check pixelratio
1626
- if (props.dpr !== undefined && state.viewport.dpr !== calculateDpr(props.dpr)) state.setDpr(props.dpr); // Check size
1606
+ if (!(cameraOptions != null && cameraOptions.rotation)) camera.lookAt(0, 0, 0);
1607
+ }
1627
1608
 
1628
- if (state.size.width !== size.width || state.size.height !== size.height) state.setSize(size.width, size.height); // Check frameloop
1609
+ state.set({
1610
+ camera
1611
+ });
1612
+ } // Set up XR (one time only!)
1629
1613
 
1630
- if (state.frameloop !== props.frameloop) state.setFrameloop(props.frameloop); // For some props we want to reset the entire root
1631
- // Changes to the color-space
1632
1614
 
1633
- const linearChanged = props.linear !== state.internal.lastProps.linear;
1615
+ if (!state.xr) {
1616
+ // Handle frame behavior in WebXR
1617
+ const handleXRFrame = (timestamp, frame) => {
1618
+ const state = store.getState();
1619
+ if (state.frameloop === 'never') return;
1620
+ advance(timestamp, true, state, frame);
1621
+ }; // Toggle render switching on session
1634
1622
 
1635
- if (linearChanged) {
1636
- unmountComponentAtNode(canvas);
1637
- fiber = undefined;
1638
- }
1639
- }
1640
1623
 
1641
- if (!fiber) {
1642
- // If no root has been found, make one
1643
- // Create gl
1644
- const glRenderer = createRendererInstance(gl, canvas); // Create store
1624
+ const handleSessionChange = () => {
1625
+ const gl = store.getState().gl;
1626
+ gl.xr.enabled = gl.xr.isPresenting; // @ts-expect-error
1627
+ // WebXRManager's signature is incorrect.
1628
+ // See: https://github.com/pmndrs/react-three-fiber/pull/2017#discussion_r790134505
1645
1629
 
1646
- store = createStore(applyProps, invalidate, advance, {
1647
- gl: glRenderer,
1648
- size,
1649
- ...props
1650
- });
1651
- const state = store.getState(); // Create renderer
1630
+ gl.xr.setAnimationLoop(gl.xr.isPresenting ? handleXRFrame : null);
1631
+ }; // WebXR session manager
1652
1632
 
1653
- fiber = reconciler.createContainer(store, ConcurrentRoot, false, null); // Map it
1654
1633
 
1655
- roots.set(canvas, {
1656
- fiber,
1657
- store
1658
- }); // Store events internally
1634
+ const xr = {
1635
+ connect() {
1636
+ const gl = store.getState().gl;
1637
+ gl.xr.addEventListener('sessionstart', handleSessionChange);
1638
+ gl.xr.addEventListener('sessionend', handleSessionChange);
1639
+ },
1640
+
1641
+ disconnect() {
1642
+ const gl = store.getState().gl;
1643
+ gl.xr.removeEventListener('sessionstart', handleSessionChange);
1644
+ gl.xr.removeEventListener('sessionend', handleSessionChange);
1645
+ }
1659
1646
 
1660
- if (events) state.set({
1661
- events: events(store)
1647
+ }; // Subscribe to WebXR session events
1648
+
1649
+ if (gl.xr) xr.connect();
1650
+ state.set({
1651
+ xr
1662
1652
  });
1663
- }
1653
+ } // Set shadowmap
1664
1654
 
1665
- if (store && fiber) {
1666
- reconciler.updateContainer( /*#__PURE__*/React.createElement(Provider, {
1667
- store: store,
1668
- element: element,
1669
- onCreated: onCreated,
1670
- target: canvas
1671
- }), fiber, null, () => undefined);
1672
- return store;
1673
- } else {
1674
- throw 'Error creating root!';
1675
- }
1655
+
1656
+ if (gl.shadowMap) {
1657
+ const isBoolean = is.boo(shadows);
1658
+
1659
+ if (isBoolean && gl.shadowMap.enabled !== shadows || !is.equ(shadows, gl.shadowMap, shallowLoose)) {
1660
+ const old = gl.shadowMap.enabled;
1661
+ gl.shadowMap.enabled = !!shadows;
1662
+ if (!isBoolean) Object.assign(gl.shadowMap, shadows);else gl.shadowMap.type = THREE.PCFSoftShadowMap;
1663
+ if (old !== gl.shadowMap.enabled) gl.shadowMap.needsUpdate = true;
1664
+ }
1665
+ } // Set color management
1666
+
1667
+
1668
+ const outputEncoding = linear ? THREE.LinearEncoding : THREE.sRGBEncoding;
1669
+ const toneMapping = flat ? THREE.NoToneMapping : THREE.ACESFilmicToneMapping;
1670
+ if (gl.outputEncoding !== outputEncoding) gl.outputEncoding = outputEncoding;
1671
+ if (gl.toneMapping !== toneMapping) gl.toneMapping = toneMapping; // Set gl props
1672
+
1673
+ if (glConfig && !is.fun(glConfig) && !isRenderer(glConfig) && !is.equ(glConfig, gl, shallowLoose)) applyProps(gl, glConfig); // Store events internally
1674
+
1675
+ if (events && !state.events.handlers) state.set({
1676
+ events: events(store)
1677
+ }); // Check pixelratio
1678
+
1679
+ if (dpr && state.viewport.dpr !== calculateDpr(dpr)) state.setDpr(dpr); // Check size, allow it to take on container bounds initially
1680
+
1681
+ size = size || {
1682
+ width: (_canvas$parentElement = (_canvas$parentElement2 = canvas.parentElement) == null ? void 0 : _canvas$parentElement2.clientWidth) != null ? _canvas$parentElement : 0,
1683
+ height: (_canvas$parentElement3 = (_canvas$parentElement4 = canvas.parentElement) == null ? void 0 : _canvas$parentElement4.clientHeight) != null ? _canvas$parentElement3 : 0
1684
+ };
1685
+ if (!is.equ(size, state.size, shallowLoose)) state.setSize(size.width, size.height); // Check frameloop
1686
+
1687
+ if (state.frameloop !== frameloop) state.setFrameloop(frameloop); // Check pointer missed
1688
+
1689
+ if (!state.onPointerMissed) state.set({
1690
+ onPointerMissed
1691
+ }); // Check performance
1692
+
1693
+ if (performance && !is.equ(performance, state.performance, shallowLoose)) state.set(state => ({
1694
+ performance: { ...state.performance,
1695
+ ...performance
1696
+ }
1697
+ })); // Set locals
1698
+
1699
+ onCreated = onCreatedCallback;
1700
+ configured = true;
1701
+ return this;
1676
1702
  },
1677
- unmount: () => unmountComponentAtNode(canvas)
1703
+
1704
+ render(element) {
1705
+ // The root has to be configured before it can be rendered
1706
+ if (!configured) this.configure();
1707
+ reconciler.updateContainer( /*#__PURE__*/React.createElement(Provider, {
1708
+ store: store,
1709
+ element: element,
1710
+ onCreated: onCreated,
1711
+ target: canvas
1712
+ }), fiber, null, () => undefined);
1713
+ return store;
1714
+ },
1715
+
1716
+ unmount() {
1717
+ unmountComponentAtNode(canvas);
1718
+ }
1719
+
1678
1720
  };
1679
1721
  }
1680
1722
 
1681
1723
  function render(element, canvas, config = {}) {
1682
1724
  console.warn('R3F.render is no longer supported in React 18. Use createRoot instead!');
1683
- return createRoot(canvas, config).render(element);
1725
+ const root = createRoot(canvas);
1726
+ root.configure(config);
1727
+ return root.render(element);
1684
1728
  }
1685
1729
 
1686
1730
  function Provider({
@@ -1723,7 +1767,7 @@ function unmountComponentAtNode(canvas, callback) {
1723
1767
  state.events.disconnect == null ? void 0 : state.events.disconnect();
1724
1768
  (_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();
1725
1769
  (_state$gl2 = state.gl) == null ? void 0 : _state$gl2.forceContextLoss == null ? void 0 : _state$gl2.forceContextLoss();
1726
- if ((_state$gl3 = state.gl) != null && _state$gl3.xr) state.internal.xr.disconnect();
1770
+ if ((_state$gl3 = state.gl) != null && _state$gl3.xr) state.xr.disconnect();
1727
1771
  dispose(state);
1728
1772
  roots.delete(canvas);
1729
1773
  if (callback) callback(canvas);