@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.
@@ -4,7 +4,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var rapier3dCompat = require('@dimforge/rapier3d-compat');
6
6
  var fiber = require('@react-three/fiber');
7
- var React = require('react');
7
+ var React$1 = require('react');
8
8
  var three = require('three');
9
9
  var useAsset = require('use-asset');
10
10
  var threeStdlib = require('three-stdlib');
@@ -29,7 +29,7 @@ function _interopNamespace(e) {
29
29
  return Object.freeze(n);
30
30
  }
31
31
 
32
- var React__default = /*#__PURE__*/_interopDefault(React);
32
+ var React__default = /*#__PURE__*/_interopDefault(React$1);
33
33
 
34
34
  function _defineProperty(obj, key, value) {
35
35
  if (key in obj) {
@@ -85,6 +85,12 @@ const vectorArrayToVector3 = arr => {
85
85
  const [x, y, z] = arr;
86
86
  return new three.Vector3(x, y, z);
87
87
  };
88
+ const tupleToObject = (tuple, keys) => {
89
+ return keys.reduce((obj, key, i) => {
90
+ obj[key] = tuple[i];
91
+ return obj;
92
+ }, {});
93
+ };
88
94
  const rapierVector3ToVector3 = ({
89
95
  x,
90
96
  y,
@@ -132,7 +138,7 @@ const vectorToTuple = v => {
132
138
  return [v];
133
139
  };
134
140
  function useConst(initialValue) {
135
- const ref = React.useRef();
141
+ const ref = React$1.useRef();
136
142
 
137
143
  if (ref.current === undefined) {
138
144
  ref.current = {
@@ -242,7 +248,7 @@ const createInstancedRigidBodiesApi = bodiesGetter => ({
242
248
  return bodiesGetter.current().length;
243
249
  }
244
250
 
245
- }); // TODO: Flesh this out
251
+ });
246
252
  const createWorldApi = ref => {
247
253
  return {
248
254
  raw: () => ref.current(),
@@ -275,8 +281,7 @@ const createWorldApi = ref => {
275
281
  },
276
282
  debugRender: () => ref.current().debugRender()
277
283
  };
278
- }; // TODO: Broken currently, waiting for Rapier3D to fix
279
-
284
+ };
280
285
  const createJointApi = ref => {
281
286
  return {
282
287
  raw: () => ref.current(),
@@ -421,10 +426,10 @@ const setColliderOptions = (collider, options, states) => {
421
426
  };
422
427
  const useUpdateColliderOptions = (collidersRef, props, states) => {
423
428
  // TODO: Improve this, split each prop into its own effect
424
- const mutablePropsAsFlatArray = React.useMemo(() => mutableColliderOptionKeys.flatMap(key => {
429
+ const mutablePropsAsFlatArray = React$1.useMemo(() => mutableColliderOptionKeys.flatMap(key => {
425
430
  return vectorToTuple(props[key]);
426
431
  }), [props]);
427
- React.useEffect(() => {
432
+ React$1.useEffect(() => {
428
433
  collidersRef.current.forEach(collider => {
429
434
  setColliderOptions(collider, props, states);
430
435
  });
@@ -558,7 +563,7 @@ const useColliderEvents = (collidersRef, props, events) => {
558
563
  onIntersectionExit,
559
564
  onContactForce
560
565
  } = props;
561
- React.useEffect(() => {
566
+ React$1.useEffect(() => {
562
567
  var _collidersRef$current;
563
568
 
564
569
  (_collidersRef$current = collidersRef.current) === null || _collidersRef$current === void 0 ? void 0 : _collidersRef$current.forEach(collider => {
@@ -698,10 +703,10 @@ const setRigidBodyOptions = (rigidBody, options, states, updateTranslations = tr
698
703
  };
699
704
  const useUpdateRigidBodyOptions = (rigidBodyRef, props, states, updateTranslations = true) => {
700
705
  // TODO: Improve this, split each prop into its own effect
701
- const mutablePropsAsFlatArray = React.useMemo(() => mutableRigidBodyOptionKeys.flatMap(key => {
706
+ const mutablePropsAsFlatArray = React$1.useMemo(() => mutableRigidBodyOptionKeys.flatMap(key => {
702
707
  return vectorToTuple(props[key]);
703
708
  }), [props]);
704
- React.useEffect(() => {
709
+ React$1.useEffect(() => {
705
710
  if (Array.isArray(rigidBodyRef.current)) {
706
711
  for (const rigidBody of rigidBodyRef.current) {
707
712
  setRigidBodyOptions(rigidBody, props, states, updateTranslations);
@@ -728,7 +733,7 @@ const useRigidBodyEvents = (rigidBodyRef, props, events) => {
728
733
  onIntersectionEnter,
729
734
  onIntersectionExit
730
735
  };
731
- React.useEffect(() => {
736
+ React$1.useEffect(() => {
732
737
  if (Array.isArray(rigidBodyRef.current)) {
733
738
  for (const rigidBody of rigidBodyRef.current) {
734
739
  events.set(rigidBody.handle, eventHandlers);
@@ -750,11 +755,34 @@ const useRigidBodyEvents = (rigidBodyRef, props, events) => {
750
755
  };
751
756
 
752
757
  const useRapier = () => {
753
- return React.useContext(RapierContext);
758
+ return React$1.useContext(rapierContext);
759
+ };
760
+ const useBeforePhysicsStep = callback => {
761
+ const {
762
+ beforeStepCallbacks
763
+ } = useRapier();
764
+ React$1.useEffect(() => {
765
+ beforeStepCallbacks.add(callback);
766
+ return () => {
767
+ beforeStepCallbacks.delete(callback);
768
+ };
769
+ }, []);
754
770
  };
771
+ const useAfterPhysicsStep = callback => {
772
+ const {
773
+ afterStepCallbacks
774
+ } = useRapier();
775
+ React$1.useEffect(() => {
776
+ afterStepCallbacks.add(callback);
777
+ return () => {
778
+ afterStepCallbacks.delete(callback);
779
+ };
780
+ }, []);
781
+ }; // Internal hooks
782
+
755
783
  const useChildColliderProps = (ref, options, ignoreMeshColliders = true) => {
756
- const [colliderProps, setColliderProps] = React.useState([]);
757
- React.useEffect(() => {
784
+ const [colliderProps, setColliderProps] = React$1.useState([]);
785
+ React$1.useEffect(() => {
758
786
  const object = ref.current;
759
787
 
760
788
  if (object && options.colliders !== false) {
@@ -774,16 +802,16 @@ const useRigidBody = (options = {}) => {
774
802
  physicsOptions,
775
803
  rigidBodyEvents
776
804
  } = useRapier();
777
- const ref = React.useRef();
778
- const mergedOptions = React.useMemo(() => {
805
+ const ref = React$1.useRef();
806
+ const mergedOptions = React$1.useMemo(() => {
779
807
  return _objectSpread2(_objectSpread2(_objectSpread2({}, physicsOptions), options), {}, {
780
808
  children: undefined
781
809
  });
782
810
  }, [physicsOptions, options]);
783
811
  const childColliderProps = useChildColliderProps(ref, mergedOptions); // Create rigidbody
784
812
 
785
- const rigidBodyRef = React.useRef();
786
- const getRigidBodyRef = React.useRef(() => {
813
+ const rigidBodyRef = React$1.useRef();
814
+ const getRigidBodyRef = React$1.useRef(() => {
787
815
  if (!rigidBodyRef.current) {
788
816
  const desc = rigidBodyDescFromOptions(options);
789
817
  const rigidBody = world.createRigidBody(desc);
@@ -793,7 +821,7 @@ const useRigidBody = (options = {}) => {
793
821
  return rigidBodyRef.current;
794
822
  }); // Setup
795
823
 
796
- React.useEffect(() => {
824
+ React$1.useEffect(() => {
797
825
  const rigidBody = getRigidBodyRef.current();
798
826
  rigidBodyRef.current = rigidBody;
799
827
 
@@ -813,109 +841,8 @@ const useRigidBody = (options = {}) => {
813
841
  }, []);
814
842
  useUpdateRigidBodyOptions(rigidBodyRef, mergedOptions, rigidBodyStates);
815
843
  useRigidBodyEvents(rigidBodyRef, mergedOptions, rigidBodyEvents);
816
- const api = React.useMemo(() => createRigidBodyApi(getRigidBodyRef), []);
844
+ const api = React$1.useMemo(() => createRigidBodyApi(getRigidBodyRef), []);
817
845
  return [ref, api, childColliderProps];
818
- }; // Joints
819
-
820
- const useImpulseJoint = (body1, body2, params) => {
821
- const {
822
- world
823
- } = useRapier();
824
- const jointRef = React.useRef();
825
- const getJointRef = React.useRef(() => {
826
- if (!jointRef.current) {
827
- let rb1;
828
- let rb2;
829
-
830
- if ("current" in body1 && body1.current && "current" in body2 && body2.current) {
831
- rb1 = world.getRigidBody(body1.current.handle);
832
- rb2 = world.getRigidBody(body2.current.handle);
833
- const newJoint = world.createImpulseJoint(params, rb1, rb2);
834
- jointRef.current = newJoint;
835
- }
836
- }
837
-
838
- return jointRef.current;
839
- });
840
- React.useEffect(() => {
841
- const joint = getJointRef.current();
842
- return () => {
843
- if (joint) {
844
- world.removeImpulseJoint(joint);
845
- jointRef.current = undefined;
846
- }
847
- };
848
- }, []);
849
- const api = React.useMemo(() => createJointApi(getJointRef), []);
850
- return api;
851
- };
852
- /**
853
- *
854
- * A fixed joint ensures that two rigid-bodies don't move relative to each other.
855
- * Fixed joints are characterized by one local frame (represented by an isometry) on each rigid-body.
856
- * The fixed-joint makes these frames coincide in world-space.
857
- */
858
-
859
- const useFixedJoint = (body1, body2, [body1Anchor, body1LocalFrame, body2Anchor, body2LocalFrame]) => {
860
- const {
861
- rapier
862
- } = useRapier();
863
- return useImpulseJoint(body1, body2, rapier.JointData.fixed(vectorArrayToVector3(body1Anchor), _objectSpread2(_objectSpread2({}, vectorArrayToVector3(body1LocalFrame)), {}, {
864
- w: 1
865
- }), vectorArrayToVector3(body2Anchor), _objectSpread2(_objectSpread2({}, vectorArrayToVector3(body2LocalFrame)), {}, {
866
- w: 1
867
- })));
868
- };
869
- /**
870
- * The spherical joint ensures that two points on the local-spaces of two rigid-bodies always coincide (it prevents any relative
871
- * translational motion at this points). This is typically used to simulate ragdolls arms, pendulums, etc.
872
- * They are characterized by one local anchor on each rigid-body. Each anchor represents the location of the
873
- * points that need to coincide on the local-space of each rigid-body.
874
- */
875
-
876
- const useSphericalJoint = (body1, body2, [body1Anchor, body2Anchor]) => {
877
- const {
878
- rapier
879
- } = useRapier();
880
- return useImpulseJoint(body1, body2, rapier.JointData.spherical(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor)));
881
- };
882
- /**
883
- * The revolute joint prevents any relative movement between two rigid-bodies, except for relative
884
- * rotations along one axis. This is typically used to simulate wheels, fans, etc.
885
- * They are characterized by one local anchor as well as one local axis on each rigid-body.
886
- */
887
-
888
- const useRevoluteJoint = (body1, body2, [body1Anchor, body2Anchor, axis, limits]) => {
889
- const {
890
- rapier
891
- } = useRapier();
892
- const params = rapier.JointData.revolute(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor), vectorArrayToVector3(axis));
893
-
894
- if (limits) {
895
- params.limitsEnabled = true;
896
- params.limits = limits;
897
- }
898
-
899
- return useImpulseJoint(body1, body2, params);
900
- };
901
- /**
902
- * The prismatic joint prevents any relative movement between two rigid-bodies, except for relative translations along one axis.
903
- * It is characterized by one local anchor as well as one local axis on each rigid-body. In 3D, an optional
904
- * local tangent axis can be specified for each rigid-body.
905
- */
906
-
907
- const usePrismaticJoint = (body1, body2, [body1Anchor, body2Anchor, axis, limits]) => {
908
- const {
909
- rapier
910
- } = useRapier();
911
- const params = rapier.JointData.prismatic(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor), vectorArrayToVector3(axis));
912
-
913
- if (limits) {
914
- params.limitsEnabled = true;
915
- params.limits = limits;
916
- }
917
-
918
- return useImpulseJoint(body1, body2, params);
919
846
  };
920
847
 
921
848
  const calcForceByType = {
@@ -964,7 +891,7 @@ const applyAttractorForceOnRigidBody = (rigidBody, {
964
891
  }
965
892
  }
966
893
  };
967
- const Attractor = /*#__PURE__*/React.memo(props => {
894
+ const Attractor = /*#__PURE__*/React$1.memo(props => {
968
895
  const {
969
896
  position = [0, 0, 0],
970
897
  strength = 1,
@@ -976,8 +903,8 @@ const Attractor = /*#__PURE__*/React.memo(props => {
976
903
  const {
977
904
  attractorStates
978
905
  } = useRapier();
979
- const object = React.useRef(null);
980
- React.useEffect(() => {
906
+ const object = React$1.useRef(null);
907
+ React$1.useEffect(() => {
981
908
  var _object$current;
982
909
 
983
910
  let uuid = ((_object$current = object.current) === null || _object$current === void 0 ? void 0 : _object$current.uuid) || "_";
@@ -1003,7 +930,7 @@ const Attractor = /*#__PURE__*/React.memo(props => {
1003
930
  });
1004
931
  });
1005
932
 
1006
- const RapierContext = /*#__PURE__*/React.createContext(undefined);
933
+ const rapierContext = /*#__PURE__*/React$1.createContext(undefined);
1007
934
 
1008
935
  const getCollisionPayloadFromSource = (target, other) => {
1009
936
  var _target$collider$stat, _target$rigidBody$sta, _other$collider$state, _other$rigidBody$stat, _other$collider$state2, _other$rigidBody$stat2;
@@ -1044,8 +971,8 @@ const Physics = ({
1044
971
  interpolate: _interpolate = true
1045
972
  }) => {
1046
973
  const rapier = useAsset.useAsset(importRapier);
1047
- const worldRef = React.useRef();
1048
- const getWorldRef = React.useRef(() => {
974
+ const worldRef = React$1.useRef();
975
+ const getWorldRef = React$1.useRef(() => {
1049
976
  if (!worldRef.current) {
1050
977
  const world = new rapier.World(vectorArrayToVector3(_gravity));
1051
978
  worldRef.current = world;
@@ -1058,9 +985,11 @@ const Physics = ({
1058
985
  const rigidBodyEvents = useConst(() => new Map());
1059
986
  const colliderEvents = useConst(() => new Map());
1060
987
  const eventQueue = useConst(() => new rapier3dCompat.EventQueue(false));
1061
- const attractorStates = useConst(() => new Map()); // Init world
988
+ const attractorStates = useConst(() => new Map());
989
+ const beforeStepCallbacks = useConst(() => new Set());
990
+ const afterStepCallbacks = useConst(() => new Set()); // Init world
1062
991
 
1063
- React.useEffect(() => {
992
+ React$1.useEffect(() => {
1064
993
  const world = getWorldRef.current();
1065
994
  return () => {
1066
995
  if (world) {
@@ -1070,14 +999,15 @@ const Physics = ({
1070
999
  };
1071
1000
  }, []); // Update gravity
1072
1001
 
1073
- React.useEffect(() => {
1002
+ React$1.useEffect(() => {
1074
1003
  const world = worldRef.current;
1075
1004
 
1076
1005
  if (world) {
1077
1006
  world.gravity = vectorArrayToVector3(_gravity);
1078
1007
  }
1079
1008
  }, [_gravity]);
1080
- const getSourceFromColliderHandle = React.useCallback(handle => {
1009
+ const api = React$1.useMemo(() => createWorldApi(getWorldRef), []);
1010
+ const getSourceFromColliderHandle = React$1.useCallback(handle => {
1081
1011
  const world = worldRef.current;
1082
1012
 
1083
1013
  if (world) {
@@ -1105,11 +1035,11 @@ const Physics = ({
1105
1035
  return source;
1106
1036
  }
1107
1037
  }, []);
1108
- const [steppingState] = React.useState({
1038
+ const [steppingState] = React$1.useState({
1109
1039
  previousState: {},
1110
1040
  accumulator: 0
1111
1041
  });
1112
- const step = React.useCallback(dt => {
1042
+ const step = React$1.useCallback(dt => {
1113
1043
  const world = worldRef.current;
1114
1044
  if (!world) return;
1115
1045
  /* Check if the timestep is supposed to be variable. We'll do this here
@@ -1123,9 +1053,21 @@ const Physics = ({
1123
1053
 
1124
1054
  const clampedDelta = three.MathUtils.clamp(dt, 0, 0.2);
1125
1055
 
1056
+ const stepWorld = () => {
1057
+ // Trigger beforeStep callbacks
1058
+ beforeStepCallbacks.forEach(callback => {
1059
+ callback(api);
1060
+ });
1061
+ world.step(eventQueue); // Trigger afterStep callbacks
1062
+
1063
+ afterStepCallbacks.forEach(callback => {
1064
+ callback(api);
1065
+ });
1066
+ };
1067
+
1126
1068
  if (timeStepVariable) {
1127
1069
  world.timestep = clampedDelta;
1128
- world.step(eventQueue);
1070
+ stepWorld();
1129
1071
  } else {
1130
1072
  world.timestep = _timeStep; // don't step time forwards if paused
1131
1073
  // Increase accumulator
@@ -1149,7 +1091,7 @@ const Physics = ({
1149
1091
  applyAttractorForceOnRigidBody(body, attractorState);
1150
1092
  });
1151
1093
  });
1152
- world.step(eventQueue);
1094
+ stepWorld();
1153
1095
  steppingState.accumulator -= _timeStep;
1154
1096
  }
1155
1097
  }
@@ -1312,8 +1254,7 @@ const Physics = ({
1312
1254
  fiber.useFrame((_, dt) => {
1313
1255
  if (!_paused) step(dt);
1314
1256
  }, updatePriority);
1315
- const api = React.useMemo(() => createWorldApi(getWorldRef), []);
1316
- const context = React.useMemo(() => ({
1257
+ const context = React$1.useMemo(() => ({
1317
1258
  rapier,
1318
1259
  world: api,
1319
1260
  physicsOptions: {
@@ -1325,10 +1266,12 @@ const Physics = ({
1325
1266
  rigidBodyEvents,
1326
1267
  colliderEvents,
1327
1268
  attractorStates,
1269
+ beforeStepCallbacks,
1270
+ afterStepCallbacks,
1328
1271
  isPaused: _paused,
1329
1272
  step
1330
1273
  }), [_paused, step]);
1331
- return /*#__PURE__*/React__default["default"].createElement(RapierContext.Provider, {
1274
+ return /*#__PURE__*/React__default["default"].createElement(rapierContext.Provider, {
1332
1275
  value: context
1333
1276
  }, children);
1334
1277
  };
@@ -1385,7 +1328,7 @@ function _objectWithoutProperties(source, excluded) {
1385
1328
  }
1386
1329
 
1387
1330
  // Colliders
1388
- const AnyCollider = /*#__PURE__*/React.memo( /*#__PURE__*/React__default["default"].forwardRef((props, forwardedRef) => {
1331
+ const AnyCollider = /*#__PURE__*/React$1.memo( /*#__PURE__*/React__default["default"].forwardRef((props, forwardedRef) => {
1389
1332
  const {
1390
1333
  children,
1391
1334
  position,
@@ -1400,8 +1343,8 @@ const AnyCollider = /*#__PURE__*/React.memo( /*#__PURE__*/React__default["defaul
1400
1343
  colliderStates
1401
1344
  } = useRapier();
1402
1345
  const rigidBodyContext = useRigidBodyContext();
1403
- const ref = React.useRef(null);
1404
- const collidersRef = React.useMemo(() => {
1346
+ const ref = React$1.useRef(null);
1347
+ const collidersRef = React$1.useMemo(() => {
1405
1348
  if (forwardedRef !== null) {
1406
1349
  return forwardedRef;
1407
1350
  }
@@ -1410,7 +1353,7 @@ const AnyCollider = /*#__PURE__*/React.memo( /*#__PURE__*/React__default["defaul
1410
1353
  result.current = [];
1411
1354
  return result;
1412
1355
  }, []);
1413
- React.useEffect(() => {
1356
+ React$1.useEffect(() => {
1414
1357
  const object = ref.current;
1415
1358
  const worldScale = object.getWorldScale(new three.Vector3());
1416
1359
  const colliders = []; // If this is an InstancedRigidBody api
@@ -1442,7 +1385,7 @@ const AnyCollider = /*#__PURE__*/React.memo( /*#__PURE__*/React__default["defaul
1442
1385
  });
1443
1386
  };
1444
1387
  }, []);
1445
- const mergedProps = React.useMemo(() => {
1388
+ const mergedProps = React$1.useMemo(() => {
1446
1389
  return _objectSpread2(_objectSpread2({}, rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.options), props);
1447
1390
  }, [props, rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.options]);
1448
1391
  useUpdateColliderOptions(collidersRef, mergedProps, colliderStates);
@@ -1521,9 +1464,9 @@ CylinderCollider.displayName = "CylinderCollider";
1521
1464
  ConvexHullCollider.displayName = "ConvexHullCollider";
1522
1465
 
1523
1466
  const _excluded$1 = ["children", "type", "position", "rotation", "scale", "quaternion"];
1524
- const RigidBodyContext = /*#__PURE__*/React.createContext(undefined);
1525
- const useRigidBodyContext = () => React.useContext(RigidBodyContext);
1526
- const RigidBody = /*#__PURE__*/React.memo( /*#__PURE__*/React.forwardRef((props, ref) => {
1467
+ const RigidBodyContext = /*#__PURE__*/React$1.createContext(undefined);
1468
+ const useRigidBodyContext = () => React$1.useContext(RigidBodyContext);
1469
+ const RigidBody = /*#__PURE__*/React$1.memo( /*#__PURE__*/React$1.forwardRef((props, ref) => {
1527
1470
  const {
1528
1471
  children,
1529
1472
  type,
@@ -1535,8 +1478,8 @@ const RigidBody = /*#__PURE__*/React.memo( /*#__PURE__*/React.forwardRef((props,
1535
1478
  objectProps = _objectWithoutProperties(props, _excluded$1);
1536
1479
 
1537
1480
  const [object, api, childColliderProps] = useRigidBody(props);
1538
- React.useImperativeHandle(ref, () => api);
1539
- const contextValue = React.useMemo(() => ({
1481
+ React$1.useImperativeHandle(ref, () => api);
1482
+ const contextValue = React$1.useMemo(() => ({
1540
1483
  ref: object,
1541
1484
  api,
1542
1485
  options: props
@@ -1556,7 +1499,7 @@ const RigidBody = /*#__PURE__*/React.memo( /*#__PURE__*/React.forwardRef((props,
1556
1499
  }));
1557
1500
  RigidBody.displayName = "RigidBody";
1558
1501
 
1559
- const MeshCollider = props => {
1502
+ const MeshCollider = /*#__PURE__*/React$1.memo(props => {
1560
1503
  const {
1561
1504
  children,
1562
1505
  type
@@ -1565,11 +1508,11 @@ const MeshCollider = props => {
1565
1508
  physicsOptions,
1566
1509
  world
1567
1510
  } = useRapier();
1568
- const object = React.useRef(null);
1511
+ const object = React$1.useRef(null);
1569
1512
  const {
1570
1513
  options
1571
1514
  } = useRigidBodyContext();
1572
- const mergedOptions = React.useMemo(() => {
1515
+ const mergedOptions = React$1.useMemo(() => {
1573
1516
  return _objectSpread2(_objectSpread2(_objectSpread2({}, physicsOptions), options), {}, {
1574
1517
  children: undefined,
1575
1518
  colliders: type
@@ -1584,7 +1527,7 @@ const MeshCollider = props => {
1584
1527
  }, children, childColliderProps.map((colliderProps, index) => /*#__PURE__*/React__default["default"].createElement(AnyCollider, _extends({
1585
1528
  key: index
1586
1529
  }, colliderProps))));
1587
- };
1530
+ });
1588
1531
  MeshCollider.displayName = "MeshCollider";
1589
1532
 
1590
1533
  function mapsEqual(map1, map2) {
@@ -1609,10 +1552,10 @@ const AttractorHelper = props => {
1609
1552
  const {
1610
1553
  scene
1611
1554
  } = fiber.useThree();
1612
- const ref = React.useRef(null);
1613
- const normalsHelper = React.useRef();
1555
+ const ref = React$1.useRef(null);
1556
+ const normalsHelper = React$1.useRef();
1614
1557
  const color = props.strength > 0 ? 0x0000ff : 0xff0000;
1615
- React.useEffect(() => {
1558
+ React$1.useEffect(() => {
1616
1559
  if (ref.current) {
1617
1560
  normalsHelper.current = new threeStdlib.VertexNormalsHelper(ref.current, props.range, color);
1618
1561
  normalsHelper.current.frustumCulled = false;
@@ -1646,14 +1589,14 @@ const AttractorHelper = props => {
1646
1589
  }));
1647
1590
  };
1648
1591
 
1649
- const Debug = () => {
1592
+ const Debug = /*#__PURE__*/React$1.memo(() => {
1650
1593
  const {
1651
1594
  world,
1652
1595
  attractorStates
1653
1596
  } = useRapier();
1654
- const ref = React.useRef(null);
1655
- const [attractors, setAttractors] = React.useState([]);
1656
- const currMap = React.useRef(new Map());
1597
+ const ref = React$1.useRef(null);
1598
+ const [attractors, setAttractors] = React$1.useState([]);
1599
+ const currMap = React$1.useRef(new Map());
1657
1600
  fiber.useFrame(() => {
1658
1601
  const mesh = ref.current;
1659
1602
  if (!mesh) return;
@@ -1675,17 +1618,17 @@ const Debug = () => {
1675
1618
  }), /*#__PURE__*/React__default["default"].createElement("bufferGeometry", null)), attractors.map((attractor, i) => /*#__PURE__*/React__default["default"].createElement(AttractorHelper, _extends({
1676
1619
  key: attractor.object.uuid
1677
1620
  }, attractor))));
1678
- };
1621
+ });
1679
1622
 
1680
1623
  const _excluded = ["positions", "rotations", "children"];
1681
- const InstancedRigidBodies = /*#__PURE__*/React.forwardRef((props, ref) => {
1624
+ const InstancedRigidBodies = /*#__PURE__*/React$1.forwardRef((props, ref) => {
1682
1625
  const {
1683
1626
  world,
1684
1627
  rigidBodyStates,
1685
1628
  physicsOptions,
1686
1629
  rigidBodyEvents
1687
1630
  } = useRapier();
1688
- const object = React.useRef(null);
1631
+ const object = React$1.useRef(null);
1689
1632
 
1690
1633
  const {
1691
1634
  positions,
@@ -1694,20 +1637,20 @@ const InstancedRigidBodies = /*#__PURE__*/React.forwardRef((props, ref) => {
1694
1637
  } = props,
1695
1638
  options = _objectWithoutProperties(props, _excluded);
1696
1639
 
1697
- const instancesRef = React.useRef([]);
1698
- const rigidBodyRefs = React.useRef([]);
1699
- const instancesRefGetter = React.useRef(() => {
1640
+ const instancesRef = React$1.useRef([]);
1641
+ const rigidBodyRefs = React$1.useRef([]);
1642
+ const instancesRefGetter = React$1.useRef(() => {
1700
1643
  if (!instancesRef.current) {
1701
1644
  instancesRef.current = [];
1702
1645
  }
1703
1646
 
1704
1647
  return instancesRef.current;
1705
1648
  });
1706
- const mergedOptions = React.useMemo(() => {
1649
+ const mergedOptions = React$1.useMemo(() => {
1707
1650
  return _objectSpread2(_objectSpread2({}, physicsOptions), options);
1708
1651
  }, [physicsOptions, options]);
1709
1652
  const childColliderProps = useChildColliderProps(object, mergedOptions);
1710
- React.useLayoutEffect(() => {
1653
+ React$1.useLayoutEffect(() => {
1711
1654
  object.current.updateWorldMatrix(true, false);
1712
1655
  const instances = instancesRefGetter.current();
1713
1656
  const invertedWorld = object.current.matrixWorld.clone().invert();
@@ -1768,27 +1711,124 @@ const InstancedRigidBodies = /*#__PURE__*/React.forwardRef((props, ref) => {
1768
1711
  instancesRef.current = [];
1769
1712
  };
1770
1713
  }, []);
1771
- const api = React.useMemo(() => createInstancedRigidBodiesApi(instancesRefGetter), []);
1772
- React.useImperativeHandle(ref, () => api);
1714
+ const api = React$1.useMemo(() => createInstancedRigidBodiesApi(instancesRefGetter), []);
1715
+ React$1.useImperativeHandle(ref, () => api);
1773
1716
  useUpdateRigidBodyOptions(rigidBodyRefs, mergedOptions, rigidBodyStates, false);
1774
1717
  useRigidBodyEvents(rigidBodyRefs, mergedOptions, rigidBodyEvents);
1775
- const contextValue = React.useMemo(() => {
1718
+ const contextValue = React$1.useMemo(() => {
1776
1719
  return {
1777
1720
  ref: object,
1778
1721
  api,
1779
1722
  options: mergedOptions
1780
1723
  };
1781
1724
  }, [api, mergedOptions]);
1782
- return /*#__PURE__*/React__default["default"].createElement(RigidBodyContext.Provider, {
1725
+ return /*#__PURE__*/React.createElement(RigidBodyContext.Provider, {
1783
1726
  value: contextValue
1784
- }, /*#__PURE__*/React__default["default"].createElement("object3D", {
1727
+ }, /*#__PURE__*/React.createElement("object3D", {
1785
1728
  ref: object
1786
- }, props.children, childColliderProps.map((colliderProps, index) => /*#__PURE__*/React__default["default"].createElement(AnyCollider, _extends({
1729
+ }, props.children, childColliderProps.map((colliderProps, index) => /*#__PURE__*/React.createElement(AnyCollider, _extends({
1787
1730
  key: index
1788
1731
  }, colliderProps)))));
1789
1732
  });
1790
1733
  InstancedRigidBodies.displayName = "InstancedRigidBodies";
1791
1734
 
1735
+ const useImpulseJoint = (body1, body2, params) => {
1736
+ const {
1737
+ world
1738
+ } = useRapier();
1739
+ const jointRef = React$1.useRef();
1740
+ const getJointRef = React$1.useRef(() => {
1741
+ if (!jointRef.current) {
1742
+ let rb1;
1743
+ let rb2;
1744
+
1745
+ if ("current" in body1 && body1.current && "current" in body2 && body2.current) {
1746
+ rb1 = world.getRigidBody(body1.current.handle);
1747
+ rb2 = world.getRigidBody(body2.current.handle);
1748
+ const newJoint = world.createImpulseJoint(params, rb1, rb2);
1749
+ jointRef.current = newJoint;
1750
+ }
1751
+ }
1752
+
1753
+ return jointRef.current;
1754
+ });
1755
+ React$1.useEffect(() => {
1756
+ const joint = getJointRef.current();
1757
+ return () => {
1758
+ if (joint) {
1759
+ world.removeImpulseJoint(joint);
1760
+ jointRef.current = undefined;
1761
+ }
1762
+ };
1763
+ }, []);
1764
+ const api = React$1.useMemo(() => createJointApi(getJointRef), []);
1765
+ return api;
1766
+ };
1767
+ /**
1768
+ *
1769
+ * A fixed joint ensures that two rigid-bodies don't move relative to each other.
1770
+ * Fixed joints are characterized by one local frame (represented by an isometry) on each rigid-body.
1771
+ * The fixed-joint makes these frames coincide in world-space.
1772
+ */
1773
+
1774
+ const useFixedJoint = (body1, body2, [body1Anchor, body1LocalFrame, body2Anchor, body2LocalFrame]) => {
1775
+ const {
1776
+ rapier
1777
+ } = useRapier();
1778
+ return useImpulseJoint(body1, body2, rapier.JointData.fixed(vectorArrayToVector3(body1Anchor), tupleToObject(body1LocalFrame, ["x", "y", "z", "w"]), vectorArrayToVector3(body2Anchor), tupleToObject(body2LocalFrame, ["x", "y", "z", "w"])));
1779
+ };
1780
+ /**
1781
+ * The spherical joint ensures that two points on the local-spaces of two rigid-bodies always coincide (it prevents any relative
1782
+ * translational motion at this points). This is typically used to simulate ragdolls arms, pendulums, etc.
1783
+ * They are characterized by one local anchor on each rigid-body. Each anchor represents the location of the
1784
+ * points that need to coincide on the local-space of each rigid-body.
1785
+ */
1786
+
1787
+ const useSphericalJoint = (body1, body2, [body1Anchor, body2Anchor]) => {
1788
+ const {
1789
+ rapier
1790
+ } = useRapier();
1791
+ return useImpulseJoint(body1, body2, rapier.JointData.spherical(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor)));
1792
+ };
1793
+ /**
1794
+ * The revolute joint prevents any relative movement between two rigid-bodies, except for relative
1795
+ * rotations along one axis. This is typically used to simulate wheels, fans, etc.
1796
+ * They are characterized by one local anchor as well as one local axis on each rigid-body.
1797
+ */
1798
+
1799
+ const useRevoluteJoint = (body1, body2, [body1Anchor, body2Anchor, axis, limits]) => {
1800
+ const {
1801
+ rapier
1802
+ } = useRapier();
1803
+ const params = rapier.JointData.revolute(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor), vectorArrayToVector3(axis));
1804
+
1805
+ if (limits) {
1806
+ params.limitsEnabled = true;
1807
+ params.limits = limits;
1808
+ }
1809
+
1810
+ return useImpulseJoint(body1, body2, params);
1811
+ };
1812
+ /**
1813
+ * The prismatic joint prevents any relative movement between two rigid-bodies, except for relative translations along one axis.
1814
+ * It is characterized by one local anchor as well as one local axis on each rigid-body. In 3D, an optional
1815
+ * local tangent axis can be specified for each rigid-body.
1816
+ */
1817
+
1818
+ const usePrismaticJoint = (body1, body2, [body1Anchor, body2Anchor, axis, limits]) => {
1819
+ const {
1820
+ rapier
1821
+ } = useRapier();
1822
+ const params = rapier.JointData.prismatic(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor), vectorArrayToVector3(axis));
1823
+
1824
+ if (limits) {
1825
+ params.limitsEnabled = true;
1826
+ params.limits = limits;
1827
+ }
1828
+
1829
+ return useImpulseJoint(body1, body2, params);
1830
+ };
1831
+
1792
1832
  /**
1793
1833
  * Calculates an InteractionGroup bitmask for use in the `collisionGroups` or `solverGroups`
1794
1834
  * properties of RigidBody or Collider components. The first argument represents a list of
@@ -1854,11 +1894,11 @@ exports.RigidBody = RigidBody;
1854
1894
  exports.RoundCuboidCollider = RoundCuboidCollider;
1855
1895
  exports.TrimeshCollider = TrimeshCollider;
1856
1896
  exports.interactionGroups = interactionGroups;
1857
- exports.useChildColliderProps = useChildColliderProps;
1897
+ exports.useAfterPhysicsStep = useAfterPhysicsStep;
1898
+ exports.useBeforePhysicsStep = useBeforePhysicsStep;
1858
1899
  exports.useFixedJoint = useFixedJoint;
1859
1900
  exports.useImpulseJoint = useImpulseJoint;
1860
1901
  exports.usePrismaticJoint = usePrismaticJoint;
1861
1902
  exports.useRapier = useRapier;
1862
1903
  exports.useRevoluteJoint = useRevoluteJoint;
1863
- exports.useRigidBody = useRigidBody;
1864
1904
  exports.useSphericalJoint = useSphericalJoint;