@react-three/fiber 9.5.0 → 9.6.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 CHANGED
@@ -1,5 +1,17 @@
1
1
  # @react-three/fiber
2
2
 
3
+ ## 9.6.1
4
+
5
+ ### Patch Changes
6
+
7
+ - b645741874486417727ea75a0704d48e9f21d623: fix: Seamlessly transfer interactivity state when swapping instances
8
+
9
+ ## 9.6.0
10
+
11
+ ### Minor Changes
12
+
13
+ - 26e4716412b11a189dd9ac4b3033d0e504f1d7df: Fix uniforms refs so they remain stable for ShaderMaterial
14
+
3
15
  ## 9.5.0
4
16
 
5
17
  ### Minor Changes
@@ -86,6 +86,8 @@ export interface PointerCaptureTarget {
86
86
  intersection: Intersection;
87
87
  target: Element;
88
88
  }
89
+ /** This function transfers all interactivity state from one object instance to another. Used when swapping instances due to reconstruction. */
90
+ export declare function swapInteractivity(store: RootStore, object: THREE.Object3D, newObject: THREE.Object3D): void;
89
91
  export declare function removeInteractivity(store: RootStore, object: THREE.Object3D): void;
90
92
  export declare function createEvents(store: RootStore): {
91
93
  handlePointer: (name: string) => (event: DomEvent) => void;
@@ -449,6 +449,19 @@ function applyProps(object, props) {
449
449
  // Otherwise just set single value
450
450
  else target.set(value);
451
451
  }
452
+ // ShaderMaterial uniforms must keep a stable target reference
453
+ else if (root instanceof THREE__namespace.ShaderMaterial && key === 'uniforms' && is.obj(value)) {
454
+ if (!is.obj(root.uniforms)) root.uniforms = {};
455
+ const uniforms = root.uniforms;
456
+ const nextUniforms = value;
457
+ for (const name in nextUniforms) {
458
+ const uniform = nextUniforms[name];
459
+ const targetUniform = uniforms[name];
460
+ if (targetUniform) Object.assign(targetUniform, uniform);else uniforms[name] = {
461
+ ...uniform
462
+ };
463
+ }
464
+ }
452
465
  // Else, just overwrite the value
453
466
  else {
454
467
  var _root$key;
@@ -529,6 +542,37 @@ function releaseInternalPointerCapture(capturedMap, obj, captures, pointerId) {
529
542
  }
530
543
  }
531
544
  }
