@react-three/rapier 0.7.5 → 0.7.7

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.
@@ -17,4 +17,4 @@ export declare const useRigidBodyContext: () => {
17
17
  export interface RigidBodyProps extends UseRigidBodyOptions {
18
18
  children?: ReactNode;
19
19
  }
20
- export declare const RigidBody: React.ForwardRefExoticComponent<RigidBodyProps & React.RefAttributes<import("./api").RigidBodyApi>>;
20
+ export declare const RigidBody: React.MemoExoticComponent<React.ForwardRefExoticComponent<RigidBodyProps & React.RefAttributes<import("./api").RigidBodyApi>>>;
@@ -22,27 +22,27 @@ export interface RigidBodyApi {
22
22
  /**
23
23
  * Applies an impulse at the center-of-mass of this rigid-body.
24
24
  */
25
- applyImpulse(impulseVector: Vector3Object, wakeUp: boolean): void;
25
+ applyImpulse(impulseVector: Vector3Object, wakeUp?: boolean): void;
26
26
  /**
27
27
  * Applies an impulsive torque at the center-of-mass of this rigid-body.
28
28
  */
29
- applyTorqueImpulse(torqueVector: Vector3Object, wakeUp: boolean): void;
29
+ applyTorqueImpulse(torqueVector: Vector3Object, wakeUp?: boolean): void;
30
30
  /**
31
31
  * Applies an impulse at the given world-space point of this rigid-body.
32
32
  */
33
- applyImpulseAtPoint(impulseVector: Vector3Object, impulsePoint: Vector3Object, wakeUp: boolean): void;
33
+ applyImpulseAtPoint(impulseVector: Vector3Object, impulsePoint: Vector3Object, wakeUp?: boolean): void;
34
34
  /**
35
35
  * Adds a force at the center-of-mass of this rigid-body.
36
36
  */
37
- addForce(force: Vector3Object, wakeUp: boolean): void;
37
+ addForce(force: Vector3Object, wakeUp?: boolean): void;
38
38
  /**
39
39
  * Adds a force at the given world-space point of this rigid-body.
40
40
  */
41
- addForceAtPoint(force: Vector3Object, point: Vector3Object, wakeUp: boolean): void;
41
+ addForceAtPoint(force: Vector3Object, point: Vector3Object, wakeUp?: boolean): void;
42
42
  /**
43
43
  * Adds a torque at the center-of-mass of this rigid-body.
44
44
  */
45
- addTorque(torque: Vector3Object, wakeUp: boolean): void;
45
+ addTorque(torque: Vector3Object, wakeUp?: boolean): void;
46
46
  /**
47
47
  * The world-space translation of this rigid-body.
48
48
  */
@@ -50,7 +50,7 @@ export interface RigidBodyApi {
50
50
  /**
51
51
  * Sets the translation of this rigid-body.
52
52
  */
53
- setTranslation(translation: Vector3Object, wakeUp: boolean): void;
53
+ setTranslation(translation: Vector3Object, wakeUp?: boolean): void;
54
54
  /**
55
55
  * The world-space orientation of this rigid-body.
56
56
  */
@@ -58,7 +58,7 @@ export interface RigidBodyApi {
58
58
  /**
59
59
  * Sets the rotation quaternion of this rigid-body.
60
60
  */
61
- setRotation(rotation: Quaternion, wakeUp: boolean): void;
61
+ setRotation(rotation: Quaternion, wakeUp?: boolean): void;
62
62
  /**
63
63
  * The linear velocity of this rigid-body.
64
64
  */
@@ -66,7 +66,7 @@ export interface RigidBodyApi {
66
66
  /**
67
67
  * Sets the linear velocity of this rigid-body.
68
68
  */
69
- setLinvel(velocity: Vector3Object, wakeUp: boolean): void;
69
+ setLinvel(velocity: Vector3Object, wakeUp?: boolean): void;
70
70
  /**
71
71
  * The angular velocity of this rigid-body.
72
72
  */
@@ -74,7 +74,7 @@ export interface RigidBodyApi {
74
74
  /**
75
75
  * Sets the angular velocity of this rigid-body.
76
76
  */
77
- setAngvel(velocity: Vector3Object, wakeUp: boolean): void;
77
+ setAngvel(velocity: Vector3Object, wakeUp?: boolean): void;
78
78
  /**
79
79
  * The linear damping of this rigid-body.
80
80
  */
@@ -101,38 +101,38 @@ export interface RigidBodyApi {
101
101
  */
102
102
  setNextKinematicRotation(rotation: Quaternion): void;
103
103
  /**
104
- * If this rigid body is kinematic, sets its future rotation after the next timestep integration.
104
+ * If this rigid body is kinematic, sets its future translation after the next timestep integration.
105
105
  *
106
- * This should be used instead of rigidBody.setRotation to make the dynamic object interacting with
107
- * this kinematic body behave as expected. Internally, Rapier will compute an artificial velocity
108
- * for this rigid-body from its current position and its next kinematic position. This velocity
109
- * will be used to compute forces on dynamic bodies interacting with this body.
106
+ * This should be used instead of rigidBody.setTranslation to make the dynamic object interacting with
107
+ * this kinematic body behave as expected. Internally, Rapier will compute an artificial velocity
108
+ * for this rigid-body from its current position and its next kinematic position. This velocity
109
+ * will be used to compute forces on dynamic bodies interacting with this body.
110
110
  */
111
111
  setNextKinematicTranslation(translation: Vector3Object): void;
112
112
  /**
113
113
  * Resets to zero the user forces (but not torques) applied to this rigid-body.
114
114
  */
115
- resetForces(wakeUp: boolean): void;
115
+ resetForces(wakeUp?: boolean): void;
116
116
  /**
117
117
  * Resets to zero the user torques applied to this rigid-body.
118
118
  */
119
- resetTorques(wakeUp: boolean): void;
119
+ resetTorques(wakeUp?: boolean): void;
120
120
  /**
121
121
  * Locks or unlocks the ability of this rigid-body to rotate.
122
122
  */
123
- lockRotations(locked: boolean, wakeUp: boolean): void;
123
+ lockRotations(locked: boolean, wakeUp?: boolean): void;
124
124
  /**
125
125
  * Locks or unlocks the ability of this rigid-body to translate.
126
126
  */
127
- lockTranslations(locked: boolean, wakeUp: boolean): void;
127
+ lockTranslations(locked: boolean, wakeUp?: boolean): void;
128
128
  /**
129
129
  * Locks or unlocks the ability of this rigid-body to rotate along individual coordinate axes.
130
130
  */
131
- setEnabledRotations(x: boolean, y: boolean, z: boolean, wakeUp: boolean): void;
131
+ setEnabledRotations(x: boolean, y: boolean, z: boolean, wakeUp?: boolean): void;
132
132
  /**
133
133
  * Locks or unlocks the ability of this rigid-body to translate along individual coordinate axes.
134
134
  */
135
- setEnabledTranslations(x: boolean, y: boolean, z: boolean, wakeUp: boolean): void;
135
+ setEnabledTranslations(x: boolean, y: boolean, z: boolean, wakeUp?: boolean): void;
136
136
  }
137
137
  export declare const createRigidBodyApi: (ref: RefGetter<RigidBody>) => RigidBodyApi;
138
138
  export interface InstancedRigidBodyApi {
@@ -155,9 +155,9 @@ export interface WorldApi {
155
155
  createRigidBody(desc: RigidBodyDesc): RigidBody;
156
156
  createCollider(desc: ColliderDesc, parent?: RigidBody): Collider;
157
157
  removeRigidBody(rigidBody: RigidBody): void;
158
- removeCollider(collider: Collider, wakeUp: boolean): void;
159
- createImpulseJoint(params: JointData, rigidBodyA: RigidBody, rigidBodyB: RigidBody, wakeUp: boolean): ImpulseJoint;
160
- removeImpulseJoint(joint: ImpulseJoint, wakeUp: boolean): void;
158
+ removeCollider(collider: Collider, wakeUp?: boolean): void;
159
+ createImpulseJoint(params: JointData, rigidBodyA: RigidBody, rigidBodyB: RigidBody, wakeUp?: boolean): ImpulseJoint;
160
+ removeImpulseJoint(joint: ImpulseJoint, wakeUp?: boolean): void;
161
161
  forEachCollider(callback: (collider: Collider) => void): void;
162
162
  setGravity(gravity: Vector3): void;
163
163
  }
@@ -31,4 +31,4 @@ import { InteractionGroups } from "@dimforge/rapier3d-compat";
31
31
  * @param filters Groups the interaction group should filter against. (Values can range from 0 to 15.)
32
32
  * @returns An InteractionGroup bitmask.
33
33
  */
34
- export declare const interactionGroups: (memberships: number | number[], filters?: number | number[] | undefined) => InteractionGroups;
34
+ export declare const interactionGroups: (memberships: number | number[], filters?: number | number[]) => InteractionGroups;
@@ -19,7 +19,7 @@ export declare type CuboidArgs = [
19
19
  halfDepth: number
20
20
  ];
21
21
  export declare type BallArgs = [radius: number];
22
- export declare type CapsuleArgs = [radius: number, height: number];
22
+ export declare type CapsuleArgs = [halfHeight: number, radius: number];
23
23
  export declare type ConvexHullArgs = [vertices: ArrayLike<number>];
24
24
  export declare type HeightfieldArgs = [
25
25
  width: number,
@@ -42,16 +42,16 @@ export declare type RoundCuboidArgs = [
42
42
  halfDepth: number,
43
43
  borderRadius: number
44
44
  ];
45
- export declare type CylinderArgs = [radius: number, height: number];
45
+ export declare type CylinderArgs = [halfHeight: number, radius: number];
46
46
  export declare type RoundCylinderArgs = [
47
+ halfHeight: number,
47
48
  radius: number,
48
- height: number,
49
49
  borderRadius: number
50
50
  ];
51
- export declare type ConeArgs = [radius: number, height: number];
51
+ export declare type ConeArgs = [halfHeight: number, radius: number];
52
52
  export declare type RoundConeArgs = [
53
+ halfHeight: number,
53
54
  radius: number,
54
- height: number,
55
55
  borderRadius: number
56
56
  ];
57
57
  export declare type ConvexMeshArgs = [
@@ -14,12 +14,12 @@ export declare const scaleColliderArgs: (shape: ColliderShape, args: (number | A
14
14
  y: number;
15
15
  z: number;
16
16
  })[];
17
- export declare const createColliderFromOptions: (options: ColliderProps, world: WorldApi, scale: Vector3, rigidBody?: RigidBody | undefined) => Collider;
17
+ export declare const createColliderFromOptions: (options: ColliderProps, world: WorldApi, scale: Vector3, rigidBody?: RigidBody) => Collider;
18
18
  declare type ImmutableColliderOptions = (keyof ColliderProps)[];
19
19
  export declare const immutableColliderOptions: ImmutableColliderOptions;
20
20
  export declare const setColliderOptions: (collider: Collider, options: ColliderProps, states: ColliderStateMap) => void;
21
21
  export declare const useUpdateColliderOptions: (collidersRef: MutableRefObject<Collider[]>, props: ColliderProps, states: ColliderStateMap) => void;
22
- export declare const createColliderState: (collider: Collider, object: Object3D, rigidBodyObject?: Object3D<import("three").Event> | null | undefined) => ColliderState;
22
+ export declare const createColliderState: (collider: Collider, object: Object3D, rigidBodyObject?: Object3D | null) => ColliderState;
23
23
  interface CreateColliderPropsFromChildren {
24
24
  (options: {
25
25
  object: Object3D;
@@ -1,9 +1,10 @@
1
1
  import { Quaternion as RapierQuaternion, Vector3 as RapierVector3 } from "@dimforge/rapier3d-compat";
2
- import { Vector3 } from "three";
2
+ import { Euler, Quaternion, Vector3 } from "three";
3
3
  import { RigidBodyTypeString, Vector3Array } from "./types";
4
4
  export declare const vectorArrayToVector3: (arr: Vector3Array) => Vector3;
5
- export declare const vector3ToQuaternion: (v: Vector3) => import("three").Quaternion;
5
+ export declare const vector3ToQuaternion: (v: Vector3) => Quaternion;
6
6
  export declare const rapierVector3ToVector3: ({ x, y, z }: RapierVector3) => Vector3;
7
- export declare const rapierQuaternionToQuaternion: ({ x, y, z, w }: RapierQuaternion) => import("three").Quaternion;
7
+ export declare const rapierQuaternionToQuaternion: ({ x, y, z, w }: RapierQuaternion) => Quaternion;
8
8
  export declare const rigidBodyTypeFromString: (type: RigidBodyTypeString) => number;
9
9
  export declare const scaleVertices: (vertices: ArrayLike<number>, scale: Vector3) => number[];
10
+ export declare const vectorToTuple: (v: Vector3 | Quaternion | any[] | undefined | number | Euler) => any[];
@@ -73,6 +73,23 @@ const scaleVertices = (vertices, scale) => {
73
73
 
74
74
  return scaledVerts;
75
75
  };
76
+ const vectorToTuple = v => {
77
+ if (!v) return [0];
78
+
79
+ if (v instanceof three.Quaternion) {
80
+ return [v.x, v.y, v.z, v.w];
81
+ }
82
+
83
+ if (v instanceof three.Vector3 || v instanceof three.Euler) {
84
+ return [v.x, v.y, v.z];
85
+ }
86
+
87
+ if (Array.isArray(v)) {
88
+ return v;
89
+ }
90
+
91
+ return [v];
92
+ };
76
93
 
77
94
  const createRigidBodyApi = ref => {
78
95
  return {
@@ -181,10 +198,19 @@ const createWorldApi = ref => {
181
198
  getRigidBody: handle => ref.current().getRigidBody(handle),
182
199
  createRigidBody: desc => ref.current().createRigidBody(desc),
183
200
  createCollider: (desc, rigidBody) => ref.current().createCollider(desc, rigidBody),
184
- removeRigidBody: rigidBody => ref.current().removeRigidBody(rigidBody),
185
- removeCollider: (collider, wakeUp = true) => ref.current().removeCollider(collider, wakeUp),
201
+ removeRigidBody: rigidBody => {
202
+ if (!ref.current().bodies.contains(rigidBody.handle)) return;
203
+ ref.current().removeRigidBody(rigidBody);
204
+ },
205
+ removeCollider: (collider, wakeUp = true) => {
206
+ if (!ref.current().colliders.contains(collider.handle)) return;
207
+ ref.current().removeCollider(collider, wakeUp);
208
+ },
186
209
  createImpulseJoint: (params, rigidBodyA, rigidBodyB, wakeUp = true) => ref.current().createImpulseJoint(params, rigidBodyA, rigidBodyB, wakeUp),
187
- removeImpulseJoint: (joint, wakeUp = true) => ref.current().removeImpulseJoint(joint, wakeUp),
210
+ removeImpulseJoint: (joint, wakeUp = true) => {
211
+ if (!ref.current().impulseJoints.contains(joint.handle)) return;
212
+ ref.current().removeImpulseJoint(joint, wakeUp);
213
+ },
188
214
  forEachCollider: callback => ref.current().forEachCollider(callback),
189
215
  setGravity: ({
190
216
  x,
@@ -228,10 +254,6 @@ const Physics = ({
228
254
  updatePriority
229
255
  }) => {
230
256
  const rapier = useAsset.useAsset(importRapier);
231
- const [isPaused, setIsPaused] = React.useState(_paused);
232
- React.useEffect(() => {
233
- setIsPaused(_paused);
234
- }, [_paused]);
235
257
  const worldRef = React.useRef();
236
258
  const getWorldRef = React.useRef(() => {
237
259
  if (!worldRef.current) {
@@ -252,6 +274,7 @@ const Physics = ({
252
274
  return () => {
253
275
  if (world) {
254
276
  world.free();
277
+ worldRef.current = undefined;
255
278
  }
256
279
  };
257
280
  }, []); // Update gravity
@@ -485,15 +508,15 @@ const Physics = ({
485
508
  colliderStates,
486
509
  rigidBodyEvents,
487
510
  colliderEvents,
488
- isPaused
489
- }), [isPaused]);
511
+ isPaused: _paused
512
+ }), [_paused]);
490
513
  return /*#__PURE__*/React__default["default"].createElement(RapierContext.Provider, {
491
514
  value: context
492
515
  }, children);
493
516
  };
494
517
 
495
518
  function _extends() {
496
- _extends = Object.assign || function (target) {
519
+ _extends = Object.assign ? Object.assign.bind() : function (target) {
497
520
  for (var i = 1; i < arguments.length; i++) {
498
521
  var source = arguments[i];
499
522
 
@@ -506,7 +529,6 @@ function _extends() {
506
529
 
507
530
  return target;
508
531
  };
509
-
510
532
  return _extends.apply(this, arguments);
511
533
  }
512
534
 
@@ -643,7 +665,11 @@ const mutableRigidBodyOptions = {
643
665
  },
644
666
  ccd: (rb, value) => {
645
667
  rb.enableCcd(value);
646
- }
668
+ },
669
+ position: () => {},
670
+ rotation: () => {},
671
+ quaternion: () => {},
672
+ scale: () => {}
647
673
  };
648
674
  const mutableRigidBodyOptionKeys = Object.keys(mutableRigidBodyOptions);
649
675
  const setRigidBodyOptions = (rigidBody, options, states, updateTranslations = true) => {
@@ -671,15 +697,19 @@ const setRigidBodyOptions = (rigidBody, options, states, updateTranslations = tr
671
697
  }
672
698
  };
673
699
  const useUpdateRigidBodyOptions = (rigidBodyRef, props, states, updateTranslations = true) => {
700
+ // TODO: Improve this, split each prop into its own effect
701
+ const mutablePropsAsFlatArray = React.useMemo(() => mutableRigidBodyOptionKeys.flatMap(key => {
702
+ return vectorToTuple(props[key]);
703
+ }), [props]);
674
704
  React.useEffect(() => {
675
- if ("length" in rigidBodyRef.current) {
676
- rigidBodyRef.current.forEach(rigidBody => {
705
+ if (Array.isArray(rigidBodyRef.current)) {
706
+ for (const rigidBody of rigidBodyRef.current) {
677
707
  setRigidBodyOptions(rigidBody, props, states, updateTranslations);
678
- });
679
- } else {
708
+ }
709
+ } else if (rigidBodyRef.current) {
680
710
  setRigidBodyOptions(rigidBodyRef.current, props, states, updateTranslations);
681
711
  }
682
- }, [props]);
712
+ }, mutablePropsAsFlatArray);
683
713
  };
684
714
  const useRigidBodyEvents = (rigidBodyRef, props, events) => {
685
715
  const {
@@ -699,24 +729,24 @@ const useRigidBodyEvents = (rigidBodyRef, props, events) => {
699
729
  onIntersectionExit
700
730
  };
701
731
  React.useEffect(() => {
702
- if ("length" in rigidBodyRef.current) {
703
- rigidBodyRef.current.forEach(rigidBody => {
732
+ if (Array.isArray(rigidBodyRef.current)) {
733
+ for (const rigidBody of rigidBodyRef.current) {
704
734
  events.set(rigidBody.handle, eventHandlers);
705
- });
706
- } else {
735
+ }
736
+ } else if (rigidBodyRef.current) {
707
737
  events.set(rigidBodyRef.current.handle, eventHandlers);
708
738
  }
709
739
 
710
740
  return () => {
711
- if ("length" in rigidBodyRef.current) {
712
- rigidBodyRef.current.forEach(rigidBody => {
741
+ if (Array.isArray(rigidBodyRef.current)) {
742
+ for (const rigidBody of rigidBodyRef.current) {
713
743
  events.delete(rigidBody.handle);
714
- });
715
- } else {
744
+ }
745
+ } else if (rigidBodyRef.current) {
716
746
  events.delete(rigidBodyRef.current.handle);
717
747
  }
718
748
  };
719
- }, [onWake, onSleep, onCollisionEnter, onCollisionExit]);
749
+ }, [onWake, onSleep, onCollisionEnter, onCollisionExit, onIntersectionEnter, onIntersectionExit]);
720
750
  };
721
751
 
722
752
  const scaleColliderArgs = (shape, args, scale) => {
@@ -793,7 +823,12 @@ const mutableColliderOptions = {
793
823
  },
794
824
  restitutionCombineRule: (collider, value) => {
795
825
  collider.setRestitutionCombineRule(value);
796
- }
826
+ },
827
+ // To make sure the options all mutalbe options are listed
828
+ quaternion: () => {},
829
+ position: () => {},
830
+ rotation: () => {},
831
+ scale: () => {}
797
832
  };
798
833
  const mutableColliderOptionKeys = Object.keys(mutableColliderOptions);
799
834
  const setColliderOptions = (collider, options, states) => {
@@ -835,11 +870,15 @@ const setColliderOptions = (collider, options, states) => {
835
870
  }
836
871
  };
837
872
  const useUpdateColliderOptions = (collidersRef, props, states) => {
873
+ // TODO: Improve this, split each prop into its own effect
874
+ const mutablePropsAsFlatArray = React.useMemo(() => mutableColliderOptionKeys.flatMap(key => {
875
+ return vectorToTuple(props[key]);
876
+ }), [props]);
838
877
  React.useEffect(() => {
839
878
  collidersRef.current.forEach(collider => {
840
879
  setColliderOptions(collider, props, states);
841
880
  });
842
- }, [props]);
881
+ }, mutablePropsAsFlatArray);
843
882
  };
844
883
 
845
884
  const isChildOfMeshCollider = child => {
@@ -980,7 +1019,7 @@ const useColliderEvents = (collidersRef, props, events) => {
980
1019
 
981
1020
  (_collidersRef$current2 = collidersRef.current) === null || _collidersRef$current2 === void 0 ? void 0 : _collidersRef$current2.forEach(collider => events.delete(collider.handle));
982
1021
  };
983
- }, [onCollisionEnter, onCollisionExit]);
1022
+ }, [onCollisionEnter, onCollisionExit, onIntersectionEnter, onIntersectionExit]);
984
1023
  };
985
1024
 
986
1025
  const useRapier = () => {
@@ -1044,6 +1083,7 @@ const useRigidBody = (options = {}) => {
1044
1083
  return () => {
1045
1084
  world.removeRigidBody(rigidBody);
1046
1085
  rigidBodyStates.delete(rigidBody.handle);
1086
+ rigidBodyRef.current = undefined;
1047
1087
  };
1048
1088
  }, []);
1049
1089
  useUpdateRigidBodyOptions(rigidBodyRef, mergedOptions, rigidBodyStates);
@@ -1267,7 +1307,7 @@ const ConvexHullCollider = /*#__PURE__*/React__default["default"].forwardRef((pr
1267
1307
  const _excluded$1 = ["children", "type", "position", "rotation", "scale", "quaternion"];
1268
1308
  const RigidBodyContext = /*#__PURE__*/React.createContext(undefined);
1269
1309
  const useRigidBodyContext = () => React.useContext(RigidBodyContext);
1270
- const RigidBody = /*#__PURE__*/React.forwardRef((props, ref) => {
1310
+ const RigidBody = /*#__PURE__*/React.memo( /*#__PURE__*/React.forwardRef((props, ref) => {
1271
1311
  const {
1272
1312
  children,
1273
1313
  type,
@@ -1297,7 +1337,7 @@ const RigidBody = /*#__PURE__*/React.forwardRef((props, ref) => {
1297
1337
  }), children, childColliderProps.map((colliderProps, index) => /*#__PURE__*/React__default["default"].createElement(AnyCollider, _extends({
1298
1338
  key: index
1299
1339
  }, colliderProps)))));
1300
- });
1340
+ }));
1301
1341
 
1302
1342
  const MeshCollider = props => {
1303
1343
  const {
@@ -73,6 +73,23 @@ const scaleVertices = (vertices, scale) => {
73
73
 
74
74
  return scaledVerts;
75
75
  };
76
+ const vectorToTuple = v => {
77
+ if (!v) return [0];
78
+
79
+ if (v instanceof three.Quaternion) {
80
+ return [v.x, v.y, v.z, v.w];
81
+ }
82
+
83
+ if (v instanceof three.Vector3 || v instanceof three.Euler) {
84
+ return [v.x, v.y, v.z];
85
+ }
86
+
87
+ if (Array.isArray(v)) {
88
+ return v;
89
+ }
90
+
91
+ return [v];
92
+ };
76
93
 
77
94
  const createRigidBodyApi = ref => {
78
95
  return {
@@ -181,10 +198,19 @@ const createWorldApi = ref => {
181
198
  getRigidBody: handle => ref.current().getRigidBody(handle),
182
199
  createRigidBody: desc => ref.current().createRigidBody(desc),
183
200
  createCollider: (desc, rigidBody) => ref.current().createCollider(desc, rigidBody),
184
- removeRigidBody: rigidBody => ref.current().removeRigidBody(rigidBody),
185
- removeCollider: (collider, wakeUp = true) => ref.current().removeCollider(collider, wakeUp),
201
+ removeRigidBody: rigidBody => {
202
+ if (!ref.current().bodies.contains(rigidBody.handle)) return;
203
+ ref.current().removeRigidBody(rigidBody);
204
+ },
205
+ removeCollider: (collider, wakeUp = true) => {
206
+ if (!ref.current().colliders.contains(collider.handle)) return;
207
+ ref.current().removeCollider(collider, wakeUp);
208
+ },
186
209
  createImpulseJoint: (params, rigidBodyA, rigidBodyB, wakeUp = true) => ref.current().createImpulseJoint(params, rigidBodyA, rigidBodyB, wakeUp),
187
- removeImpulseJoint: (joint, wakeUp = true) => ref.current().removeImpulseJoint(joint, wakeUp),
210
+ removeImpulseJoint: (joint, wakeUp = true) => {
211
+ if (!ref.current().impulseJoints.contains(joint.handle)) return;
212
+ ref.current().removeImpulseJoint(joint, wakeUp);
213
+ },
188
214
  forEachCollider: callback => ref.current().forEachCollider(callback),
189
215
  setGravity: ({
190
216
  x,
@@ -228,10 +254,6 @@ const Physics = ({
228
254
  updatePriority
229
255
  }) => {
230
256
  const rapier = useAsset.useAsset(importRapier);
231
- const [isPaused, setIsPaused] = React.useState(_paused);
232
- React.useEffect(() => {
233
- setIsPaused(_paused);
234
- }, [_paused]);
235
257
  const worldRef = React.useRef();
236
258
  const getWorldRef = React.useRef(() => {
237
259
  if (!worldRef.current) {
@@ -252,6 +274,7 @@ const Physics = ({
252
274
  return () => {
253
275
  if (world) {
254
276
  world.free();
277
+ worldRef.current = undefined;
255
278
  }
256
279
  };
257
280
  }, []); // Update gravity
@@ -485,15 +508,15 @@ const Physics = ({
485
508
  colliderStates,
486
509
  rigidBodyEvents,
487
510
  colliderEvents,
488
- isPaused
489
- }), [isPaused]);
511
+ isPaused: _paused
512
+ }), [_paused]);
490
513
  return /*#__PURE__*/React__default["default"].createElement(RapierContext.Provider, {
491
514
  value: context
492
515
  }, children);
493
516
  };
494
517
 
495
518
  function _extends() {
496
- _extends = Object.assign || function (target) {
519
+ _extends = Object.assign ? Object.assign.bind() : function (target) {
497
520
  for (var i = 1; i < arguments.length; i++) {
498
521
  var source = arguments[i];
499
522
 
@@ -506,7 +529,6 @@ function _extends() {
506
529
 
507
530
  return target;
508
531
  };
509
-
510
532
  return _extends.apply(this, arguments);
511
533
  }
512
534
 
@@ -643,7 +665,11 @@ const mutableRigidBodyOptions = {
643
665
  },
644
666
  ccd: (rb, value) => {
645
667
  rb.enableCcd(value);
646
- }
668
+ },
669
+ position: () => {},
670
+ rotation: () => {},
671
+ quaternion: () => {},
672
+ scale: () => {}
647
673
  };
648
674
  const mutableRigidBodyOptionKeys = Object.keys(mutableRigidBodyOptions);
649
675
  const setRigidBodyOptions = (rigidBody, options, states, updateTranslations = true) => {
@@ -671,15 +697,19 @@ const setRigidBodyOptions = (rigidBody, options, states, updateTranslations = tr
671
697
  }
672
698
  };
673
699
  const useUpdateRigidBodyOptions = (rigidBodyRef, props, states, updateTranslations = true) => {
700
+ // TODO: Improve this, split each prop into its own effect
701
+ const mutablePropsAsFlatArray = React.useMemo(() => mutableRigidBodyOptionKeys.flatMap(key => {
702
+ return vectorToTuple(props[key]);
703
+ }), [props]);
674
704
  React.useEffect(() => {
675
- if ("length" in rigidBodyRef.current) {
676
- rigidBodyRef.current.forEach(rigidBody => {
705
+ if (Array.isArray(rigidBodyRef.current)) {
706
+ for (const rigidBody of rigidBodyRef.current) {
677
707
  setRigidBodyOptions(rigidBody, props, states, updateTranslations);
678
- });
679
- } else {
708
+ }
709
+ } else if (rigidBodyRef.current) {
680
710
  setRigidBodyOptions(rigidBodyRef.current, props, states, updateTranslations);
681
711
  }
682
- }, [props]);
712
+ }, mutablePropsAsFlatArray);
683
713
  };
684
714
  const useRigidBodyEvents = (rigidBodyRef, props, events) => {
685
715
  const {
@@ -699,24 +729,24 @@ const useRigidBodyEvents = (rigidBodyRef, props, events) => {
699
729
  onIntersectionExit
700
730
  };
701
731
  React.useEffect(() => {
702
- if ("length" in rigidBodyRef.current) {
703
- rigidBodyRef.current.forEach(rigidBody => {
732
+ if (Array.isArray(rigidBodyRef.current)) {
733
+ for (const rigidBody of rigidBodyRef.current) {
704
734
  events.set(rigidBody.handle, eventHandlers);
705
- });
706
- } else {
735
+ }
736
+ } else if (rigidBodyRef.current) {
707
737
  events.set(rigidBodyRef.current.handle, eventHandlers);
708
738
  }
709
739
 
710
740
  return () => {
711
- if ("length" in rigidBodyRef.current) {
712
- rigidBodyRef.current.forEach(rigidBody => {
741
+ if (Array.isArray(rigidBodyRef.current)) {
742
+ for (const rigidBody of rigidBodyRef.current) {
713
743
  events.delete(rigidBody.handle);
714
- });
715
- } else {
744
+ }
745
+ } else if (rigidBodyRef.current) {
716
746
  events.delete(rigidBodyRef.current.handle);
717
747
  }
718
748
  };
719
- }, [onWake, onSleep, onCollisionEnter, onCollisionExit]);
749
+ }, [onWake, onSleep, onCollisionEnter, onCollisionExit, onIntersectionEnter, onIntersectionExit]);
720
750
  };
721
751
 
722
752
  const scaleColliderArgs = (shape, args, scale) => {
@@ -793,7 +823,12 @@ const mutableColliderOptions = {
793
823
  },
794
824
  restitutionCombineRule: (collider, value) => {
795
825
  collider.setRestitutionCombineRule(value);
796
- }
826
+ },
827
+ // To make sure the options all mutalbe options are listed
828
+ quaternion: () => {},
829
+ position: () => {},
830
+ rotation: () => {},
831
+ scale: () => {}
797
832
  };
798
833
  const mutableColliderOptionKeys = Object.keys(mutableColliderOptions);
799
834
  const setColliderOptions = (collider, options, states) => {
@@ -835,11 +870,15 @@ const setColliderOptions = (collider, options, states) => {
835
870
  }
836
871
  };
837
872
  const useUpdateColliderOptions = (collidersRef, props, states) => {
873
+ // TODO: Improve this, split each prop into its own effect
874
+ const mutablePropsAsFlatArray = React.useMemo(() => mutableColliderOptionKeys.flatMap(key => {
875
+ return vectorToTuple(props[key]);
876
+ }), [props]);
838
877
  React.useEffect(() => {
839
878
  collidersRef.current.forEach(collider => {
840
879
  setColliderOptions(collider, props, states);
841
880
  });
842
- }, [props]);
881
+ }, mutablePropsAsFlatArray);
843
882
  };
844
883
 
845
884
  const isChildOfMeshCollider = child => {
@@ -980,7 +1019,7 @@ const useColliderEvents = (collidersRef, props, events) => {
980
1019
 
981
1020
  (_collidersRef$current2 = collidersRef.current) === null || _collidersRef$current2 === void 0 ? void 0 : _collidersRef$current2.forEach(collider => events.delete(collider.handle));
982
1021
  };
983
- }, [onCollisionEnter, onCollisionExit]);
1022
+ }, [onCollisionEnter, onCollisionExit, onIntersectionEnter, onIntersectionExit]);
984
1023
  };
985
1024
 
986
1025
  const useRapier = () => {
@@ -1044,6 +1083,7 @@ const useRigidBody = (options = {}) => {
1044
1083
  return () => {
1045
1084
  world.removeRigidBody(rigidBody);
1046
1085
  rigidBodyStates.delete(rigidBody.handle);
1086
+ rigidBodyRef.current = undefined;
1047
1087
  };
1048
1088
  }, []);
1049
1089
  useUpdateRigidBodyOptions(rigidBodyRef, mergedOptions, rigidBodyStates);
@@ -1267,7 +1307,7 @@ const ConvexHullCollider = /*#__PURE__*/React__default["default"].forwardRef((pr
1267
1307
  const _excluded$1 = ["children", "type", "position", "rotation", "scale", "quaternion"];
1268
1308
  const RigidBodyContext = /*#__PURE__*/React.createContext(undefined);
1269
1309
  const useRigidBodyContext = () => React.useContext(RigidBodyContext);
1270
- const RigidBody = /*#__PURE__*/React.forwardRef((props, ref) => {
1310
+ const RigidBody = /*#__PURE__*/React.memo( /*#__PURE__*/React.forwardRef((props, ref) => {
1271
1311
  const {
1272
1312
  children,
1273
1313
  type,
@@ -1297,7 +1337,7 @@ const RigidBody = /*#__PURE__*/React.forwardRef((props, ref) => {
1297
1337
  }), children, childColliderProps.map((colliderProps, index) => /*#__PURE__*/React__default["default"].createElement(AnyCollider, _extends({
1298
1338
  key: index
1299
1339
  }, colliderProps)))));
1300
- });
1340
+ }));
1301
1341
 
1302
1342
  const MeshCollider = props => {
1303
1343
  const {
@@ -1,6 +1,6 @@
1
1
  import { EventQueue, RigidBodyDesc, ColliderDesc, ActiveEvents, ShapeType } from '@dimforge/rapier3d-compat';
2
2
  export { CoefficientCombineRule, Collider as RapierCollider, RigidBody as RapierRigidBody } from '@dimforge/rapier3d-compat';
3
- import React, { useState, useEffect, useRef, useMemo, createContext, useContext, memo, forwardRef, useImperativeHandle, useLayoutEffect } from 'react';
3
+ import React, { useRef, useState, useEffect, useMemo, createContext, useContext, memo, forwardRef, useImperativeHandle, useLayoutEffect } from 'react';
4
4
  import { useAsset } from 'use-asset';
5
5
  import { useFrame } from '@react-three/fiber';
6
6
  import { Quaternion, Euler, Vector3, Object3D, Matrix4, MathUtils, InstancedMesh, MeshBasicMaterial, Color, PlaneGeometry, ConeGeometry, CapsuleGeometry, CylinderGeometry, BufferGeometry, BufferAttribute, SphereGeometry, BoxGeometry, DynamicDrawUsage } from 'three';
@@ -48,6 +48,23 @@ const scaleVertices = (vertices, scale) => {
48
48
 
49
49
  return scaledVerts;
50
50
  };
51
+ const vectorToTuple = v => {
52
+ if (!v) return [0];
53
+
54
+ if (v instanceof Quaternion) {
55
+ return [v.x, v.y, v.z, v.w];
56
+ }
57
+
58
+ if (v instanceof Vector3 || v instanceof Euler) {
59
+ return [v.x, v.y, v.z];
60
+ }
61
+
62
+ if (Array.isArray(v)) {
63
+ return v;
64
+ }
65
+
66
+ return [v];
67
+ };
51
68
 
52
69
  const createRigidBodyApi = ref => {
53
70
  return {
@@ -156,10 +173,19 @@ const createWorldApi = ref => {
156
173
  getRigidBody: handle => ref.current().getRigidBody(handle),
157
174
  createRigidBody: desc => ref.current().createRigidBody(desc),
158
175
  createCollider: (desc, rigidBody) => ref.current().createCollider(desc, rigidBody),
159
- removeRigidBody: rigidBody => ref.current().removeRigidBody(rigidBody),
160
- removeCollider: (collider, wakeUp = true) => ref.current().removeCollider(collider, wakeUp),
176
+ removeRigidBody: rigidBody => {
177
+ if (!ref.current().bodies.contains(rigidBody.handle)) return;
178
+ ref.current().removeRigidBody(rigidBody);
179
+ },
180
+ removeCollider: (collider, wakeUp = true) => {
181
+ if (!ref.current().colliders.contains(collider.handle)) return;
182
+ ref.current().removeCollider(collider, wakeUp);
183
+ },
161
184
  createImpulseJoint: (params, rigidBodyA, rigidBodyB, wakeUp = true) => ref.current().createImpulseJoint(params, rigidBodyA, rigidBodyB, wakeUp),
162
- removeImpulseJoint: (joint, wakeUp = true) => ref.current().removeImpulseJoint(joint, wakeUp),
185
+ removeImpulseJoint: (joint, wakeUp = true) => {
186
+ if (!ref.current().impulseJoints.contains(joint.handle)) return;
187
+ ref.current().removeImpulseJoint(joint, wakeUp);
188
+ },
163
189
  forEachCollider: callback => ref.current().forEachCollider(callback),
164
190
  setGravity: ({
165
191
  x,
@@ -203,10 +229,6 @@ const Physics = ({
203
229
  updatePriority
204
230
  }) => {
205
231
  const rapier = useAsset(importRapier);
206
- const [isPaused, setIsPaused] = useState(_paused);
207
- useEffect(() => {
208
- setIsPaused(_paused);
209
- }, [_paused]);
210
232
  const worldRef = useRef();
211
233
  const getWorldRef = useRef(() => {
212
234
  if (!worldRef.current) {
@@ -227,6 +249,7 @@ const Physics = ({
227
249
  return () => {
228
250
  if (world) {
229
251
  world.free();
252
+ worldRef.current = undefined;
230
253
  }
231
254
  };
232
255
  }, []); // Update gravity
@@ -460,15 +483,15 @@ const Physics = ({
460
483
  colliderStates,
461
484
  rigidBodyEvents,
462
485
  colliderEvents,
463
- isPaused
464
- }), [isPaused]);
486
+ isPaused: _paused
487
+ }), [_paused]);
465
488
  return /*#__PURE__*/React.createElement(RapierContext.Provider, {
466
489
  value: context
467
490
  }, children);
468
491
  };
469
492
 
470
493
  function _extends() {
471
- _extends = Object.assign || function (target) {
494
+ _extends = Object.assign ? Object.assign.bind() : function (target) {
472
495
  for (var i = 1; i < arguments.length; i++) {
473
496
  var source = arguments[i];
474
497
 
@@ -481,7 +504,6 @@ function _extends() {
481
504
 
482
505
  return target;
483
506
  };
484
-
485
507
  return _extends.apply(this, arguments);
486
508
  }
487
509
 
@@ -618,7 +640,11 @@ const mutableRigidBodyOptions = {
618
640
  },
619
641
  ccd: (rb, value) => {
620
642
  rb.enableCcd(value);
621
- }
643
+ },
644
+ position: () => {},
645
+ rotation: () => {},
646
+ quaternion: () => {},
647
+ scale: () => {}
622
648
  };
623
649
  const mutableRigidBodyOptionKeys = Object.keys(mutableRigidBodyOptions);
624
650
  const setRigidBodyOptions = (rigidBody, options, states, updateTranslations = true) => {
@@ -646,15 +672,19 @@ const setRigidBodyOptions = (rigidBody, options, states, updateTranslations = tr
646
672
  }
647
673
  };
648
674
  const useUpdateRigidBodyOptions = (rigidBodyRef, props, states, updateTranslations = true) => {
675
+ // TODO: Improve this, split each prop into its own effect
676
+ const mutablePropsAsFlatArray = useMemo(() => mutableRigidBodyOptionKeys.flatMap(key => {
677
+ return vectorToTuple(props[key]);
678
+ }), [props]);
649
679
  useEffect(() => {
650
- if ("length" in rigidBodyRef.current) {
651
- rigidBodyRef.current.forEach(rigidBody => {
680
+ if (Array.isArray(rigidBodyRef.current)) {
681
+ for (const rigidBody of rigidBodyRef.current) {
652
682
  setRigidBodyOptions(rigidBody, props, states, updateTranslations);
653
- });
654
- } else {
683
+ }
684
+ } else if (rigidBodyRef.current) {
655
685
  setRigidBodyOptions(rigidBodyRef.current, props, states, updateTranslations);
656
686
  }
657
- }, [props]);
687
+ }, mutablePropsAsFlatArray);
658
688
  };
659
689
  const useRigidBodyEvents = (rigidBodyRef, props, events) => {
660
690
  const {
@@ -674,24 +704,24 @@ const useRigidBodyEvents = (rigidBodyRef, props, events) => {
674
704
  onIntersectionExit
675
705
  };
676
706
  useEffect(() => {
677
- if ("length" in rigidBodyRef.current) {
678
- rigidBodyRef.current.forEach(rigidBody => {
707
+ if (Array.isArray(rigidBodyRef.current)) {
708
+ for (const rigidBody of rigidBodyRef.current) {
679
709
  events.set(rigidBody.handle, eventHandlers);
680
- });
681
- } else {
710
+ }
711
+ } else if (rigidBodyRef.current) {
682
712
  events.set(rigidBodyRef.current.handle, eventHandlers);
683
713
  }
684
714
 
685
715
  return () => {
686
- if ("length" in rigidBodyRef.current) {
687
- rigidBodyRef.current.forEach(rigidBody => {
716
+ if (Array.isArray(rigidBodyRef.current)) {
717
+ for (const rigidBody of rigidBodyRef.current) {
688
718
  events.delete(rigidBody.handle);
689
- });
690
- } else {
719
+ }
720
+ } else if (rigidBodyRef.current) {
691
721
  events.delete(rigidBodyRef.current.handle);
692
722
  }
693
723
  };
694
- }, [onWake, onSleep, onCollisionEnter, onCollisionExit]);
724
+ }, [onWake, onSleep, onCollisionEnter, onCollisionExit, onIntersectionEnter, onIntersectionExit]);
695
725
  };
696
726
 
697
727
  const scaleColliderArgs = (shape, args, scale) => {
@@ -768,7 +798,12 @@ const mutableColliderOptions = {
768
798
  },
769
799
  restitutionCombineRule: (collider, value) => {
770
800
  collider.setRestitutionCombineRule(value);
771
- }
801
+ },
802
+ // To make sure the options all mutalbe options are listed
803
+ quaternion: () => {},
804
+ position: () => {},
805
+ rotation: () => {},
806
+ scale: () => {}
772
807
  };
773
808
  const mutableColliderOptionKeys = Object.keys(mutableColliderOptions);
774
809
  const setColliderOptions = (collider, options, states) => {
@@ -810,11 +845,15 @@ const setColliderOptions = (collider, options, states) => {
810
845
  }
811
846
  };
812
847
  const useUpdateColliderOptions = (collidersRef, props, states) => {
848
+ // TODO: Improve this, split each prop into its own effect
849
+ const mutablePropsAsFlatArray = useMemo(() => mutableColliderOptionKeys.flatMap(key => {
850
+ return vectorToTuple(props[key]);
851
+ }), [props]);
813
852
  useEffect(() => {
814
853
  collidersRef.current.forEach(collider => {
815
854
  setColliderOptions(collider, props, states);
816
855
  });
817
- }, [props]);
856
+ }, mutablePropsAsFlatArray);
818
857
  };
819
858
 
820
859
  const isChildOfMeshCollider = child => {
@@ -955,7 +994,7 @@ const useColliderEvents = (collidersRef, props, events) => {
955
994
 
956
995
  (_collidersRef$current2 = collidersRef.current) === null || _collidersRef$current2 === void 0 ? void 0 : _collidersRef$current2.forEach(collider => events.delete(collider.handle));
957
996
  };
958
- }, [onCollisionEnter, onCollisionExit]);
997
+ }, [onCollisionEnter, onCollisionExit, onIntersectionEnter, onIntersectionExit]);
959
998
  };
960
999
 
961
1000
  const useRapier = () => {
@@ -1019,6 +1058,7 @@ const useRigidBody = (options = {}) => {
1019
1058
  return () => {
1020
1059
  world.removeRigidBody(rigidBody);
1021
1060
  rigidBodyStates.delete(rigidBody.handle);
1061
+ rigidBodyRef.current = undefined;
1022
1062
  };
1023
1063
  }, []);
1024
1064
  useUpdateRigidBodyOptions(rigidBodyRef, mergedOptions, rigidBodyStates);
@@ -1242,7 +1282,7 @@ const ConvexHullCollider = /*#__PURE__*/React.forwardRef((props, ref) => {
1242
1282
  const _excluded$1 = ["children", "type", "position", "rotation", "scale", "quaternion"];
1243
1283
  const RigidBodyContext = /*#__PURE__*/createContext(undefined);
1244
1284
  const useRigidBodyContext = () => useContext(RigidBodyContext);
1245
- const RigidBody = /*#__PURE__*/forwardRef((props, ref) => {
1285
+ const RigidBody = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((props, ref) => {
1246
1286
  const {
1247
1287
  children,
1248
1288
  type,
@@ -1272,7 +1312,7 @@ const RigidBody = /*#__PURE__*/forwardRef((props, ref) => {
1272
1312
  }), children, childColliderProps.map((colliderProps, index) => /*#__PURE__*/React.createElement(AnyCollider, _extends({
1273
1313
  key: index
1274
1314
  }, colliderProps)))));
1275
- });
1315
+ }));
1276
1316
 
1277
1317
  const MeshCollider = props => {
1278
1318
  const {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-three/rapier",
3
- "version": "0.7.5",
3
+ "version": "0.7.7",
4
4
  "source": "src/index.ts",
5
5
  "main": "dist/react-three-rapier.cjs.js",
6
6
  "module": "dist/react-three-rapier.esm.js",
@@ -9,18 +9,18 @@
9
9
  "dist"
10
10
  ],
11
11
  "devDependencies": {
12
- "@react-three/drei": "^9.6.2",
13
- "@react-three/fiber": "^8.0.12",
12
+ "@react-three/drei": "^9.34.1",
13
+ "@react-three/fiber": "^8.8.9",
14
14
  "@react-three/test-renderer": "^8.0.17",
15
15
  "@types/react-dom": "^18.0.2",
16
16
  "@types/three": "^0.139.0",
17
17
  "@vitejs/plugin-react": "^2.1.0",
18
- "@vitest/ui": "^0.23.4",
19
- "happy-dom": "^6.0.4",
18
+ "@vitest/ui": "^0.24.1",
19
+ "happy-dom": "^7.5.5",
20
20
  "react": "^18.1.0",
21
21
  "react-dom": "^18.1.0",
22
22
  "three": "^0.139.2",
23
- "vitest": "^0.23.4"
23
+ "vitest": "^0.24.1"
24
24
  },
25
25
  "peerDependencies": {
26
26
  "@react-three/fiber": "^8.0.12",