@react-three/rapier 0.15.1 → 0.16.0-canary.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.
@@ -1,7 +1,7 @@
1
1
  import { ActiveEvents, ColliderDesc, EventQueue, RigidBodyDesc } 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, useEffect, memo, useMemo, useContext, useState, createContext, useCallback, forwardRef, useImperativeHandle, Fragment } from 'react';
4
+ import React, { useRef, useEffect, memo, useMemo, useContext, useState, useCallback, createContext, forwardRef, Fragment } from 'react';
5
5
  import { Quaternion, Euler, Vector3, Object3D, Matrix4, BufferAttribute, MathUtils, DynamicDrawUsage } from 'three';
6
6
  import { useAsset } from 'use-asset';
7
7
  import { mergeVertices } from 'three-stdlib';
@@ -47,37 +47,37 @@ function _objectSpread2(target) {
47
47
  return target;
48
48
  }
49
49
 
50
- const createWorldApi = ref => {
50
+ const createWorldApi = getWorld => {
51
51
  return {
52
- raw: () => ref.current(),
53
- getCollider: handle => ref.current().getCollider(handle),
54
- getRigidBody: handle => ref.current().getRigidBody(handle),
55
- createRigidBody: desc => ref.current().createRigidBody(desc),
56
- createCollider: (desc, rigidBody) => ref.current().createCollider(desc, rigidBody),
52
+ raw: () => getWorld(),
53
+ getCollider: handle => getWorld().getCollider(handle),
54
+ getRigidBody: handle => getWorld().getRigidBody(handle),
55
+ createRigidBody: desc => getWorld().createRigidBody(desc),
56
+ createCollider: (desc, rigidBody) => getWorld().createCollider(desc, rigidBody),
57
57
  removeRigidBody: rigidBody => {
58
- if (!ref.current().bodies.contains(rigidBody.handle)) return;
59
- ref.current().removeRigidBody(rigidBody);
58
+ if (!getWorld().bodies.contains(rigidBody.handle)) return;
59
+ getWorld().removeRigidBody(rigidBody);
60
60
  },
61
61
  removeCollider: (collider, wakeUp = true) => {
62
- if (!ref.current().colliders.contains(collider.handle)) return;
63
- ref.current().removeCollider(collider, wakeUp);
62
+ if (!getWorld().colliders.contains(collider.handle)) return;
63
+ getWorld().removeCollider(collider, wakeUp);
64
64
  },
65
- createImpulseJoint: (params, rigidBodyA, rigidBodyB, wakeUp = true) => ref.current().createImpulseJoint(params, rigidBodyA, rigidBodyB, wakeUp),
65
+ createImpulseJoint: (params, rigidBodyA, rigidBodyB, wakeUp = true) => getWorld().createImpulseJoint(params, rigidBodyA, rigidBodyB, wakeUp),
66
66
  removeImpulseJoint: (joint, wakeUp = true) => {
67
- if (!ref.current().impulseJoints.contains(joint.handle)) return;
68
- ref.current().removeImpulseJoint(joint, wakeUp);
67
+ if (!getWorld().impulseJoints.contains(joint.handle)) return;
68
+ getWorld().removeImpulseJoint(joint, wakeUp);
69
69
  },
70
- forEachCollider: callback => ref.current().forEachCollider(callback),
70
+ forEachCollider: callback => getWorld().forEachCollider(callback),
71
71
  setGravity: ({
72
72
  x,
73
73
  y,
74
74
  z
75
- }) => ref.current().gravity = {
75
+ }) => getWorld().gravity = {
76
76
  x,
77
77
  y,
78
78
  z
79
79
  },
80
- debugRender: () => ref.current().debugRender()
80
+ debugRender: () => getWorld().debugRender()
81
81
  };
82
82
  };
83
83
 
@@ -270,6 +270,7 @@ const createColliderFromOptions = (options, world, scale, getRigidBody) => {
270
270
  const desc = ColliderDesc[options.shape](...scaledArgs);
271
271
  return world.createCollider(desc, getRigidBody === null || getRigidBody === void 0 ? void 0 : getRigidBody());
272
272
  };
