@react-three/rapier 1.1.2 → 1.2.0

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.
@@ -77,6 +77,10 @@ export interface RapierContext {
77
77
  * The Rapier physics world
78
78
  */
79
79
  world: World;
80
+ /**
81
+ * overwriting the Rapier physics world with a restored snapshot
82
+ */
83
+ setWorld: (world: World) => void;
80
84
  /**
81
85
  * If the physics simulation is paused
82
86
  */
@@ -7,4 +7,5 @@
7
7
  export declare const createSingletonProxy: <SingletonClass extends object, CreationFn extends () => SingletonClass = () => SingletonClass>(createInstance: CreationFn) => {
8
8
  proxy: SingletonClass;
9
9
  reset: () => void;
10
+ set: (newInstance: SingletonClass) => void;
10
11
  };
@@ -572,7 +572,7 @@ const useMutableCallback = fn => {
572
572
 
573
573
  const useRapier = () => {
574
574
  const rapier = React.useContext(rapierContext);
575
- if (!rapier) throw new Error('react-three-rapier: useRapier must be used within <Physics />!');
575
+ if (!rapier) throw new Error("react-three-rapier: useRapier must be used within <Physics />!");
576
576
  return rapier;
577
577
  };
578
578
  /**
@@ -682,6 +682,10 @@ const createSingletonProxy = createInstance => {
682
682
  const reset = () => {
683
683
  instance = undefined;
684
684
  };
685
+
686
+ const set = newInstance => {
687
+ instance = newInstance;
688
+ };
685
689
  /**
686
690
  * Return the proxy and a reset function
687
691
  */
@@ -689,7 +693,8 @@ const createSingletonProxy = createInstance => {
689
693
 
690
694
  return {
691
695
  proxy,
692
- reset
696
+ reset,
697
+ set
693
698
  };
694
699
  };
695
700
 
@@ -764,7 +769,8 @@ const Physics = props => {
764
769
 
765
770
  const {
766
771
  proxy: worldProxy,
767
- reset: resetWorldProxy
772
+ reset: resetWorldProxy,
773
+ set: setWorldProxy
768
774
  } = useConst(() => createSingletonProxy(() => new rapier.World(vectorArrayToVector3(gravity))));
769
775
  React.useEffect(() => {
770
776
  return () => {
@@ -1020,6 +1026,9 @@ const Physics = props => {
1020
1026
  const context = React.useMemo(() => ({
1021
1027
  rapier,
1022
1028
  world: worldProxy,
1029
+ setWorld: world => {
1030
+ setWorldProxy(world);
1031
+ },
1023
1032
  physicsOptions: {
1024
1033
  colliders,
1025
1034
  gravity
@@ -572,7 +572,7 @@ const useMutableCallback = fn => {
572
572
 
573
573
  const useRapier = () => {
574
574
  const rapier = React.useContext(rapierContext);
575
- if (!rapier) throw new Error('react-three-rapier: useRapier must be used within <Physics />!');
575
+ if (!rapier) throw new Error("react-three-rapier: useRapier must be used within <Physics />!");
576
576
  return rapier;
577
577
  };
578
578
  /**
@@ -682,6 +682,10 @@ const createSingletonProxy = createInstance => {
682
682
  const reset = () => {
683
683
  instance = undefined;
684
684
  };
685
+
686
+ const set = newInstance => {
687
+ instance = newInstance;
688
+ };
685
689
  /**
686
690
  * Return the proxy and a reset function
687
691
  */
@@ -689,7 +693,8 @@ const createSingletonProxy = createInstance => {
689
693
 
690
694
  return {
691
695
  proxy,
692
- reset
696
+ reset,
697
+ set
693
698
  };
694
699
  };
695
700
 
@@ -764,7 +769,8 @@ const Physics = props => {
764
769
 
765
770
  const {
766
771
  proxy: worldProxy,
767
- reset: resetWorldProxy
772
+ reset: resetWorldProxy,
773
+ set: setWorldProxy
768
774
  } = useConst(() => createSingletonProxy(() => new rapier.World(vectorArrayToVector3(gravity))));
769
775
  React.useEffect(() => {
770
776
  return () => {
@@ -1020,6 +1026,9 @@ const Physics = props => {
1020
1026
  const context = React.useMemo(() => ({
1021
1027
  rapier,
1022
1028
  world: worldProxy,
1029
+ setWorld: world => {
1030
+ setWorldProxy(world);
1031
+ },
1023
1032
  physicsOptions: {
1024
1033
  colliders,
1025
1034
  gravity
@@ -547,7 +547,7 @@ const useMutableCallback = fn => {
547
547
 
548
548
  const useRapier = () => {
549
549
  const rapier = useContext(rapierContext);
550
- if (!rapier) throw new Error('react-three-rapier: useRapier must be used within <Physics />!');
550
+ if (!rapier) throw new Error("react-three-rapier: useRapier must be used within <Physics />!");
551
551
  return rapier;
552
552
  };
553
553
  /**
@@ -657,6 +657,10 @@ const createSingletonProxy = createInstance => {
657
657
  const reset = () => {
658
658
  instance = undefined;
659
659
  };
660
+
661
+ const set = newInstance => {
662
+ instance = newInstance;
663
+ };
660
664
  /**
661
665
  * Return the proxy and a reset function
662
666
  */
@@ -664,7 +668,8 @@ const createSingletonProxy = createInstance => {
664
668
 
665
669
  return {
666
670
  proxy,
667
- reset
671
+ reset,
672
+ set
668
673
  };
669
674
  };
670
675
 
@@ -739,7 +744,8 @@ const Physics = props => {
739
744
 
740
745
  const {
741
746
  proxy: worldProxy,
742
- reset: resetWorldProxy
747
+ reset: resetWorldProxy,
748
+ set: setWorldProxy
743
749
  } = useConst(() => createSingletonProxy(() => new rapier.World(vectorArrayToVector3(gravity))));
744
750
  useEffect(() => {
745
751
  return () => {
@@ -995,6 +1001,9 @@ const Physics = props => {
995
1001
  const context = useMemo(() => ({
996
1002
  rapier,
997
1003
  world: worldProxy,
1004
+ setWorld: world => {
1005
+ setWorldProxy(world);
1006
+ },
998
1007
  physicsOptions: {
999
1008
  colliders,
1000
1009
  gravity
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-three/rapier",
3
- "version": "1.1.2",
3
+ "version": "1.2.0",
4
4
  "source": "src/index.ts",
5
5
  "main": "dist/react-three-rapier.cjs.js",
6
6
  "module": "dist/react-three-rapier.esm.js",
package/readme.md CHANGED
@@ -413,7 +413,7 @@ const Scene = () => {
413
413
  // While Rapier's return types need conversion, setting values can be done directly with Three.js types
414
414
  rigidBody.current.setTranslation(position, true);
415
415
  rigidBody.current.setRotation(quaternion, true);
416
- rigidBody.current.setAngVel({ x: 0, y: 2, z: 0 }, true);
416
+ rigidBody.current.setAngvel({ x: 0, y: 2, z: 0 }, true);
417
417
  }
418
418
  }, []);
419
419
 
@@ -812,3 +812,39 @@ Setting `<Physics updateLoop="independent" />` will make the physics simulation
812
812
  <Physics updateLoop="independent">...</Physics>
813
813
  </Canvas>
814
814
  ```
815
+
816
+ ### Snapshots
817
+ The `world` can be serialized as a `Uint8Array` using `world.takeSnapshot()`, see Rapier's docs on [Serialization](https://rapier.rs/docs/user_guides/javascript/serialization/) for more info.
818
+
819
+ The snapshot can be used to construct a new world. In `r3/rapier`, you need to replace the world with this snapshot.
820
+
821
+ > [!NOTE]
822
+ > This only works if the snapshotted world is identical to the restored one. If objects, or the order of creation of objects vary, expect RigidBodies to scramble.
823
+
824
+ ```tsx
825
+ import { useRapier } from '@react-three/rapier';
826
+
827
+ const SnapshottingComponent = () => {
828
+ const { world, setWorld, rapier } = useRapier();
829
+ const worldSnapshot = useRef<Uint8Array>();
830
+
831
+ // Store the snapshot
832
+ const takeSnapshot = () => {
833
+ const snapshot = world.takeSnapshot()
834
+ worldSnapshot.current = snapshot
835
+ }
836
+
837
+ // Create a new World from the snapshot, and replace the current one
838
+ const restoreSnapshot = () => {
839
+ setWorld(rapier.World.restoreSnapshot(worldSnapshot.current))
840
+ }
841
+
842
+ return <>
843
+ <Rigidbody>...</RigidBody>
844
+ <Rigidbody>...</RigidBody>
845
+ <Rigidbody>...</RigidBody>
846
+ <Rigidbody>...</RigidBody>
847
+ <Rigidbody>...</RigidBody>
848
+ </>
849
+ }
850
+ ```