@react-three/rapier 0.11.2 → 0.12.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.
@@ -1,7 +1,7 @@
1
1
  import { ColliderDesc, ActiveEvents, RigidBodyDesc, EventQueue } from '@dimforge/rapier3d-compat';
2
2
  export { CoefficientCombineRule, Collider as RapierCollider, RigidBody as RapierRigidBody } from '@dimforge/rapier3d-compat';
3
3
  import { useFrame, useThree } from '@react-three/fiber';
4
- import React, { useRef, useMemo, useEffect, useContext, useState, memo, createContext, useCallback, forwardRef, useImperativeHandle, useLayoutEffect } from 'react';
4
+ import React$1, { useRef, useMemo, useEffect, useContext, useState, memo, createContext, useCallback, forwardRef, useImperativeHandle, useLayoutEffect } from 'react';
5
5
  import { Quaternion, Euler, Vector3, Object3D, Matrix4, MathUtils, InstancedMesh, BufferAttribute, DynamicDrawUsage } from 'three';
6
6
  import { useAsset } from 'use-asset';
7
7
  import { mergeVertices, VertexNormalsHelper } from 'three-stdlib';
@@ -60,6 +60,12 @@ const vectorArrayToVector3 = arr => {
60
60
  const [x, y, z] = arr;
61
61
  return new Vector3(x, y, z);
62
62
  };