273
+ const immutableColliderOptions = ["shape", "args"];
273
274
  const massPropertiesConflictError = "Please pick ONLY ONE of the `density`, `mass` and `massProperties` options.";
274
275
 
275
276
  const setColliderMassOptions = (collider, options) => {
@@ -318,7 +319,7 @@ const mutableColliderOptions = {
318
319
  restitutionCombineRule: (collider, value) => {
319
320
  collider.setRestitutionCombineRule(value);
320
321
  },
321
- // To make sure the options all mutalbe options are listed
322
+ // To make sure the options all mutable options are listed
322
323
  quaternion: () => {},
323
324
  position: () => {},
324
325
  rotation: () => {},
@@ -380,7 +381,7 @@ const useUpdateColliderOptions = (getCollider, props, states) => {
380
381
  useEffect(() => {
381
382
  const collider = getCollider();
382
383
  setColliderOptions(collider, props, states);
383
- }, mutablePropsAsFlatArray);
384
+ }, [...mutablePropsAsFlatArray, getCollider]);
384
385
  };
385
386
 
386
387
  const isChildOfMeshCollider = child => {
@@ -657,6 +658,33 @@ const Debug = /*#__PURE__*/memo(() => {
657
658
  }), /*#__PURE__*/React.createElement("bufferGeometry", null)));
658
659
  });
659
660
 
661
+ /**
662
+ * Initiate an instance and return a safe getter
663
+ */
664
+
665
+ const useImperativeInstance = (createFn, destroyFn, dependencyList) => {
666
+ const ref = useRef();
667
+ const getInstance = useCallback(() => {
668
+ if (!ref.current) {
669
+ ref.current = createFn();
670
+ }
671
+
672
+ return ref.current;
673
+ }, dependencyList);
674
+ useEffect(() => {
675
+ // Save the destroy function and instance
676
+ const instance = getInstance();
677
+
678
+ const destroy = () => destroyFn(instance);
679
+
680
+ return () => {
681
+ destroy();
682
+ ref.current = undefined;
683
+ };
684
+ }, [getInstance]);
685
+ return getInstance;
686
+ };
687
+
660
688
  const rapierContext = /*#__PURE__*/createContext(undefined);
661
689
 
