@react-three/rapier 0.11.3 → 0.12.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.
@@ -223,7 +223,7 @@ const createInstancedRigidBodiesApi = bodiesGetter => ({
223
223
  return bodiesGetter.current().length;
224
224
  }
225
225
 
226
- }); // TODO: Flesh this out
226
+ });
227
227
  const createWorldApi = ref => {
228
228
  return {
229
229
  raw: () => ref.current(),
@@ -256,8 +256,7 @@ const createWorldApi = ref => {
256
256
  },
257
257
  debugRender: () => ref.current().debugRender()
258
258
  };
259
- }; // TODO: Broken currently, waiting for Rapier3D to fix
260
-
259
+ };
261
260
  const createJointApi = ref => {
262
261
  return {
263
262
  raw: () => ref.current(),
@@ -731,8 +730,31 @@ const useRigidBodyEvents = (rigidBodyRef, props, events) => {
731
730
  };
732
731
 
733
732
  const useRapier = () => {
734
- return useContext(RapierContext);
733
+ return useContext(rapierContext);
734
+ };
735
+ const useBeforePhysicsStep = callback => {
736
+ const {
737
+ beforeStepCallbacks
738
+ } = useRapier();
739
+ useEffect(() => {
740
+ beforeStepCallbacks.add(callback);
741
+ return () => {
742
+ beforeStepCallbacks.delete(callback);
743
+ };
744
+ }, []);
735
745
  };
746
+ const useAfterPhysicsStep = callback => {
747
+ const {
748
+ afterStepCallbacks
749
+ } = useRapier();
750
+ useEffect(() => {
751
+ afterStepCallbacks.add(callback);
752
+ return () => {
753
+ afterStepCallbacks.delete(callback);
754
+ };
755
+ }, []);
756
+ }; // Internal hooks
757
+
736
758
  const useChildColliderProps = (ref, options, ignoreMeshColliders = true) => {
737
759
  const [colliderProps, setColliderProps] = useState([]);
738
760
  useEffect(() => {
@@ -796,103 +818,6 @@ const useRigidBody = (options = {}) => {
796
818
  useRigidBodyEvents(rigidBodyRef, mergedOptions, rigidBodyEvents);
797
819
  const api = useMemo(() => createRigidBodyApi(getRigidBodyRef), []);
798
820
  return [ref, api, childColliderProps];
799
- }; // Joints
800
-
801
- const useImpulseJoint = (body1, body2, params) => {
802
- const {
803
- world
804
- } = useRapier();
805
- const jointRef = useRef();
806
- const getJointRef = useRef(() => {
807
- if (!jointRef.current) {
808
- let rb1;
809
- let rb2;
810
-
811
- if ("current" in body1 && body1.current && "current" in body2 && body2.current) {
812
- rb1 = world.getRigidBody(body1.current.handle);
813
- rb2 = world.getRigidBody(body2.current.handle);
814
- const newJoint = world.createImpulseJoint(params, rb1, rb2);
815
- jointRef.current = newJoint;
816
- }
817
- }
818
-
819
- return jointRef.current;
820
- });
821
- useEffect(() => {
822
- const joint = getJointRef.current();
823
- return () => {
824
- if (joint) {
825
- world.removeImpulseJoint(joint);
826
- jointRef.current = undefined;
827
- }
828
- };
829
- }, []);
830
- const api = useMemo(() => createJointApi(getJointRef), []);
831
- return api;
832
- };
833
- /**
834
- *
835
- * A fixed joint ensures that two rigid-bodies don't move relative to each other.
836
- * Fixed joints are characterized by one local frame (represented by an isometry) on each rigid-body.
837
- * The fixed-joint makes these frames coincide in world-space.
838
- */
839
-
840
- const useFixedJoint = (body1, body2, [body1Anchor, body1LocalFrame, body2Anchor, body2LocalFrame]) => {
841
- const {
842
- rapier
843
- } = useRapier();
844
- return useImpulseJoint(body1, body2, rapier.JointData.fixed(vectorArrayToVector3(body1Anchor), tupleToObject(body1LocalFrame, ["x", "y", "z", "w"]), vectorArrayToVector3(body2Anchor), tupleToObject(body2LocalFrame, ["x", "y", "z", "w"])));
845
- };
846
- /**
847
- * The spherical joint ensures that two points on the local-spaces of two rigid-bodies always coincide (it prevents any relative
848
- * translational motion at this points). This is typically used to simulate ragdolls arms, pendulums, etc.
849
- * They are characterized by one local anchor on each rigid-body. Each anchor represents the location of the
850
- * points that need to coincide on the local-space of each rigid-body.
851
- */
852
-
853
- const useSphericalJoint = (body1, body2, [body1Anchor, body2Anchor]) => {
854
- const {
855
- rapier
856
- } = useRapier();
857
- return useImpulseJoint(body1, body2, rapier.JointData.spherical(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor)));
858
- };
859
- /**
860
- * The revolute joint prevents any relative movement between two rigid-bodies, except for relative
861
- * rotations along one axis. This is typically used to simulate wheels, fans, etc.
862
- * They are characterized by one local anchor as well as one local axis on each rigid-body.
863
- */
864
-
865
- const useRevoluteJoint = (body1, body2, [body1Anchor, body2Anchor, axis, limits]) => {
866
- const {
867
- rapier
868
- } = useRapier();
869
- const params = rapier.JointData.revolute(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor), vectorArrayToVector3(axis));
870
-
871
- if (limits) {
872
- params.limitsEnabled = true;
873
- params.limits = limits;
874
- }
875
-
876
- return useImpulseJoint(body1, body2, params);
877
- };
878
- /**
879
- * The prismatic joint prevents any relative movement between two rigid-bodies, except for relative translations along one axis.
880
- * It is characterized by one local anchor as well as one local axis on each rigid-body. In 3D, an optional
881
- * local tangent axis can be specified for each rigid-body.
882
- */
883
-
884
- const usePrismaticJoint = (body1, body2, [body1Anchor, body2Anchor, axis, limits]) => {
885
- const {
886
- rapier
887
- } = useRapier();
888
- const params = rapier.JointData.prismatic(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor), vectorArrayToVector3(axis));
889
-
890
- if (limits) {
891
- params.limitsEnabled = true;
892
- params.limits = limits;
893
- }
894
-
895
- return useImpulseJoint(body1, body2, params);
896
821
  };
897
822
 
898
823
  const calcForceByType = {
@@ -980,7 +905,7 @@ const Attractor = /*#__PURE__*/memo(props => {
980
905
  });
981
906
  });
982
907
 
983
- const RapierContext = /*#__PURE__*/createContext(undefined);
908
+ const rapierContext = /*#__PURE__*/createContext(undefined);
984
909
 
985
910
  const getCollisionPayloadFromSource = (target, other) => {
986
911
  var _target$collider$stat, _target$rigidBody$sta, _other$collider$state, _other$rigidBody$stat, _other$collider$state2, _other$rigidBody$stat2;
@@ -1035,7 +960,9 @@ const Physics = ({
1035
960
  const rigidBodyEvents = useConst(() => new Map());
1036
961
  const colliderEvents = useConst(() => new Map());
1037
962
  const eventQueue = useConst(() => new EventQueue(false));
1038
- const attractorStates = useConst(() => new Map()); // Init world
963
+ const attractorStates = useConst(() => new Map());
964
+ const beforeStepCallbacks = useConst(() => new Set());
965
+ const afterStepCallbacks = useConst(() => new Set()); // Init world
1039
966
 
1040
967
  useEffect(() => {
1041
968
  const world = getWorldRef.current();
@@ -1054,6 +981,7 @@ const Physics = ({
1054
981
  world.gravity = vectorArrayToVector3(_gravity);
1055
982
  }
1056
983
  }, [_gravity]);
984
+ const api = useMemo(() => createWorldApi(getWorldRef), []);
1057
985
  const getSourceFromColliderHandle = useCallback(handle => {
1058
986
  const world = worldRef.current;
1059
987
 
@@ -1100,9 +1028,21 @@ const Physics = ({
1100
1028
 
1101
1029
  const clampedDelta = MathUtils.clamp(dt, 0, 0.2);
1102
1030
 
1031
+ const stepWorld = () => {
1032
+ // Trigger beforeStep callbacks
1033
+ beforeStepCallbacks.forEach(callback => {
1034
+ callback(api);
1035
+ });
1036
+ world.step(eventQueue); // Trigger afterStep callbacks
1037
+
1038
+ afterStepCallbacks.forEach(callback => {
1039
+ callback(api);
1040
+ });
1041
+ };
1042
+
1103
1043
  if (timeStepVariable) {
1104
1044
  world.timestep = clampedDelta;
1105
- world.step(eventQueue);
1045
+ stepWorld();
1106
1046
  } else {
1107
1047
  world.timestep = _timeStep; // don't step time forwards if paused
1108
1048
  // Increase accumulator
@@ -1126,7 +1066,7 @@ const Physics = ({
1126
1066
  applyAttractorForceOnRigidBody(body, attractorState);
1127
1067
  });
1128
1068
  });
1129
- world.step(eventQueue);
1069
+ stepWorld();
1130
1070
  steppingState.accumulator -= _timeStep;
1131
1071
  }
1132
1072
  }
@@ -1289,7 +1229,6 @@ const Physics = ({
1289
1229
  useFrame((_, dt) => {
1290
1230
  if (!_paused) step(dt);
1291
1231
  }, updatePriority);
1292
- const api = useMemo(() => createWorldApi(getWorldRef), []);
1293
1232
  const context = useMemo(() => ({
1294
1233
  rapier,
1295
1234
  world: api,
@@ -1302,10 +1241,12 @@ const Physics = ({
1302
1241
  rigidBodyEvents,
1303
1242
  colliderEvents,
1304
1243
  attractorStates,
1244
+ beforeStepCallbacks,
1245
+ afterStepCallbacks,
1305
1246
  isPaused: _paused,
1306
1247
  step
1307
1248
  }), [_paused, step]);
1308
- return /*#__PURE__*/React.createElement(RapierContext.Provider, {
1249
+ return /*#__PURE__*/React.createElement(rapierContext.Provider, {
1309
1250
  value: context
1310
1251
  }, children);
1311
1252
  };
@@ -1533,7 +1474,7 @@ const RigidBody = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((props, ref) => {
1533
1474
  }));
1534
1475
  RigidBody.displayName = "RigidBody";
1535
1476
 
1536
- const MeshCollider = props => {
1477
+ const MeshCollider = /*#__PURE__*/memo(props => {
1537
1478
  const {
1538
1479
  children,
1539
1480
  type
@@ -1561,7 +1502,7 @@ const MeshCollider = props => {
1561
1502
  }, children, childColliderProps.map((colliderProps, index) => /*#__PURE__*/React.createElement(AnyCollider, _extends({
1562
1503
  key: index
1563
1504
  }, colliderProps))));
1564
- };
1505
+ });
1565
1506
  MeshCollider.displayName = "MeshCollider";
1566
1507
 
1567
1508
  function mapsEqual(map1, map2) {
@@ -1623,7 +1564,7 @@ const AttractorHelper = props => {
1623
1564
  }));
1624
1565
  };
1625
1566
 
1626
- const Debug = () => {
1567
+ const Debug = /*#__PURE__*/memo(() => {
1627
1568
  const {
1628
1569
  world,
1629
1570
  attractorStates
@@ -1652,7 +1593,7 @@ const Debug = () => {
1652
1593
  }), /*#__PURE__*/React.createElement("bufferGeometry", null)), attractors.map((attractor, i) => /*#__PURE__*/React.createElement(AttractorHelper, _extends({
1653
1594
  key: attractor.object.uuid
1654
1595
  }, attractor))));
1655
- };
1596
+ });
1656
1597
 
1657
1598
  const _excluded = ["positions", "rotations", "children"];
1658
1599
  const InstancedRigidBodies = /*#__PURE__*/forwardRef((props, ref) => {
@@ -1766,6 +1707,103 @@ const InstancedRigidBodies = /*#__PURE__*/forwardRef((props, ref) => {
1766
1707
  });
1767
1708
  InstancedRigidBodies.displayName = "InstancedRigidBodies";
1768
1709
 
1710
+ const useImpulseJoint = (body1, body2, params) => {
1711
+ const {
1712
+ world
1713
+ } = useRapier();
1714
+ const jointRef = useRef();
1715
+ const getJointRef = useRef(() => {
1716
+ if (!jointRef.current) {
1717
+ let rb1;
1718
+ let rb2;
1719
+
1720
+ if ("current" in body1 && body1.current && "current" in body2 && body2.current) {
1721
+ rb1 = world.getRigidBody(body1.current.handle);
1722
+ rb2 = world.getRigidBody(body2.current.handle);
1723
+ const newJoint = world.createImpulseJoint(params, rb1, rb2);
1724
+ jointRef.current = newJoint;
1725
+ }
1726
+ }
1727
+
1728
+ return jointRef.current;
1729
+ });
1730
+ useEffect(() => {
1731
+ const joint = getJointRef.current();
1732
+ return () => {
1733
+ if (joint) {
1734
+ world.removeImpulseJoint(joint);
1735
+ jointRef.current = undefined;
1736
+ }
1737
+ };
1738
+ }, []);
1739
+ const api = useMemo(() => createJointApi(getJointRef), []);
1740
+ return api;
1741
+ };
1742
+ /**
1743
+ *
1744
+ * A fixed joint ensures that two rigid-bodies don't move relative to each other.
1745
+ * Fixed joints are characterized by one local frame (represented by an isometry) on each rigid-body.
1746
+ * The fixed-joint makes these frames coincide in world-space.
1747
+ */
1748
+
1749
+ const useFixedJoint = (body1, body2, [body1Anchor, body1LocalFrame, body2Anchor, body2LocalFrame]) => {
1750
+ const {
1751
+ rapier
1752
+ } = useRapier();
1753
+ return useImpulseJoint(body1, body2, rapier.JointData.fixed(vectorArrayToVector3(body1Anchor), tupleToObject(body1LocalFrame, ["x", "y", "z", "w"]), vectorArrayToVector3(body2Anchor), tupleToObject(body2LocalFrame, ["x", "y", "z", "w"])));
1754
+ };
1755
+ /**
1756
+ * The spherical joint ensures that two points on the local-spaces of two rigid-bodies always coincide (it prevents any relative
1757
+ * translational motion at this points). This is typically used to simulate ragdolls arms, pendulums, etc.
1758
+ * They are characterized by one local anchor on each rigid-body. Each anchor represents the location of the
1759
+ * points that need to coincide on the local-space of each rigid-body.
1760
+ */
1761
+
1762
+ const useSphericalJoint = (body1, body2, [body1Anchor, body2Anchor]) => {
1763
+ const {
1764
+ rapier
1765
+ } = useRapier();
1766
+ return useImpulseJoint(body1, body2, rapier.JointData.spherical(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor)));
1767
+ };
1768
+ /**
1769
+ * The revolute joint prevents any relative movement between two rigid-bodies, except for relative
1770
+ * rotations along one axis. This is typically used to simulate wheels, fans, etc.
1771
+ * They are characterized by one local anchor as well as one local axis on each rigid-body.
1772
+ */
1773
+
1774
+ const useRevoluteJoint = (body1, body2, [body1Anchor, body2Anchor, axis, limits]) => {
1775
+ const {
1776
+ rapier
1777
+ } = useRapier();
1778
+ const params = rapier.JointData.revolute(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor), vectorArrayToVector3(axis));
1779
+
1780
+ if (limits) {
1781
+ params.limitsEnabled = true;
1782
+ params.limits = limits;
1783
+ }
1784
+
1785
+ return useImpulseJoint(body1, body2, params);
1786
+ };
1787
+ /**
1788
+ * The prismatic joint prevents any relative movement between two rigid-bodies, except for relative translations along one axis.
1789
+ * It is characterized by one local anchor as well as one local axis on each rigid-body. In 3D, an optional
1790
+ * local tangent axis can be specified for each rigid-body.
1791
+ */
1792
+
1793
+ const usePrismaticJoint = (body1, body2, [body1Anchor, body2Anchor, axis, limits]) => {
1794
+ const {
1795
+ rapier
1796
+ } = useRapier();
1797
+ const params = rapier.JointData.prismatic(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor), vectorArrayToVector3(axis));
1798
+
1799
+ if (limits) {
1800
+ params.limitsEnabled = true;
1801
+ params.limits = limits;
1802
+ }
1803
+
1804
+ return useImpulseJoint(body1, body2, params);
1805
+ };
1806
+
1769
1807
  /**
1770
1808
  * Calculates an InteractionGroup bitmask for use in the `collisionGroups` or `solverGroups`
1771
1809
  * properties of RigidBody or Collider components. The first argument represents a list of
@@ -1802,4 +1840,4 @@ const interactionGroups = (memberships, filters) => (bitmask(memberships) << 16)
1802
1840
 
1803
1841
  const bitmask = groups => [groups].flat().reduce((acc, layer) => acc | 1 << layer, 0);
1804
1842
 
1805
- export { AnyCollider, Attractor, BallCollider, CapsuleCollider, ConeCollider, ConvexHullCollider, CuboidCollider, CylinderCollider, Debug, HeightfieldCollider, InstancedRigidBodies, MeshCollider, Physics, RigidBody, RoundCuboidCollider, TrimeshCollider, interactionGroups, useChildColliderProps, useFixedJoint, useImpulseJoint, usePrismaticJoint, useRapier, useRevoluteJoint, useRigidBody, useSphericalJoint };
1843
+ export { AnyCollider, Attractor, BallCollider, CapsuleCollider, ConeCollider, ConvexHullCollider, CuboidCollider, CylinderCollider, Debug, HeightfieldCollider, InstancedRigidBodies, MeshCollider, Physics, RigidBody, RoundCuboidCollider, TrimeshCollider, interactionGroups, useAfterPhysicsStep, useBeforePhysicsStep, useFixedJoint, useImpulseJoint, usePrismaticJoint, useRapier, useRevoluteJoint, useSphericalJoint };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-three/rapier",
3
- "version": "0.11.3",
3
+ "version": "0.12.1",
4
4
  "source": "src/index.ts",
5
5
  "main": "dist/react-three-rapier.cjs.js",
6
6
  "module": "dist/react-three-rapier.esm.js",