545
+
546
+ /** This function transfers all interactivity state from one object instance to another. Used when swapping instances due to reconstruction. */
547
+ function swapInteractivity(store, object, newObject) {
548
+ const {
549
+ internal
550
+ } = store.getState();
551
+ for (let i = 0; i < internal.interaction.length; i++) {
552
+ if (internal.interaction[i] === object) internal.interaction[i] = newObject;
553
+ }
554
+ for (let i = 0; i < internal.initialHits.length; i++) {
555
+ if (internal.initialHits[i] === object) internal.initialHits[i] = newObject;
556
+ }
557
+ internal.hovered.forEach((value, key) => {
558
+ if (value.eventObject === object || value.object === object) {
559
+ internal.hovered.delete(key);
560
+ const next = {
561
+ ...value,
562
+ eventObject: value.eventObject === object ? newObject : value.eventObject,
563
+ object: value.object === object ? newObject : value.object
564
+ };
565
+ internal.hovered.set(makeId(next), next);
566
+ }
567
+ });
568
+ internal.capturedMap.forEach(captures => {
569
+ const captureData = captures.get(object);
570
+ if (captureData) {
571
+ captures.delete(object);
572
+ captures.set(newObject, captureData);
573
+ }
574
+ });
575
+ }
532
576
  function removeInteractivity(store, object) {
533
577
  const {
534
578
  internal
@@ -770,7 +814,7 @@ function createEvents(store) {
770
814
  internal
771
815
  } = store.getState();
772
816
  for (const hoveredObj of internal.hovered.values()) {
773
- // When no objects were hit or the the hovered object wasn't found underneath the cursor
817
+ // When no objects were hit or the hovered object wasn't found underneath the cursor
774
818
  // we call onPointerOut and delete the object from the hovered-elements map
775
819
  if (!intersections.length || !intersections.find(hit => hit.object === hoveredObj.object && hit.index === hoveredObj.index && hit.instanceId === hoveredObj.instanceId)) {
776
820
  const eventObject = hoveredObj.eventObject;
@@ -1296,7 +1340,7 @@ useLoader.clear = function (loader, input) {
1296
1340
 
1297
1341
  var packageData = {
1298
1342
  name: "@react-three/fiber",
1299
- version: "9.5.0",
1343
+ version: "9.6.1",
1300
1344
  description: "A React renderer for Threejs",
1301
1345
  keywords: [
1302
1346
  "react",
@@ -7065,11 +7109,11 @@ function swapInstances() {
7065
7109
  const target = catalogue[toPascalCase(instance.type)];
7066
7110
 
7067
7111
  // Create object
7112
+ const prevObject = instance.object;
7068
7113
  instance.object = (_instance$props$objec = instance.props.object) != null ? _instance$props$objec : new target(...((_instance$props$args = instance.props.args) != null ? _instance$props$args : []));
7069
7114
  instance.object.__r3f = instance;
7070
7115
  setFiberRef(fiber, instance.object);
7071
-
7072
- // Set initial props
7116
+ swapInteractivity(findInitialRoot(instance), prevObject, instance.object);
7073
7117
  applyProps(instance.object, instance.props);
7074
7118
  if (instance.props.attach) {
7075
7119
  attach(parent, instance);
@@ -7904,7 +7948,7 @@ function invalidate(state, frames = 1) {
7904
7948
  //called from within a useFrame, it means the user wants an additional frame
7905
7949
  state.internal.frames = 2;
7906
7950
  } else {
7907
- //the user need a new frame, no need to increment further than 1
7951
+ //the user needs a new frame, no need to increment further than 1
7908
7952
  state.internal.frames = 1;
7909
7953
  }
7910
7954
  }
@@ -424,6 +424,19 @@ function applyProps(object, props) {
424
424
  // Otherwise just set single value
425
425
  else target.set(value);
426
426
  }
427
+ // ShaderMaterial uniforms must keep a stable target reference
428
+ else if (root instanceof THREE.ShaderMaterial && key === 'uniforms' && is.obj(value)) {
429
+ if (!is.obj(root.uniforms)) root.uniforms = {};
430
+ const uniforms = root.uniforms;
431
+ const nextUniforms = value;
432
+ for (const name in nextUniforms) {
433
+ const uniform = nextUniforms[name];
434
+ const targetUniform = uniforms[name];
435
+ if (targetUniform) Object.assign(targetUniform, uniform);else uniforms[name] = {
436
+ ...uniform
437
+ };
438
+ }
439
+ }
427
440
  // Else, just overwrite the value
428
441
  else {
429
442
  var _root$key;
@@ -504,6 +517,37 @@ function releaseInternalPointerCapture(capturedMap, obj, captures, pointerId) {
504
517
  }
505
518
  }
506
519
  }
520
+
521
+ /** This function transfers all interactivity state from one object instance to another. Used when swapping instances due to reconstruction. */
522
+ function swapInteractivity(store, object, newObject) {
523
+ const {
524
+ internal
525
+ } = store.getState();
526
+ for (let i = 0; i < internal.interaction.length; i++) {
527
+ if (internal.interaction[i] === object) internal.interaction[i] = newObject;
528
+ }
529
+ for (let i = 0; i < internal.initialHits.length; i++) {
530
+ if (internal.initialHits[i] === object) internal.initialHits[i] = newObject;
531
+ }
532
+ internal.hovered.forEach((value, key) => {
533
+ if (value.eventObject === object || value.object === object) {
534
+ internal.hovered.delete(key);
535
+ const next = {
536
+ ...value,
537
+ eventObject: value.eventObject === object ? newObject : value.eventObject,
538
+ object: value.object === object ? newObject : value.object
539
+ };
540
+ internal.hovered.set(makeId(next), next);
541
+ }
542
+ });
543
+ internal.capturedMap.forEach(captures => {
544
+ const captureData = captures.get(object);
545
+ if (captureData) {
546
+ captures.delete(object);
547
+ captures.set(newObject, captureData);
548
+ }
549
+ });
550
+ }
507
551
  function removeInteractivity(store, object) {
508
552
  const {
509
553
  internal
@@ -745,7 +789,7 @@ function createEvents(store) {
745
789
  internal
746
790
  } = store.getState();
747
791
  for (const hoveredObj of internal.hovered.values()) {
748
- // When no objects were hit or the the hovered object wasn't found underneath the cursor
792
+ // When no objects were hit or the hovered object wasn't found underneath the cursor
749
793
  // we call onPointerOut and delete the object from the hovered-elements map
750
794
  if (!intersections.length || !intersections.find(hit => hit.object === hoveredObj.object && hit.index === hoveredObj.index && hit.instanceId === hoveredObj.instanceId)) {
751
795
  const eventObject = hoveredObj.eventObject;
@@ -1271,7 +1315,7 @@ useLoader.clear = function (loader, input) {
1271
1315
 
1272
1316
  var packageData = {
1273
1317
  name: "@react-three/fiber",
1274
- version: "9.5.0",
1318
+ version: "9.6.1",
1275
1319
  description: "A React renderer for Threejs",
1276
1320
  keywords: [
1277
1321
  "react",
@@ -15237,11 +15281,11 @@ function swapInstances() {
15237
15281
  const target = catalogue[toPascalCase(instance.type)];
15238
15282
 
15239
15283
  // Create object
15284
+ const prevObject = instance.object;
15240
15285
  instance.object = (_instance$props$objec = instance.props.object) != null ? _instance$props$objec : new target(...((_instance$props$args = instance.props.args) != null ? _instance$props$args : []));
15241
15286
  instance.object.__r3f = instance;
15242
15287
  setFiberRef(fiber, instance.object);
15243
-
15244
- // Set initial props
15288
+ swapInteractivity(findInitialRoot(instance), prevObject, instance.object);
15245
15289
  applyProps(instance.object, instance.props);
15246
15290
  if (instance.props.attach) {
15247
15291
  attach(parent, instance);
@@ -16076,7 +16120,7 @@ function invalidate(state, frames = 1) {
16076
16120
  //called from within a useFrame, it means the user wants an additional frame
16077
16121
  state.internal.frames = 2;
16078
16122
  } else {
16079
- //the user need a new frame, no need to increment further than 1
16123
+ //the user needs a new frame, no need to increment further than 1
16080
16124
  state.internal.frames = 1;
16081
16125
  }
16082
16126
  }
@@ -449,6 +449,19 @@ function applyProps(object, props) {
449
449
  // Otherwise just set single value
450
450
  else target.set(value);
451
451
  }
452
+ // ShaderMaterial uniforms must keep a stable target reference
453
+ else if (root instanceof THREE__namespace.ShaderMaterial && key === 'uniforms' && is.obj(value)) {
454
+ if (!is.obj(root.uniforms)) root.uniforms = {};
455
+ const uniforms = root.uniforms;
456
+ const nextUniforms = value;
457
+ for (const name in nextUniforms) {
458
+ const uniform = nextUniforms[name];
459
+ const targetUniform = uniforms[name];
460
+ if (targetUniform) Object.assign(targetUniform, uniform);else uniforms[name] = {
461
+ ...uniform
462
+ };
463
+ }
464
+ }
452
465
  // Else, just overwrite the value
453
466
  else {
454
467
  var _root$key;
@@ -529,6 +542,37 @@ function releaseInternalPointerCapture(capturedMap, obj, captures, pointerId) {
529
542
  }
530
543
  }
531
544
  }
545
+
546
+ /** This function transfers all interactivity state from one object instance to another. Used when swapping instances due to reconstruction. */
547
+ function swapInteractivity(store, object, newObject) {
548
+ const {
549
+ internal
550
+ } = store.getState();
551
+ for (let i = 0; i < internal.interaction.length; i++) {
552
+ if (internal.interaction[i] === object) internal.interaction[i] = newObject;
553
+ }
554
+ for (let i = 0; i < internal.initialHits.length; i++) {
555
+ if (internal.initialHits[i] === object) internal.initialHits[i] = newObject;
556
+ }
557
+ internal.hovered.forEach((value, key) => {
558
+ if (value.eventObject === object || value.object === object) {
559
+ internal.hovered.delete(key);
560
+ const next = {
561
+ ...value,
562
+ eventObject: value.eventObject === object ? newObject : value.eventObject,
563
+ object: value.object === object ? newObject : value.object
564
+ };
565
+ internal.hovered.set(makeId(next), next);
566
+ }
567
+ });
568
+ internal.capturedMap.forEach(captures => {
569
+ const captureData = captures.get(object);
570
+ if (captureData) {
571
+ captures.delete(object);
572
+ captures.set(newObject, captureData);
573
+ }
574
+ });
575
+ }
532
576
  function removeInteractivity(store, object) {
533
577
  const {
534
578
  internal
@@ -770,7 +814,7 @@ function createEvents(store) {
770
814
  internal
771
815
  } = store.getState();
772
816
  for (const hoveredObj of internal.hovered.values()) {
773
- // When no objects were hit or the the hovered object wasn't found underneath the cursor
817
+ // When no objects were hit or the hovered object wasn't found underneath the cursor
774
818
  // we call onPointerOut and delete the object from the hovered-elements map
775
819
  if (!intersections.length || !intersections.find(hit => hit.object === hoveredObj.object && hit.index === hoveredObj.index && hit.instanceId === hoveredObj.instanceId)) {
776
820
  const eventObject = hoveredObj.eventObject;
@@ -1296,7 +1340,7 @@ useLoader.clear = function (loader, input) {
1296
1340
 
1297
1341
  var packageData = {
1298
1342
  name: "@react-three/fiber",
1299
- version: "9.5.0",
1343
+ version: "9.6.1",
1300
1344
  description: "A React renderer for Threejs",
1301
1345
  keywords: [
1302
1346
  "react",
@@ -15262,11 +15306,11 @@ function swapInstances() {
15262
15306
  const target = catalogue[toPascalCase(instance.type)];
15263
15307
 
15264
15308
  // Create object
15309
+ const prevObject = instance.object;
15265
15310
  instance.object = (_instance$props$objec = instance.props.object) != null ? _instance$props$objec : new target(...((_instance$props$args = instance.props.args) != null ? _instance$props$args : []));
15266
15311
  instance.object.__r3f = instance;
15267
15312
  setFiberRef(fiber, instance.object);
15268
-
15269
- // Set initial props
15313
+ swapInteractivity(findInitialRoot(instance), prevObject, instance.object);
15270
15314
  applyProps(instance.object, instance.props);
15271
15315
  if (instance.props.attach) {
15272
15316
  attach(parent, instance);
@@ -16101,7 +16145,7 @@ function invalidate(state, frames = 1) {
16101
16145
  //called from within a useFrame, it means the user wants an additional frame
16102
16146
  state.internal.frames = 2;
16103
16147
  } else {
16104
- //the user need a new frame, no need to increment further than 1
16148
+ //the user needs a new frame, no need to increment further than 1
16105
16149
  state.internal.frames = 1;
16106
16150
  }
16107
16151
  }
@@ -2,7 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var events = require('./events-358c3764.cjs.dev.js');
5
+ var events = require('./events-f19bcc32.cjs.dev.js');
6
6
  var React = require('react');
7
7
  var THREE = require('three');
8
8
  var useMeasure = require('react-use-measure');
@@ -2,7 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var events = require('./events-238e0986.cjs.prod.js');
5
+ var events = require('./events-583399dd.cjs.prod.js');
6
6
  var React = require('react');
7
7
  var THREE = require('three');
8
8
  var useMeasure = require('react-use-measure');
@@ -1,5 +1,5 @@
1
- import { e as extend, u as useBridge, a as useMutableCallback, b as useIsomorphicLayoutEffect, c as createRoot, i as isRef, E as ErrorBoundary, B as Block, d as unmountComponentAtNode, f as createPointerEvents } from './events-5a94e5eb.esm.js';
2
- export { t as ReactThreeFiber, _ as _roots, x as act, k as addAfterEffect, j as addEffect, l as addTail, n as advance, s as applyProps, y as buildGraph, q as context, g as createEvents, o as createPortal, c as createRoot, w as dispose, f as events, e as extend, h as flushGlobalEffects, p as flushSync, v as getRootState, m as invalidate, r as reconciler, d as unmountComponentAtNode, D as useFrame, F as useGraph, z as useInstanceHandle, G as useLoader, A as useStore, C as useThree } from './events-5a94e5eb.esm.js';
1
+ import { e as extend, u as useBridge, a as useMutableCallback, b as useIsomorphicLayoutEffect, c as createRoot, i as isRef, E as ErrorBoundary, B as Block, d as unmountComponentAtNode, f as createPointerEvents } from './events-b389eeca.esm.js';
2
+ export { t as ReactThreeFiber, _ as _roots, x as act, k as addAfterEffect, j as addEffect, l as addTail, n as advance, s as applyProps, y as buildGraph, q as context, g as createEvents, o as createPortal, c as createRoot, w as dispose, f as events, e as extend, h as flushGlobalEffects, p as flushSync, v as getRootState, m as invalidate, r as reconciler, d as unmountComponentAtNode, D as useFrame, F as useGraph, z as useInstanceHandle, G as useLoader, A as useStore, C as useThree } from './events-b389eeca.esm.js';
3
3
  import * as React from 'react';
4
4
  import * as THREE from 'three';
5
5
  import useMeasure from 'react-use-measure';
@@ -2,7 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var events = require('../../dist/events-358c3764.cjs.dev.js');
5
+ var events = require('../../dist/events-f19bcc32.cjs.dev.js');
6
6
  var React = require('react');
7
7
  var THREE = require('three');
8
8
  var reactNative = require('react-native');
@@ -2,7 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var events = require('../../dist/events-238e0986.cjs.prod.js');
5
+ var events = require('../../dist/events-583399dd.cjs.prod.js');
6
6
  var React = require('react');
7
7
  var THREE = require('three');
8
8
  var reactNative = require('react-native');
@@ -1,5 +1,5 @@
1
- import { e as extend, u as useBridge, a as useMutableCallback, c as createRoot, b as useIsomorphicLayoutEffect, E as ErrorBoundary, B as Block, d as unmountComponentAtNode, f as createPointerEvents, g as createEvents } from '../../dist/events-5a94e5eb.esm.js';
2
- export { t as ReactThreeFiber, _ as _roots, x as act, k as addAfterEffect, j as addEffect, l as addTail, n as advance, s as applyProps, y as buildGraph, q as context, g as createEvents, o as createPortal, c as createRoot, w as dispose, e as extend, h as flushGlobalEffects, p as flushSync, v as getRootState, m as invalidate, r as reconciler, d as unmountComponentAtNode, D as useFrame, F as useGraph, z as useInstanceHandle, G as useLoader, A as useStore, C as useThree } from '../../dist/events-5a94e5eb.esm.js';
1
+ import { e as extend, u as useBridge, a as useMutableCallback, c as createRoot, b as useIsomorphicLayoutEffect, E as ErrorBoundary, B as Block, d as unmountComponentAtNode, f as createPointerEvents, g as createEvents } from '../../dist/events-b389eeca.esm.js';
2
+ export { t as ReactThreeFiber, _ as _roots, x as act, k as addAfterEffect, j as addEffect, l as addTail, n as advance, s as applyProps, y as buildGraph, q as context, g as createEvents, o as createPortal, c as createRoot, w as dispose, e as extend, h as flushGlobalEffects, p as flushSync, v as getRootState, m as invalidate, r as reconciler, d as unmountComponentAtNode, D as useFrame, F as useGraph, z as useInstanceHandle, G as useLoader, A as useStore, C as useThree } from '../../dist/events-b389eeca.esm.js';
3
3
  import * as React from 'react';
4
4
  import * as THREE from 'three';
5
5
  import { PanResponder, PixelRatio, StyleSheet, View, Platform, Image, NativeModules } from 'react-native';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-three/fiber",
3
- "version": "9.5.0",
3
+ "version": "9.6.1",
4
4
  "description": "A React renderer for Threejs",
5
5
  "keywords": [
6
6
  "react",