662
690
  const getCollisionPayloadFromSource = (target, other) => {
@@ -706,77 +734,60 @@ const Physics = ({
706
734
  const rapier = useAsset(importRapier);
707
735
  const {
708
736
  invalidate
709
- } = useThree();
710
- const worldRef = useRef();
711
- const getWorldRef = useRef(() => {
712
- if (!worldRef.current) {
713
- const world = new rapier.World(vectorArrayToVector3(_gravity));
714
- worldRef.current = world;
715
- }
737
+ } = useThree(); // Init World
716
738
 
717
- return worldRef.current;
718
- });
739
+ const getWorld = useImperativeInstance(() => {
740
+ return new rapier.World(vectorArrayToVector3(_gravity));
741
+ }, world => {
742
+ world.free();
743
+ }, []);
719
744
  const rigidBodyStates = useConst(() => new Map());
720
745
  const colliderStates = useConst(() => new Map());
721
746
  const rigidBodyEvents = useConst(() => new Map());
722
747
  const colliderEvents = useConst(() => new Map());
723
748
  const eventQueue = useConst(() => new EventQueue(false));
724
749
  const beforeStepCallbacks = useConst(() => new Set());
725
- const afterStepCallbacks = useConst(() => new Set()); // Init world
726
-
727
- useEffect(() => {
728
- const world = getWorldRef.current();
729
- return () => {
730
- if (world) {
731
- world.free();
732
- worldRef.current = undefined;
733
- }
734
- };
735
- }, []); // Update gravity
750
+ const afterStepCallbacks = useConst(() => new Set()); // Update gravity
736
751
 
737
752
  useEffect(() => {
738
- const world = worldRef.current;
753
+ const world = getWorld();
739
754
 
740
755
  if (world) {
741
756
  world.gravity = vectorArrayToVector3(_gravity);
742
757
  }
743
758
  }, [_gravity]);
744
- const api = useMemo(() => createWorldApi(getWorldRef), []);
759
+ const api = useMemo(() => createWorldApi(getWorld), []);
745
760
  const getSourceFromColliderHandle = useCallback(handle => {
746
- const world = worldRef.current;
747
-
748
- if (world) {
749
- var _collider$parent;
750
-
751
- const collider = world.getCollider(handle);
752
- const colEvents = colliderEvents.get(handle);
753
- const colliderState = colliderStates.get(handle);
754
- const rigidBodyHandle = collider === null || collider === void 0 ? void 0 : (_collider$parent = collider.parent()) === null || _collider$parent === void 0 ? void 0 : _collider$parent.handle;
755
- const rigidBody = rigidBodyHandle !== undefined ? world.getRigidBody(rigidBodyHandle) : undefined;
756
- const rbEvents = rigidBody && rigidBodyHandle !== undefined ? rigidBodyEvents.get(rigidBodyHandle) : undefined;
757
- const rigidBodyState = rigidBodyHandle !== undefined ? rigidBodyStates.get(rigidBodyHandle) : undefined;
758
- const source = {
759
- collider: {
760
- object: collider,
761
- events: colEvents,
762
- state: colliderState
763
- },
764
- rigidBody: {
765
- object: rigidBody,
766
- events: rbEvents,
767
- state: rigidBodyState
768
- }
769
- };
770
- return source;
771
- }
761
+ var _collider$parent;
762
+
763
+ const world = getWorld();
764
+ const collider = world.getCollider(handle);
765
+ const colEvents = colliderEvents.get(handle);
766
+ const colliderState = colliderStates.get(handle);
767
+ const rigidBodyHandle = collider === null || collider === void 0 ? void 0 : (_collider$parent = collider.parent()) === null || _collider$parent === void 0 ? void 0 : _collider$parent.handle;
768
+ const rigidBody = rigidBodyHandle !== undefined ? world.getRigidBody(rigidBodyHandle) : undefined;
769
+ const rbEvents = rigidBody && rigidBodyHandle !== undefined ? rigidBodyEvents.get(rigidBodyHandle) : undefined;
770
+ const rigidBodyState = rigidBodyHandle !== undefined ? rigidBodyStates.get(rigidBodyHandle) : undefined;
771
+ const source = {
772
+ collider: {
773
+ object: collider,
774
+ events: colEvents,
775
+ state: colliderState
776
+ },
777
+ rigidBody: {
778
+ object: rigidBody,
779
+ events: rbEvents,
780
+ state: rigidBodyState
781
+ }
782
+ };
783
+ return source;
772
784
  }, []);
773
785
  const [steppingState] = useState({
774
786
  previousState: {},
775
787
  accumulator: 0
776
788
  });
777
789
  const step = useCallback(dt => {
778
- const world = worldRef.current;
779
- if (!world) return;
790
+ const world = getWorld();
780
791
  /* Check if the timestep is supposed to be variable. We'll do this here
781
792
  once so we don't have to string-check every frame. */
782
793
 
@@ -1032,29 +1043,6 @@ function _extends() {
1032
1043
  return _extends.apply(this, arguments);
1033
1044
  }
1034
1045
 
1035
- /**
1036
- * Initiate an instance and return a safe getter
1037
- */
1038
-
1039
- const useImperativeInstance = (createFn, destroyFn) => {
1040
- const ref = useRef();
1041
- const refGetter = useMemo(() => () => {
1042
- if (!ref.current) {
1043
- ref.current = createFn();
1044
- }
1045
-
1046
- return ref.current;
1047
- }, []);
1048
- useEffect(() => {
1049
- const instance = refGetter();
1050
- return () => {
1051
- destroyFn(instance);
1052
- ref.current = undefined;
1053
- };
1054
- }, []);
1055
- return refGetter;
1056
- };
1057
-
1058
1046
  /**
1059
1047
  * Takes an object resembling a Vector3 and returs a Three.Vector3
1060
1048
  * @category Math helpers
@@ -1106,7 +1094,19 @@ const euler = ({
1106
1094
  return new Euler(x, y, z);
1107
1095
  };
1108
1096
 
1109
- // Colliders
1097
+ const useForwardedRef = (forwardedRef, defaultValue = null) => {
1098
+ const innerRef = useRef(defaultValue); // Update the forwarded ref when the inner ref changes
1099
+
1100
+ if (forwardedRef && typeof forwardedRef !== "function") {
1101
+ if (!forwardedRef.current) {
1102
+ forwardedRef.current = innerRef.current;
1103
+ }
1104
+
1105
+ return forwardedRef;
1106
+ }
1107
+
1108
+ return innerRef;
1109
+ };
1110
1110
 
1111
1111
  /**
1112
1112
  * A collider is a shape that can be attached to a rigid body to define its physical properties.
@@ -1127,22 +1127,30 @@ const AnyCollider = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((props, forwarded
1127
1127
  colliderStates
1128
1128
  } = useRapier();
1129
1129
  const rigidBodyContext = useRigidBodyContext();
1130
- const ref = useRef(null);
1130
+ const colliderRef = useForwardedRef(forwardedRef);
1131
+ const objectRef = useRef(null); // We spread the props out here to make sure that the ref is updated when the props change.
1132
+
1133
+ const immutablePropArray = immutableColliderOptions.flatMap(key => Array.isArray(props[key]) ? [...props[key]] : props[key]);
1131
1134
  const getInstance = useImperativeInstance(() => {
1132
- const worldScale = ref.current.getWorldScale(vec3());
1135
+ const worldScale = objectRef.current.getWorldScale(vec3());
1133
1136
  const collider = createColliderFromOptions(props, world, worldScale, rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.getRigidBody);
1137
+
1138
+ if (typeof forwardedRef == "function") {
1139
+ forwardedRef(collider);
1140
+ }
1141
+
1142
+ colliderRef.current = collider;
1134
1143
  return collider;
1135
1144
  }, collider => {
1136
1145
  world.removeCollider(collider);
1137
- });
1146
+ }, [...immutablePropArray, rigidBodyContext]);
1138
1147
  useEffect(() => {
1139
1148
  const collider = getInstance();
1140
- colliderStates.set(collider.handle, createColliderState(collider, ref.current, rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.ref.current));
1149
+ colliderStates.set(collider.handle, createColliderState(collider, objectRef.current, rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.ref.current));
1141
1150
  return () => {
1142
1151
  colliderStates.delete(collider.handle);
1143
1152
  };
1144
- }, []);
1145
- useImperativeHandle(forwardedRef, () => getInstance());
1153
+ }, [getInstance]);
1146
1154
  const mergedProps = useMemo(() => {
1147
1155
  return _objectSpread2(_objectSpread2({}, cleanRigidBodyPropsForCollider(rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.options)), props);
1148
1156
  }, [props, rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.options]);
@@ -1153,7 +1161,7 @@ const AnyCollider = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((props, forwarded
1153
1161
  rotation: rotation,
1154
1162
  quaternion: quaternion,
1155
1163
  scale: scale,
1156
- ref: ref,
1164
+ ref: objectRef,
1157
1165
  name: name
1158
1166
  }, children);
1159
1167
  }));
@@ -1168,102 +1176,106 @@ const CuboidCollider = /*#__PURE__*/React.forwardRef((props, ref) => {
1168
1176
  ref: ref
1169
1177
  }));
1170
1178
  });
1179
+ CuboidCollider.displayName = "CuboidCollider";
1180
+
1171
1181
  /**
1172
1182
  * A round cuboid collider shape
1173
1183
  * @category Colliders
1174
1184
  */
1185
+ const RoundCuboidCollider = /*#__PURE__*/React.forwardRef((props, ref) => /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
1186
+ shape: "roundCuboid",
1187
+ ref: ref
1188
+ })));
1189
+ RoundCuboidCollider.displayName = "RoundCuboidCollider";
1175
1190
 