63
+ const tupleToObject = (tuple, keys) => {
64
+ return keys.reduce((obj, key, i) => {
65
+ obj[key] = tuple[i];
66
+ return obj;
67
+ }, {});
68
+ };
63
69
  const rapierVector3ToVector3 = ({
64
70
  x,
65
71
  y,
@@ -217,7 +223,7 @@ const createInstancedRigidBodiesApi = bodiesGetter => ({
217
223
  return bodiesGetter.current().length;
218
224
  }
219
225
 
220
- }); // TODO: Flesh this out
226
+ });
221
227
  const createWorldApi = ref => {
222
228
  return {
223
229
  raw: () => ref.current(),
@@ -250,8 +256,7 @@ const createWorldApi = ref => {
250
256
  },
251
257
  debugRender: () => ref.current().debugRender()
252
258
  };
253
- }; // TODO: Broken currently, waiting for Rapier3D to fix
254
-
259
+ };
255
260
  const createJointApi = ref => {
256
261
  return {
257
262
  raw: () => ref.current(),
@@ -725,8 +730,31 @@ const useRigidBodyEvents = (rigidBodyRef, props, events) => {
725
730
  };
726
731
 
727
732
  const useRapier = () => {
728
- 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
+ }, []);
729
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
+
730
758
  const useChildColliderProps = (ref, options, ignoreMeshColliders = true) => {
731
759
  const [colliderProps, setColliderProps] = useState([]);
732
760
  useEffect(() => {
@@ -790,107 +818,6 @@ const useRigidBody = (options = {}) => {
790
818
  useRigidBodyEvents(rigidBodyRef, mergedOptions, rigidBodyEvents);
791
819
  const api = useMemo(() => createRigidBodyApi(getRigidBodyRef), []);
792
820
  return [ref, api, childColliderProps];
793
- }; // Joints
794
-
795
- const useImpulseJoint = (body1, body2, params) => {
796
- const {
797
- world
798
- } = useRapier();
799
- const jointRef = useRef();
800
- const getJointRef = useRef(() => {
801
- if (!jointRef.current) {
802
- let rb1;
803
- let rb2;
804
-
805
- if ("current" in body1 && body1.current && "current" in body2 && body2.current) {
806
- rb1 = world.getRigidBody(body1.current.handle);
807
- rb2 = world.getRigidBody(body2.current.handle);
808
- const newJoint = world.createImpulseJoint(params, rb1, rb2);
809
- jointRef.current = newJoint;
810
- }
811
- }
812
-
813
- return jointRef.current;
814
- });
815
- useEffect(() => {
816
- const joint = getJointRef.current();
817
- return () => {
818
- if (joint) {
819
- world.removeImpulseJoint(joint);
820
- jointRef.current = undefined;
821
- }
822
- };
823
- }, []);
824
- const api = useMemo(() => createJointApi(getJointRef), []);
825
- return api;
826
- };
827
- /**
828
- *
829
- * A fixed joint ensures that two rigid-bodies don't move relative to each other.
830
- * Fixed joints are characterized by one local frame (represented by an isometry) on each rigid-body.
831
- * The fixed-joint makes these frames coincide in world-space.
832
- */
833
-
834
- const useFixedJoint = (body1, body2, [body1Anchor, body1LocalFrame, body2Anchor, body2LocalFrame]) => {
835
- const {
836
- rapier
837
- } = useRapier();
838
- return useImpulseJoint(body1, body2, rapier.JointData.fixed(vectorArrayToVector3(body1Anchor), _objectSpread2(_objectSpread2({}, vectorArrayToVector3(body1LocalFrame)), {}, {
839
- w: 1
840
- }), vectorArrayToVector3(body2Anchor), _objectSpread2(_objectSpread2({}, vectorArrayToVector3(body2LocalFrame)), {}, {
841
- w: 1
842
- })));
843
- };
844
- /**
845
- * The spherical joint ensures that two points on the local-spaces of two rigid-bodies always coincide (it prevents any relative
846
- * translational motion at this points). This is typically used to simulate ragdolls arms, pendulums, etc.
847
- * They are characterized by one local anchor on each rigid-body. Each anchor represents the location of the
848
- * points that need to coincide on the local-space of each rigid-body.
849
- */
850
-
851
- const useSphericalJoint = (body1, body2, [body1Anchor, body2Anchor]) => {
852
- const {
853
- rapier
854
- } = useRapier();
855
- return useImpulseJoint(body1, body2, rapier.JointData.spherical(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor)));
856
- };
857
- /**
858
- * The revolute joint prevents any relative movement between two rigid-bodies, except for relative
859
- * rotations along one axis. This is typically used to simulate wheels, fans, etc.
860
- * They are characterized by one local anchor as well as one local axis on each rigid-body.
861
- */
862
-
863
- const useRevoluteJoint = (body1, body2, [body1Anchor, body2Anchor, axis, limits]) => {
864
- const {
865
- rapier
866
- } = useRapier();
867
- const params = rapier.JointData.revolute(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor), vectorArrayToVector3(axis));
868
-
869
- if (limits) {
870
- params.limitsEnabled = true;
871
- params.limits = limits;
872
- }
873
-
874
- return useImpulseJoint(body1, body2, params);
875
- };
876
- /**
877
- * The prismatic joint prevents any relative movement between two rigid-bodies, except for relative translations along one axis.
878
- * It is characterized by one local anchor as well as one local axis on each rigid-body. In 3D, an optional
879
- * local tangent axis can be specified for each rigid-body.
880
- */
881
-
882
- const usePrismaticJoint = (body1, body2, [body1Anchor, body2Anchor, axis, limits]) => {
883
- const {
884
- rapier
885
- } = useRapier();
886
- const params = rapier.JointData.prismatic(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor), vectorArrayToVector3(axis));
887
-
888
- if (limits) {
889
- params.limitsEnabled = true;
890
- params.limits = limits;
891
- }
892
-
893
- return useImpulseJoint(body1, body2, params);
894
821
  };
895
822
 
896
823
  const calcForceByType = {
@@ -972,13 +899,13 @@ const Attractor = /*#__PURE__*/memo(props => {
972
899
  attractorStates.delete(uuid);
973
900
  };
974
901
  }, [props]);
975
- return /*#__PURE__*/React.createElement("object3D", {
902
+ return /*#__PURE__*/React$1.createElement("object3D", {
976
903
  ref: object,
977
904
  position: position
978
905
  });
979
906
  });
980
907
 
981
- const RapierContext = /*#__PURE__*/createContext(undefined);
908
+ const rapierContext = /*#__PURE__*/createContext(undefined);
982
909
 
983
910
  const getCollisionPayloadFromSource = (target, other) => {
984
911
  var _target$collider$stat, _target$rigidBody$sta, _other$collider$state, _other$rigidBody$stat, _other$collider$state2, _other$rigidBody$stat2;
@@ -1033,7 +960,9 @@ const Physics = ({
1033
960
  const rigidBodyEvents = useConst(() => new Map());
1034
961
  const colliderEvents = useConst(() => new Map());
1035
962
  const eventQueue = useConst(() => new EventQueue(false));
1036
- 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
1037
966
 
1038
967
  useEffect(() => {
1039
968
  const world = getWorldRef.current();
@@ -1052,6 +981,7 @@ const Physics = ({
1052
981
  world.gravity = vectorArrayToVector3(_gravity);
1053
982
  }
1054
983
  }, [_gravity]);
984
+ const api = useMemo(() => createWorldApi(getWorldRef), []);
1055
985
  const getSourceFromColliderHandle = useCallback(handle => {
1056
986
  const world = worldRef.current;
1057
987
 
@@ -1098,9 +1028,21 @@ const Physics = ({
1098
1028
 
1099
1029
  const clampedDelta = MathUtils.clamp(dt, 0, 0.2);
1100
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
+
1101
1043
  if (timeStepVariable) {
1102
1044
  world.timestep = clampedDelta;
1103
- world.step(eventQueue);
1045
+ stepWorld();
1104
1046
  } else {
1105
1047
  world.timestep = _timeStep; // don't step time forwards if paused
1106
1048
  // Increase accumulator
@@ -1124,7 +1066,7 @@ const Physics = ({
1124
1066
  applyAttractorForceOnRigidBody(body, attractorState);
1125
1067
  });
1126
1068
  });
1127
- world.step(eventQueue);
1069
+ stepWorld();
1128
1070
  steppingState.accumulator -= _timeStep;
1129
1071
  }
1130
1072
  }
@@ -1287,7 +1229,6 @@ const Physics = ({
1287
1229
  useFrame((_, dt) => {
1288
1230
  if (!_paused) step(dt);
1289
1231
  }, updatePriority);
1290
- const api = useMemo(() => createWorldApi(getWorldRef), []);
1291
1232
  const context = useMemo(() => ({
1292
1233
  rapier,
1293
1234
  world: api,
@@ -1300,10 +1241,12 @@ const Physics = ({
1300
1241
  rigidBodyEvents,
1301
1242
  colliderEvents,
1302
1243
  attractorStates,
1244
+ beforeStepCallbacks,
1245
+ afterStepCallbacks,
1303
1246
  isPaused: _paused,
1304
1247
  step
1305
1248
  }), [_paused, step]);
1306
- return /*#__PURE__*/React.createElement(RapierContext.Provider, {
1249
+ return /*#__PURE__*/React$1.createElement(rapierContext.Provider, {
1307
1250
  value: context
1308
1251
  }, children);
1309
1252
  };
@@ -1360,7 +1303,7 @@ function _objectWithoutProperties(source, excluded) {
1360
1303
  }
1361
1304
 
1362
1305
  // Colliders
1363
- const AnyCollider = /*#__PURE__*/memo( /*#__PURE__*/React.forwardRef((props, forwardedRef) => {
1306
+ const AnyCollider = /*#__PURE__*/memo( /*#__PURE__*/React$1.forwardRef((props, forwardedRef) => {
1364
1307
  const {
1365
1308
  children,
1366
1309
  position,
@@ -1381,7 +1324,7 @@ const AnyCollider = /*#__PURE__*/memo( /*#__PURE__*/React.forwardRef((props, for
1381
1324
  return forwardedRef;
1382
1325
  }
1383
1326
 
1384
- const result = /*#__PURE__*/React.createRef();
1327
+ const result = /*#__PURE__*/React$1.createRef();
1385
1328
  result.current = [];
1386
1329
  return result;
1387
1330
  }, []);
@@ -1422,7 +1365,7 @@ const AnyCollider = /*#__PURE__*/memo( /*#__PURE__*/React.forwardRef((props, for
1422
1365
  }, [props, rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.options]);
1423
1366
  useUpdateColliderOptions(collidersRef, mergedProps, colliderStates);
1424
1367
  useColliderEvents(collidersRef, mergedProps, colliderEvents);
1425
- return /*#__PURE__*/React.createElement("object3D", {
1368
+ return /*#__PURE__*/React$1.createElement("object3D", {
1426
1369
  position: position,
1427
1370
  rotation: rotation,
1428
1371
  quaternion: quaternion,
@@ -1431,56 +1374,56 @@ const AnyCollider = /*#__PURE__*/memo( /*#__PURE__*/React.forwardRef((props, for
1431
1374
  name: name
1432
1375
  }, children);
1433
1376
  }));
1434
- const CuboidCollider = /*#__PURE__*/React.forwardRef((props, ref) => {
1435
- return /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
1377
+ const CuboidCollider = /*#__PURE__*/React$1.forwardRef((props, ref) => {
1378
+ return /*#__PURE__*/React$1.createElement(AnyCollider, _extends({}, props, {
1436
1379
  shape: "cuboid",
1437
1380
  ref: ref
1438
1381
  }));
1439
1382
  });
1440
- const RoundCuboidCollider = /*#__PURE__*/React.forwardRef((props, ref) => {
1441
- return /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
1383
+ const RoundCuboidCollider = /*#__PURE__*/React$1.forwardRef((props, ref) => {
1384
+ return /*#__PURE__*/React$1.createElement(AnyCollider, _extends({}, props, {
1442
1385
  shape: "roundCuboid",
1443
1386
  ref: ref
1444
1387
  }));
1445
1388
  });
1446
- const BallCollider = /*#__PURE__*/React.forwardRef((props, ref) => {
1447
- return /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
1389
+ const BallCollider = /*#__PURE__*/React$1.forwardRef((props, ref) => {
1390
+ return /*#__PURE__*/React$1.createElement(AnyCollider, _extends({}, props, {
1448
1391
  shape: "ball",
1449
1392
  ref: ref
1450
1393
  }));
1451
1394
  });
1452
- const CapsuleCollider = /*#__PURE__*/React.forwardRef((props, ref) => {
1453
- return /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
1395
+ const CapsuleCollider = /*#__PURE__*/React$1.forwardRef((props, ref) => {
1396
+ return /*#__PURE__*/React$1.createElement(AnyCollider, _extends({}, props, {
1454
1397
  shape: "capsule",
1455
1398
  ref: ref
1456
1399
  }));
1457
1400
  });
1458
- const HeightfieldCollider = /*#__PURE__*/React.forwardRef((props, ref) => {
1459
- return /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
1401
+ const HeightfieldCollider = /*#__PURE__*/React$1.forwardRef((props, ref) => {
1402
+ return /*#__PURE__*/React$1.createElement(AnyCollider, _extends({}, props, {
1460
1403
  shape: "heightfield",
1461
1404
  ref: ref
1462
1405
  }));
1463
1406
  });
1464
- const TrimeshCollider = /*#__PURE__*/React.forwardRef((props, ref) => {
1465
- return /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
1407
+ const TrimeshCollider = /*#__PURE__*/React$1.forwardRef((props, ref) => {
1408
+ return /*#__PURE__*/React$1.createElement(AnyCollider, _extends({}, props, {
1466
1409
  shape: "trimesh",
1467
1410
  ref: ref
1468
1411
  }));
1469
1412
  });
1470
- const ConeCollider = /*#__PURE__*/React.forwardRef((props, ref) => {
1471
- return /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
1413
+ const ConeCollider = /*#__PURE__*/React$1.forwardRef((props, ref) => {
1414
+ return /*#__PURE__*/React$1.createElement(AnyCollider, _extends({}, props, {
1472
1415
  shape: "cone",
1473
1416
  ref: ref
1474
1417
  }));
1475
1418
  });
1476
- const CylinderCollider = /*#__PURE__*/React.forwardRef((props, ref) => {
1477
- return /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
1419
+ const CylinderCollider = /*#__PURE__*/React$1.forwardRef((props, ref) => {
1420
+ return /*#__PURE__*/React$1.createElement(AnyCollider, _extends({}, props, {
1478
1421
  shape: "cylinder",
1479
1422
  ref: ref
1480
1423
  }));
1481
1424
  });
1482
- const ConvexHullCollider = /*#__PURE__*/React.forwardRef((props, ref) => {
1483
- return /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
1425
+ const ConvexHullCollider = /*#__PURE__*/React$1.forwardRef((props, ref) => {
1426
+ return /*#__PURE__*/React$1.createElement(AnyCollider, _extends({}, props, {
1484
1427
  shape: "convexHull",
1485
1428
  ref: ref
1486
1429
  }));
@@ -1516,22 +1459,22 @@ const RigidBody = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((props, ref) => {
1516
1459
  api,
1517
1460
  options: props
1518
1461
  }), [object, api, props]);
1519
- return /*#__PURE__*/React.createElement(RigidBodyContext.Provider, {
1462
+ return /*#__PURE__*/React$1.createElement(RigidBodyContext.Provider, {
1520
1463
  value: contextValue
1521
- }, /*#__PURE__*/React.createElement("object3D", _extends({
1464
+ }, /*#__PURE__*/React$1.createElement("object3D", _extends({
1522
1465
  ref: object
1523
1466
  }, objectProps, {
1524
1467
  position: position,
1525
1468
  rotation: rotation,
1526
1469
  quaternion: quaternion,
1527
1470
  scale: scale
1528
- }), children, childColliderProps.map((colliderProps, index) => /*#__PURE__*/React.createElement(AnyCollider, _extends({
1471
+ }), children, childColliderProps.map((colliderProps, index) => /*#__PURE__*/React$1.createElement(AnyCollider, _extends({
1529
1472
  key: index
1530
1473
  }, colliderProps)))));
1531
1474
  }));
1532
1475
  RigidBody.displayName = "RigidBody";
1533
1476
 
1534
- const MeshCollider = props => {
1477
+ const MeshCollider = /*#__PURE__*/memo(props => {
1535
1478
  const {
1536
1479
  children,
1537
1480
  type
@@ -1551,15 +1494,15 @@ const MeshCollider = props => {
1551
1494
  });
1552
1495
  }, [physicsOptions, options]);
1553
1496
  const childColliderProps = useChildColliderProps(object, mergedOptions, false);
1554
- return /*#__PURE__*/React.createElement("object3D", {
1497
+ return /*#__PURE__*/React$1.createElement("object3D", {
1555
1498
  ref: object,
1556
1499
  userData: {
1557
1500
  r3RapierType: "MeshCollider"
1558
1501
  }
1559
- }, children, childColliderProps.map((colliderProps, index) => /*#__PURE__*/React.createElement(AnyCollider, _extends({
1502
+ }, children, childColliderProps.map((colliderProps, index) => /*#__PURE__*/React$1.createElement(AnyCollider, _extends({
1560
1503
  key: index
1561
1504
  }, colliderProps))));
1562
- };
1505
+ });
1563
1506
  MeshCollider.displayName = "MeshCollider";
1564
1507
 
1565
1508
  function mapsEqual(map1, map2) {
@@ -1609,19 +1552,19 @@ const AttractorHelper = props => {
1609
1552
  (_normalsHelper$curren = normalsHelper.current) === null || _normalsHelper$curren === void 0 ? void 0 : _normalsHelper$curren.update();
1610
1553
  }
1611
1554
  });
1612
- return /*#__PURE__*/React.createElement("mesh", {
1555
+ return /*#__PURE__*/React$1.createElement("mesh", {
1613
1556
  ref: ref,
1614
1557
  position: props.object.position,
1615
1558
  frustumCulled: false
1616
- }, /*#__PURE__*/React.createElement("sphereGeometry", {
1559
+ }, /*#__PURE__*/React$1.createElement("sphereGeometry", {
1617
1560
  args: [0.2, 6, 6]
1618
- }), /*#__PURE__*/React.createElement("meshBasicMaterial", {
1561
+ }), /*#__PURE__*/React$1.createElement("meshBasicMaterial", {
1619
1562
  color: color,
1620
1563
  wireframe: true
1621
1564
  }));
1622
1565
  };
1623
1566
 
1624
- const Debug = () => {
1567
+ const Debug = /*#__PURE__*/memo(() => {
1625
1568
  const {
1626
1569
  world,
1627
1570
  attractorStates
@@ -1641,16 +1584,16 @@ const Debug = () => {
1641
1584
  currMap.current = new Map(attractorStates);
1642
1585
  }
1643
1586
  });
1644
- return /*#__PURE__*/React.createElement("group", null, /*#__PURE__*/React.createElement("lineSegments", {
1587
+ return /*#__PURE__*/React$1.createElement("group", null, /*#__PURE__*/React$1.createElement("lineSegments", {
1645
1588
  ref: ref,
1646
1589
  frustumCulled: false
1647
- }, /*#__PURE__*/React.createElement("lineBasicMaterial", {
1590
+ }, /*#__PURE__*/React$1.createElement("lineBasicMaterial", {
1648
1591
  color: 0xffffff,
1649
1592
  vertexColors: true
1650
- }), /*#__PURE__*/React.createElement("bufferGeometry", null)), attractors.map((attractor, i) => /*#__PURE__*/React.createElement(AttractorHelper, _extends({
1593
+ }), /*#__PURE__*/React$1.createElement("bufferGeometry", null)), attractors.map((attractor, i) => /*#__PURE__*/React$1.createElement(AttractorHelper, _extends({
1651
1594
  key: attractor.object.uuid
1652
1595
  }, attractor))));
1653
- };
1596
+ });
1654
1597
 
1655
1598
  const _excluded = ["positions", "rotations", "children"];
1656
1599
  const InstancedRigidBodies = /*#__PURE__*/forwardRef((props, ref) => {
@@ -1764,6 +1707,103 @@ const InstancedRigidBodies = /*#__PURE__*/forwardRef((props, ref) => {
1764
1707
  });
1765
1708
  InstancedRigidBodies.displayName = "InstancedRigidBodies";
1766
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
+
1767
1807
  /**
1768
1808
  * Calculates an InteractionGroup bitmask for use in the `collisionGroups` or `solverGroups`
1769
1809
  * properties of RigidBody or Collider components. The first argument represents a list of
@@ -1800,4 +1840,4 @@ const interactionGroups = (memberships, filters) => (bitmask(memberships) << 16)
1800
1840
 
1801
1841
  const bitmask = groups => [groups].flat().reduce((acc, layer) => acc | 1 << layer, 0);
1802
1842
 
1803
- 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.2",
3
+ "version": "0.12.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",