1176
- const RoundCuboidCollider = /*#__PURE__*/React.forwardRef((props, ref) => {
1177
- return /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
1178
- shape: "roundCuboid",
1179
- ref: ref
1180
- }));
1181
- });
1182
1191
  /**
1183
1192
  * A ball collider shape
1184
1193
  * @category Colliders
1185
1194
  */
1195
+ const BallCollider = /*#__PURE__*/React.forwardRef((props, ref) => /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
1196
+ shape: "ball",
1197
+ ref: ref
1198
+ })));
1199
+ BallCollider.displayName = "BallCollider";
1186
1200
 
1187
- const BallCollider = /*#__PURE__*/React.forwardRef((props, ref) => {
1188
- return /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
1189
- shape: "ball",
1190
- ref: ref
1191
- }));
1192
- });
1193
1201
  /**
1194
1202
  * A capsule collider shape
1195
1203
  * @category Colliders
1196
1204
  */
1205
+ const CapsuleCollider = /*#__PURE__*/React.forwardRef((props, ref) => /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
1206
+ shape: "capsule",
1207
+ ref: ref
1208
+ })));
1209
+ CapsuleCollider.displayName = "CapsuleCollider";
1197
1210
 
1198
- const CapsuleCollider = /*#__PURE__*/React.forwardRef((props, ref) => {
1199
- return /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
1200
- shape: "capsule",
1201
- ref: ref
1202
- }));
1203
- });
1204
1211
  /**
1205
1212
  * A heightfield collider shape
1206
1213
  * @category Colliders
1207
1214
  */
1215
+ const HeightfieldCollider = /*#__PURE__*/React.forwardRef((props, ref) => /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
1216
+ shape: "heightfield",
1217
+ ref: ref
1218
+ })));
1219
+ HeightfieldCollider.displayName = "HeightfieldCollider";
1208
1220
 
1209
- const HeightfieldCollider = /*#__PURE__*/React.forwardRef((props, ref) => {
1210
- return /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
1211
- shape: "heightfield",
1212
- ref: ref
1213
- }));
1214
- });
1215
1221
  /**
1216
1222
  * A trimesh collider shape
1217
1223
  * @category Colliders
1218
1224
  */
1225
+ const TrimeshCollider = /*#__PURE__*/React.forwardRef((props, ref) => /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
1226
+ shape: "trimesh",
1227
+ ref: ref
1228
+ })));
1229
+ TrimeshCollider.displayName = "TrimeshCollider";
1219
1230
 
1220
- const TrimeshCollider = /*#__PURE__*/React.forwardRef((props, ref) => {
1221
- return /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
1222
- shape: "trimesh",
1223
- ref: ref
1224
- }));
1225
- });
1226
1231
  /**
1227
1232
  * A cone collider shape
1228
1233
  * @category Colliders
1229
1234
  */
1235
+ const ConeCollider = /*#__PURE__*/React.forwardRef((props, ref) => /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
1236
+ shape: "cone",
1237
+ ref: ref
1238
+ })));
1239
+ ConeCollider.displayName = "ConeCollider";
1240
+
1241
+ /**
1242
+ * A round cylinder collider shape
1243
+ * @category Colliders
1244
+ */
1245
+ const RoundConeCollider = /*#__PURE__*/React.forwardRef((props, ref) => /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
1246
+ shape: "roundCone",
1247
+ ref: ref
1248
+ })));
1249
+ RoundConeCollider.displayName = "RoundConeCollider";
1230
1250
 
1231
- const ConeCollider = /*#__PURE__*/React.forwardRef((props, ref) => {
1232
- return /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
1233
- shape: "cone",
1234
- ref: ref
1235
- }));
1236
- });
1237
1251
  /**
1238
1252
  * A cylinder collider shape
1239
1253
  * @category Colliders
1240
1254
  */
1255
+ const CylinderCollider = /*#__PURE__*/React.forwardRef((props, ref) => /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
1256
+ shape: "cylinder",
1257
+ ref: ref
1258
+ })));
1259
+ CylinderCollider.displayName = "CylinderCollider";
1260
+
1261
+ /**
1262
+ * A round cylinder collider shape
1263
+ * @category Colliders
1264
+ */
1265
+ const RoundCylinderCollider = /*#__PURE__*/React.forwardRef((props, ref) => /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
1266
+ shape: "roundCylinder",
1267
+ ref: ref
1268
+ })));
1269
+ CylinderCollider.displayName = "RoundCylinderCollider";
1241
1270
 
1242
- const CylinderCollider = /*#__PURE__*/React.forwardRef((props, ref) => {
1243
- return /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
1244
- shape: "cylinder",
1245
- ref: ref
1246
- }));
1247
- });
1248
1271
  /**
1249
1272
  * A convex hull collider shape
1250
1273
  * @category Colliders
1251
1274
  */
1252
-
1253
- const ConvexHullCollider = /*#__PURE__*/React.forwardRef((props, ref) => {
1254
- return /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
1255
- shape: "convexHull",
1256
- ref: ref
1257
- }));
1258
- });
1259
- CuboidCollider.displayName = "CuboidCollider";
1260
- RoundCuboidCollider.displayName = "RoundCuboidCollider";
1261
- BallCollider.displayName = "BallCollider";
1262
- CapsuleCollider.displayName = "CapsuleCollider";
1263
- HeightfieldCollider.displayName = "HeightfieldCollider";
1264
- TrimeshCollider.displayName = "TrimeshCollider";
1265
- ConeCollider.displayName = "ConeCollider";
1266
- CylinderCollider.displayName = "CylinderCollider";
1275
+ const ConvexHullCollider = /*#__PURE__*/React.forwardRef((props, ref) => /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
1276
+ shape: "convexHull",
1277
+ ref: ref
1278
+ })));
1267
1279
  ConvexHullCollider.displayName = "ConvexHullCollider";
1268
1280
 
1269
1281
  const rigidBodyDescFromOptions = options => {
@@ -1298,6 +1310,7 @@ const createRigidBodyState = ({
1298
1310
  meshType: _meshType
1299
1311
  };
1300
1312
  };
1313
+ const immutableRigidBodyOptions = ["args", "colliders", "canSleep"];
1301
1314
  const mutableRigidBodyOptions = {
1302
1315
  gravityScale: (rb, value) => {
1303
1316
  rb.setGravityScale(value, true);
@@ -1436,7 +1449,8 @@ const RigidBody = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((props, forwardedRe
1436
1449
  } = props,
1437
1450
  objectProps = _objectWithoutProperties(props, _excluded$1);
1438
1451
 
1439
- const ref = useRef(null);
1452
+ const objectRef = useRef(null);
1453
+ const rigidBodyRef = useForwardedRef(forwardedRef);
1440
1454
  const {
1441
1455
  world,
1442
1456
  rigidBodyStates,
@@ -1448,41 +1462,49 @@ const RigidBody = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((props, forwardedRe
1448
1462
  children: undefined
1449
1463
  });
1450
1464
  }, [physicsOptions, props]);
1451
- const childColliderProps = useChildColliderProps(ref, mergedOptions); // Provide a way to eagerly create rigidbody
1465
+ const immutablePropArray = immutableRigidBodyOptions.flatMap(key => {
1466
+ return Array.isArray(mergedOptions[key]) ? [...mergedOptions[key]] : mergedOptions[key];
1467
+ });
1468
+ const childColliderProps = useChildColliderProps(objectRef, mergedOptions); // Provide a way to eagerly create rigidbody
1452
1469
 
1453
- const getInstance = useImperativeInstance(() => {
1470
+ const getRigidBody = useImperativeInstance(() => {
1454
1471
  const desc = rigidBodyDescFromOptions(mergedOptions);
1455
1472
  const rigidBody = world.createRigidBody(desc);
1473
+
1474
+ if (typeof forwardedRef === "function") {
1475
+ forwardedRef(rigidBody);
1476
+ }
1477
+
1478
+ rigidBodyRef.current = rigidBody;
1456
1479
  return rigidBody;
1457
1480
  }, rigidBody => {
1458
1481
  world.removeRigidBody(rigidBody);
1459
- }); // Only provide a object state after the ref has been set
1482
+ }, immutablePropArray); // Only provide a object state after the ref has been set
1460
1483
 
1461
1484
  useEffect(() => {
1462
- const rigidBody = getInstance();
1485
+ const rigidBody = getRigidBody();
1463
1486
  const state = createRigidBodyState({
1464
1487
  rigidBody,
1465
- object: ref.current
1488
+ object: objectRef.current
1466
1489
  });
1467
1490
  rigidBodyStates.set(rigidBody.handle, props.transformState ? props.transformState(state) : state);
1468
1491
  return () => {
1469
1492
  rigidBodyStates.delete(rigidBody.handle);
1470
1493
  };
1471
- }, []);
1472
- useUpdateRigidBodyOptions(getInstance, mergedOptions, rigidBodyStates);
1473
- useRigidBodyEvents(getInstance, mergedOptions, rigidBodyEvents);
1474
- useImperativeHandle(forwardedRef, () => getInstance());
1494
+ }, [getRigidBody]);
1495
+ useUpdateRigidBodyOptions(getRigidBody, mergedOptions, rigidBodyStates);
1496
+ useRigidBodyEvents(getRigidBody, mergedOptions, rigidBodyEvents);
1475
1497
  const contextValue = useMemo(() => {
1476
1498
  return {
1477
- ref,
1478
- getRigidBody: getInstance,
1499
+ ref: objectRef,
1500
+ getRigidBody: getRigidBody,
1479
1501
  options: mergedOptions
1480
1502
  };
1481
- }, [mergedOptions]);
1503
+ }, [getRigidBody]);
1482
1504
  return /*#__PURE__*/React.createElement(RigidBodyContext.Provider, {
1483
1505
  value: contextValue
1484
1506
  }, /*#__PURE__*/React.createElement("object3D", _extends({
1485
- ref: ref
1507
+ ref: objectRef
1486
1508
  }, objectProps, {
1487
1509
  position: position,
1488
1510
  rotation: rotation,
@@ -1529,9 +1551,10 @@ const MeshCollider = /*#__PURE__*/memo(props => {
1529
1551
  MeshCollider.displayName = "MeshCollider";
1530
1552
 
1531
1553
  const _excluded = ["children", "instances", "colliderNodes", "position", "rotation", "quaternion", "scale"];
1532
- const InstancedRigidBodies = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((props, ref) => {
1533
- const object = useRef(null);
1534
- const instancedWrapper = useRef(null);
1554
+ const InstancedRigidBodies = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((props, forwardedRef) => {
1555
+ const rigidBodiesRef = useForwardedRef(forwardedRef, []);
1556
+ const objectRef = useRef(null);
1557
+ const instanceWrapperRef = useRef(null);
1535
1558
 
1536
1559
  const {
1537
1560
  // instanced props
@@ -1546,14 +1569,12 @@ const InstancedRigidBodies = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((props,
1546
1569
  } = props,
1547
1570
  rigidBodyProps = _objectWithoutProperties(props, _excluded);
1548
1571
 
1549
- const rigidBodyApis = useRef([]);
1550
- useImperativeHandle(ref, () => rigidBodyApis.current, [instances]);
1551
- const childColliderProps = useChildColliderProps(object, _objectSpread2(_objectSpread2({}, props), {}, {
1572
+ const childColliderProps = useChildColliderProps(objectRef, _objectSpread2(_objectSpread2({}, props), {}, {
1552
1573
  children: undefined
1553
1574
  }));
1554
1575
 
1555
1576
  const getInstancedMesh = () => {
1556
- const firstChild = instancedWrapper.current.children[0];
1577
+ const firstChild = instanceWrapperRef.current.children[0];
1557
1578
 
1558
1579
  if (firstChild && "isInstancedMesh" in firstChild) {
1559
1580
  return firstChild;
@@ -1593,16 +1614,16 @@ const InstancedRigidBodies = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((props,
1593
1614
  };
1594
1615
 
1595
1616
  return /*#__PURE__*/React.createElement("object3D", _extends({
1596
- ref: object
1617
+ ref: objectRef
1597
1618
  }, rigidBodyProps, {
1598
1619
  position: position,
1599
1620
  rotation: rotation,
1600
1621
  quaternion: quaternion,
1601
1622
  scale: scale
1602
1623
  }), /*#__PURE__*/React.createElement("object3D", {
1603
- ref: instancedWrapper
1624
+ ref: instanceWrapperRef
1604
1625
  }, children), instances === null || instances === void 0 ? void 0 : instances.map((instance, index) => /*#__PURE__*/React.createElement(RigidBody, _extends({}, rigidBodyProps, instance, {
1605
- ref: body => rigidBodyApis.current[index] = body,
1626
+ ref: body => rigidBodiesRef.current[index] = body,
1606
1627
  transformState: state => applyInstancedState(state, index)
1607
1628
  }), /*#__PURE__*/React.createElement(React.Fragment, null, colliderNodes.map((node, index) => /*#__PURE__*/React.createElement(Fragment, {
1608
1629
  key: index
@@ -1624,7 +1645,8 @@ const useImpulseJoint = (body1, body2, params) => {
1624
1645
  useImperativeInstance(() => {
1625
1646
  if (body1.current && body2.current) {
1626
1647
  const newJoint = world.createImpulseJoint(params, body1.current, body2.current);
1627
- jointRef.current = newJoint;
1648
+ jointRef.current = newJoint; // console.log(body1.current, body2.current, newJoint);
1649
+
1628
1650
  return newJoint;
1629
1651
  }
1630
1652
  }, joint => {
@@ -1632,7 +1654,7 @@ const useImpulseJoint = (body1, body2, params) => {
1632
1654
  jointRef.current = undefined;
1633
1655
  world.removeImpulseJoint(joint);
1634
1656
  }
1635
- });
1657
+ }, []);
1636
1658
  return jointRef;
1637
1659
  };
1638
1660
  /**
@@ -1743,4 +1765,4 @@ const interactionGroups = (memberships, filters) => (bitmask(memberships) << 16)
1743
1765
 
1744
1766
  const bitmask = groups => [groups].flat().reduce((acc, layer) => acc | 1 << layer, 0);
1745
1767
 
1746
- export { AnyCollider, BallCollider, CapsuleCollider, ConeCollider, ConvexHullCollider, CuboidCollider, CylinderCollider, HeightfieldCollider, InstancedRigidBodies, MeshCollider, Physics, RigidBody, RoundCuboidCollider, TrimeshCollider, euler, interactionGroups, quat, useAfterPhysicsStep, useBeforePhysicsStep, useFixedJoint, useImpulseJoint, usePrismaticJoint, useRapier, useRevoluteJoint, useSphericalJoint, vec3 };
1768
+ export { AnyCollider, BallCollider, CapsuleCollider, ConeCollider, ConvexHullCollider, CuboidCollider, CylinderCollider, HeightfieldCollider, InstancedRigidBodies, MeshCollider, Physics, RigidBody, RoundConeCollider, RoundCuboidCollider, RoundCylinderCollider, TrimeshCollider, euler, interactionGroups, quat, useAfterPhysicsStep, useBeforePhysicsStep, useFixedJoint, useImpulseJoint, usePrismaticJoint, useRapier, useRevoluteJoint, useSphericalJoint, vec3 };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-three/rapier",
3
- "version": "0.15.1",
3
+ "version": "0.16.0-canary.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",
package/readme.md CHANGED
@@ -254,7 +254,7 @@ const Scene = () => {
254
254
 
255
255
  // You can access individual instanced by their index
256
256
  rigidBodies.current[40].applyImpulse({ x: 0, y: 10, z: 0 }, true);
257
- rigidBodies.at(100).applyImpulse({ x: 0, y: 10, z: 0 }, true);
257
+ rigidBodies.current.at(100).applyImpulse({ x: 0, y: 10, z: 0 }, true);
258
258
 
259
259
  // Or update all instances
260
260
  rigidBodies.current.forEach((api) => {
@@ -281,7 +281,7 @@ const Scene = () => {
281
281
 
282
282
  return (
283
283
  <InstancedRigidBodies
284
- ref={instancedApi}
284
+ ref={rigidBodies}
285
285
  instances={instances}
286
286
  colliders="ball"
287
287
  >
@@ -314,7 +314,6 @@ const Scene = () => {
314
314
 
315
315
  return (
316
316
  <InstancedRigidBodies
317
- ref={instancedApi}
318
317
  instances={instances}
319
318
  colliders="ball"
320
319
  colliderNodes={[