@react-three/rapier 0.13.2 → 0.14.0-rc.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.
- package/dist/declarations/src/components/Attractor.d.ts +4 -4
- package/dist/declarations/src/components/Physics.d.ts +1 -8
- package/dist/declarations/src/types.d.ts +19 -9
- package/dist/declarations/src/utils/utils-collider.d.ts +47 -1
- package/dist/declarations/src/utils/utils-physics.d.ts +1 -0
- package/dist/react-three-rapier.cjs.dev.js +104 -50
- package/dist/react-three-rapier.cjs.prod.js +104 -50
- package/dist/react-three-rapier.esm.js +106 -52
- package/package.json +1 -1
- package/readme.md +8 -4
@@ -12,13 +12,13 @@ export interface AttractorProps {
|
|
12
12
|
* The strength of the attractor.
|
13
13
|
* Positive values attract, negative values repel.
|
14
14
|
*
|
15
|
-
* @
|
15
|
+
* @defaultValue 1
|
16
16
|
*/
|
17
17
|
strength?: number;
|
18
18
|
/**
|
19
19
|
* The range of the attractor. Will not affect objects outside of this range.
|
20
20
|
*
|
21
|
-
* @
|
21
|
+
* @defaultValue 10
|
22
22
|
* @min 0
|
23
23
|
*/
|
24
24
|
range?: number;
|
@@ -27,12 +27,12 @@ export interface AttractorProps {
|
|
27
27
|
* - static: The gravity is constant and does not change over time.
|
28
28
|
* - linear: The gravity is linearly interpolated the closer the object is to the attractor.
|
29
29
|
* - newtonian: The gravity is calculated using the newtonian gravity formula.
|
30
|
-
* @
|
30
|
+
* @defaultValue "static"
|
31
31
|
*/
|
32
32
|
type?: AttractorGravityType;
|
33
33
|
/**
|
34
34
|
* The mass of the attractor. Used when type is `newtonian`.
|
35
|
-
* @
|
35
|
+
* @defaultValue 6.673e-11
|
36
36
|
*/
|
37
37
|
gravitationalConstant?: number;
|
38
38
|
/**
|
@@ -140,18 +140,11 @@ export interface PhysicsProps {
|
|
140
140
|
* @defaultValue false
|
141
141
|
*/
|
142
142
|
paused?: boolean;
|
143
|
-
/**
|
144
|
-
* The update priority at which the physics simulation should run.
|
145
|
-
*
|
146
|
-
* @see https://docs.pmnd.rs/react-three-fiber/api/hooks#taking-over-the-render-loop
|
147
|
-
* @defaultValue undefined
|
148
|
-
*/
|
149
|
-
updatePriority?: number;
|
150
143
|
/**
|
151
144
|
* Interpolate the world transform using the frame delta times.
|
152
145
|
* Has no effect if timeStep is set to "vary".
|
153
146
|
*
|
154
|
-
* @
|
147
|
+
* @defaultValue true
|
155
148
|
**/
|
156
149
|
interpolate?: boolean;
|
157
150
|
}
|
@@ -228,31 +228,41 @@ export interface RigidBodyOptions extends ColliderProps {
|
|
228
228
|
* Specify the type of this rigid body
|
229
229
|
*/
|
230
230
|
type?: RigidBodyTypeString;
|
231
|
-
/**
|
232
|
-
*
|
231
|
+
/**
|
232
|
+
* Whether or not this body can sleep.
|
233
|
+
* @defaultValue true
|
233
234
|
*/
|
234
235
|
canSleep?: boolean;
|
235
236
|
/** The linear damping coefficient of this rigid-body.*/
|
236
237
|
linearDamping?: number;
|
237
238
|
/** The angular damping coefficient of this rigid-body.*/
|
238
239
|
angularDamping?: number;
|
239
|
-
/**
|
240
|
-
*
|
240
|
+
/**
|
241
|
+
* The initial linear velocity of this body.
|
242
|
+
* @defaultValue [0,0,0]
|
241
243
|
*/
|
242
244
|
linearVelocity?: Vector3Array;
|
243
|
-
/**
|
244
|
-
*
|
245
|
+
/**
|
246
|
+
* The initial angular velocity of this body.
|
247
|
+
* @defaultValue [0,0,0]
|
245
248
|
*/
|
246
249
|
angularVelocity?: Vector3Array;
|
247
250
|
/**
|
248
251
|
* The scaling factor applied to the gravity affecting the rigid-body.
|
249
|
-
*
|
252
|
+
* @defaultValue 1.0
|
250
253
|
*/
|
251
254
|
gravityScale?: number;
|
255
|
+
/**
|
256
|
+
* The dominance group of this RigidBody. If a rigid body has a higher domiance group,
|
257
|
+
* on collision it will be immune to forces originating from the other bodies.
|
258
|
+
* https://rapier.rs/docs/user_guides/javascript/rigid_bodies#dominance
|
259
|
+
* Default: 0
|
260
|
+
*/
|
261
|
+
dominanceGroup?: number;
|
252
262
|
/**
|
253
263
|
* Whether or not Continous Collision Detection is enabled for this rigid-body.
|
254
264
|
* https://rapier.rs/docs/user_guides/javascript/rigid_bodies#continuous-collision-detection
|
255
|
-
* @
|
265
|
+
* @defaultValue false
|
256
266
|
*/
|
257
267
|
ccd?: boolean;
|
258
268
|
/**
|
@@ -308,7 +318,7 @@ export interface RigidBodyOptions extends ColliderProps {
|
|
308
318
|
*/
|
309
319
|
enabledRotations?: Boolean3Array;
|
310
320
|
/**
|
311
|
-
* Allow
|
321
|
+
* Allow translation of this rigid-body only along specific axes.
|
312
322
|
*/
|
313
323
|
enabledTranslations?: Boolean3Array;
|
314
324
|
/**
|
@@ -31,5 +31,51 @@ export declare const getColliderArgsFromGeometry: (geometry: BufferGeometry, col
|
|
31
31
|
args: unknown[];
|
32
32
|
offset: Vector3;
|
33
33
|
};
|
34
|
-
export declare const
|
34
|
+
export declare const getActiveCollisionEventsFromProps: (props?: ColliderProps) => {
|
35
|
+
collision: boolean;
|
36
|
+
contactForce: boolean;
|
37
|
+
};
|
38
|
+
export declare const useColliderEvents: (getCollider: () => Collider, props: ColliderProps, events: EventMap, activeEvents?: {
|
39
|
+
collision?: boolean;
|
40
|
+
contactForce?: boolean;
|
41
|
+
}) => void;
|
42
|
+
export declare const cleanRigidBodyPropsForCollider: (props?: RigidBodyProps) => {
|
43
|
+
linearVelocity?: import("..").Vector3Array | undefined;
|
44
|
+
angularVelocity?: import("..").Vector3Array | undefined;
|
45
|
+
dominanceGroup?: number | undefined;
|
46
|
+
position?: import("@react-three/fiber").Vector3 | undefined;
|
47
|
+
rotation?: import("@react-three/fiber").Euler | undefined;
|
48
|
+
colliders?: RigidBodyAutoCollider | undefined;
|
49
|
+
friction?: number | undefined;
|
50
|
+
restitution?: number | undefined;
|
51
|
+
collisionGroups?: number | undefined;
|
52
|
+
solverGroups?: number | undefined;
|
53
|
+
onSleep?(): void;
|
54
|
+
onWake?(): void;
|
55
|
+
lockRotations?: boolean | undefined;
|
56
|
+
lockTranslations?: boolean | undefined;
|
57
|
+
enabledRotations?: import("..").Boolean3Array | undefined;
|
58
|
+
enabledTranslations?: import("..").Boolean3Array | undefined;
|
59
|
+
userData?: {
|
60
|
+
[key: string]: any;
|
61
|
+
} | undefined;
|
62
|
+
includeInvisible?: boolean | undefined;
|
63
|
+
transformState?: ((state: import("../components/Physics").RigidBodyState) => import("../components/Physics").RigidBodyState) | undefined;
|
64
|
+
name?: string | undefined;
|
65
|
+
shape?: ColliderShape | undefined;
|
66
|
+
args?: any;
|
67
|
+
principalAngularInertia?: import("..").Vector3Array | undefined;
|
68
|
+
restitutionCombineRule?: import("@dimforge/rapier3d-compat").CoefficientCombineRule | undefined;
|
69
|
+
frictionCombineRule?: import("@dimforge/rapier3d-compat").CoefficientCombineRule | undefined;
|
70
|
+
quaternion?: import("@react-three/fiber").Quaternion | undefined;
|
71
|
+
scale?: import("@react-three/fiber").Vector3 | undefined;
|
72
|
+
density?: number | undefined;
|
73
|
+
massProperties?: {
|
74
|
+
mass: number;
|
75
|
+
centerOfMass: import("@dimforge/rapier3d-compat").Vector;
|
76
|
+
principalAngularInertia: import("@dimforge/rapier3d-compat").Vector;
|
77
|
+
angularInertiaLocalFrame: import("@dimforge/rapier3d-compat").Rotation;
|
78
|
+
} | undefined;
|
79
|
+
sensor?: boolean | undefined;
|
80
|
+
};
|
35
81
|
export {};
|
@@ -0,0 +1 @@
|
|
1
|
+
export declare const useRaf: (callback: (dt: number) => void) => void;
|
@@ -178,6 +178,62 @@ function useConst(initialValue) {
|
|
178
178
|
return ref.current.value;
|
179
179
|
}
|
180
180
|
|
181
|
+
const useRaf = callback => {
|
182
|
+
const cb = React.useRef(callback);
|
183
|
+
const raf = React.useRef(0);
|
184
|
+
const lastFrame = React.useRef(0);
|
185
|
+
React.useEffect(() => {
|
186
|
+
cb.current = callback;
|
187
|
+
}, [callback]);
|
188
|
+
React.useEffect(() => {
|
189
|
+
const loop = () => {
|
190
|
+
const now = performance.now();
|
191
|
+
const delta = now - lastFrame.current;
|
192
|
+
raf.current = requestAnimationFrame(loop);
|
193
|
+
cb.current(delta / 1000);
|
194
|
+
lastFrame.current = now;
|
195
|
+
};
|
196
|
+
|
197
|
+
raf.current = requestAnimationFrame(loop);
|
198
|
+
return () => cancelAnimationFrame(raf.current);
|
199
|
+
}, []);
|
200
|
+
};
|
201
|
+
|
202
|
+
function _objectWithoutPropertiesLoose(source, excluded) {
|
203
|
+
if (source == null) return {};
|
204
|
+
var target = {};
|
205
|
+
var sourceKeys = Object.keys(source);
|
206
|
+
var key, i;
|
207
|
+
|
208
|
+
for (i = 0; i < sourceKeys.length; i++) {
|
209
|
+
key = sourceKeys[i];
|
210
|
+
if (excluded.indexOf(key) >= 0) continue;
|
211
|
+
target[key] = source[key];
|
212
|
+
}
|
213
|
+
|
214
|
+
return target;
|
215
|
+
}
|
216
|
+
|
217
|
+
function _objectWithoutProperties(source, excluded) {
|
218
|
+
if (source == null) return {};
|
219
|
+
var target = _objectWithoutPropertiesLoose(source, excluded);
|
220
|
+
var key, i;
|
221
|
+
|
222
|
+
if (Object.getOwnPropertySymbols) {
|
223
|
+
var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
|
224
|
+
|
225
|
+
for (i = 0; i < sourceSymbolKeys.length; i++) {
|
226
|
+
key = sourceSymbolKeys[i];
|
227
|
+
if (excluded.indexOf(key) >= 0) continue;
|
228
|
+
if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
|
229
|
+
target[key] = source[key];
|
230
|
+
}
|
231
|
+
}
|
232
|
+
|
233
|
+
return target;
|
234
|
+
}
|
235
|
+
|
236
|
+
const _excluded$2 = ["mass", "linearDamping", "angularDamping", "type", "onCollisionEnter", "onCollisionExit", "onIntersectionEnter", "onIntersectionExit", "onContactForce", "children", "canSleep", "ccd", "gravityScale"];
|
181
237
|
const scaleColliderArgs = (shape, args, scale) => {
|
182
238
|
const newArgs = args.slice(); // Heightfield uses a vector
|
183
239
|
|
@@ -344,7 +400,7 @@ const createColliderPropsFromChildren = ({
|
|
344
400
|
ignoreMeshColliders: _ignoreMeshColliders = true,
|
345
401
|
options
|
346
402
|
}) => {
|
347
|
-
const
|
403
|
+
const childColliderProps = [];
|
348
404
|
object.updateWorldMatrix(true, false);
|
349
405
|
const invertedParentMatrixWorld = object.matrixWorld.clone().invert();
|
350
406
|
|
@@ -365,13 +421,16 @@ const createColliderPropsFromChildren = ({
|
|
365
421
|
args,
|
366
422
|
offset
|
367
423
|
} = getColliderArgsFromGeometry(geometry, options.colliders || "cuboid");
|
368
|
-
|
424
|
+
|
425
|
+
const colliderProps = _objectSpread2(_objectSpread2({}, cleanRigidBodyPropsForCollider(options)), {}, {
|
369
426
|
args: args,
|
370
427
|
shape: shape,
|
371
428
|
rotation: [rotationEuler.x, rotationEuler.y, rotationEuler.z],
|
372
429
|
position: [_position.x + offset.x * worldScale.x, _position.y + offset.y * worldScale.y, _position.z + offset.z * worldScale.z],
|
373
430
|
scale: [worldScale.x, worldScale.y, worldScale.z]
|
374
|
-
})
|
431
|
+
});
|
432
|
+
|
433
|
+
childColliderProps.push(colliderProps);
|
375
434
|
}
|
376
435
|
};
|
377
436
|
|
@@ -381,7 +440,7 @@ const createColliderPropsFromChildren = ({
|
|
381
440
|
object.traverseVisible(colliderFromChild);
|
382
441
|
}
|
383
442
|
|
384
|
-
return
|
443
|
+
return childColliderProps;
|
385
444
|
};
|
386
445
|
const getColliderArgsFromGeometry = (geometry, colliders) => {
|
387
446
|
switch (colliders) {
|
@@ -437,7 +496,17 @@ const getColliderArgsFromGeometry = (geometry, colliders) => {
|
|
437
496
|
offset: new three.Vector3()
|
438
497
|
};
|
439
498
|
};
|
440
|
-
const
|
499
|
+
const getActiveCollisionEventsFromProps = props => {
|
500
|
+
return {
|
501
|
+
collision: !!(props !== null && props !== void 0 && props.onCollisionEnter || props !== null && props !== void 0 && props.onCollisionExit || props !== null && props !== void 0 && props.onIntersectionEnter || props !== null && props !== void 0 && props.onIntersectionExit),
|
502
|
+
contactForce: !!(props !== null && props !== void 0 && props.onContactForce)
|
503
|
+
};
|
504
|
+
};
|
505
|
+
const useColliderEvents = (getCollider, props, events,
|
506
|
+
/**
|
507
|
+
* The RigidBody can pass down active events to the collider without attaching the event listners
|
508
|
+
*/
|
509
|
+
activeEvents = {}) => {
|
441
510
|
const {
|
442
511
|
onCollisionEnter,
|
443
512
|
onCollisionExit,
|
@@ -449,8 +518,12 @@ const useColliderEvents = (getCollider, props, events) => {
|
|
449
518
|
const collider = getCollider();
|
450
519
|
|
451
520
|
if (collider) {
|
452
|
-
const
|
453
|
-
|
521
|
+
const {
|
522
|
+
collision: collisionEventsActive,
|
523
|
+
contactForce: contactForceEventsActive
|
524
|
+
} = getActiveCollisionEventsFromProps(props);
|
525
|
+
const hasCollisionEvent = collisionEventsActive || activeEvents.collision;
|
526
|
+
const hasContactForceEvent = contactForceEventsActive || activeEvents.contactForce;
|
454
527
|
|
455
528
|
if (hasCollisionEvent && hasContactForceEvent) {
|
456
529
|
collider.setActiveEvents(rapier3dCompat.ActiveEvents.COLLISION_EVENTS | rapier3dCompat.ActiveEvents.CONTACT_FORCE_EVENTS);
|
@@ -474,7 +547,12 @@ const useColliderEvents = (getCollider, props, events) => {
|
|
474
547
|
events.delete(collider.handle);
|
475
548
|
}
|
476
549
|
};
|
477
|
-
}, [onCollisionEnter, onCollisionExit, onIntersectionEnter, onIntersectionExit, onContactForce]);
|
550
|
+
}, [onCollisionEnter, onCollisionExit, onIntersectionEnter, onIntersectionExit, onContactForce, activeEvents]);
|
551
|
+
};
|
552
|
+
const cleanRigidBodyPropsForCollider = (props = {}) => {
|
553
|
+
const rest = _objectWithoutProperties(props, _excluded$2);
|
554
|
+
|
555
|
+
return rest;
|
478
556
|
};
|
479
557
|
|
480
558
|
const useMutableCallback = fn => {
|
@@ -675,10 +753,12 @@ const Physics = ({
|
|
675
753
|
children,
|
676
754
|
timeStep: _timeStep = 1 / 60,
|
677
755
|
paused: _paused = false,
|
678
|
-
updatePriority,
|
679
756
|
interpolate: _interpolate = true
|
680
757
|
}) => {
|
681
758
|
const rapier = useAsset.useAsset(importRapier);
|
759
|
+
const {
|
760
|
+
invalidate
|
761
|
+
} = fiber.useThree();
|
682
762
|
const worldRef = React.useRef();
|
683
763
|
const getWorldRef = React.useRef(() => {
|
684
764
|
if (!worldRef.current) {
|
@@ -959,10 +1039,13 @@ const Physics = ({
|
|
959
1039
|
maxForceMagnitude: event.maxForceMagnitude()
|
960
1040
|
}));
|
961
1041
|
});
|
1042
|
+
world.forEachActiveRigidBody(body => {
|
1043
|
+
invalidate();
|
1044
|
+
});
|
962
1045
|
}, [_paused, _timeStep, _interpolate]);
|
963
|
-
|
1046
|
+
useRaf(dt => {
|
964
1047
|
if (!_paused) step(dt);
|
965
|
-
}
|
1048
|
+
});
|
966
1049
|
const context = React.useMemo(() => ({
|
967
1050
|
rapier,
|
968
1051
|
world: api,
|
@@ -1002,40 +1085,6 @@ function _extends() {
|
|
1002
1085
|
return _extends.apply(this, arguments);
|
1003
1086
|
}
|
1004
1087
|
|
1005
|
-
function _objectWithoutPropertiesLoose(source, excluded) {
|
1006
|
-
if (source == null) return {};
|
1007
|
-
var target = {};
|
1008
|
-
var sourceKeys = Object.keys(source);
|
1009
|
-
var key, i;
|
1010
|
-
|
1011
|
-
for (i = 0; i < sourceKeys.length; i++) {
|
1012
|
-
key = sourceKeys[i];
|
1013
|
-
if (excluded.indexOf(key) >= 0) continue;
|
1014
|
-
target[key] = source[key];
|
1015
|
-
}
|
1016
|
-
|
1017
|
-
return target;
|
1018
|
-
}
|
1019
|
-
|
1020
|
-
function _objectWithoutProperties(source, excluded) {
|
1021
|
-
if (source == null) return {};
|
1022
|
-
var target = _objectWithoutPropertiesLoose(source, excluded);
|
1023
|
-
var key, i;
|
1024
|
-
|
1025
|
-
if (Object.getOwnPropertySymbols) {
|
1026
|
-
var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
|
1027
|
-
|
1028
|
-
for (i = 0; i < sourceSymbolKeys.length; i++) {
|
1029
|
-
key = sourceSymbolKeys[i];
|
1030
|
-
if (excluded.indexOf(key) >= 0) continue;
|
1031
|
-
if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
|
1032
|
-
target[key] = source[key];
|
1033
|
-
}
|
1034
|
-
}
|
1035
|
-
|
1036
|
-
return target;
|
1037
|
-
}
|
1038
|
-
|
1039
1088
|
/**
|
1040
1089
|
* Initiate an instance and return a safe getter
|
1041
1090
|
*/
|
@@ -1148,10 +1197,10 @@ const AnyCollider = /*#__PURE__*/React.memo( /*#__PURE__*/React.forwardRef((prop
|
|
1148
1197
|
}, []);
|
1149
1198
|
React.useImperativeHandle(forwardedRef, () => getInstance());
|
1150
1199
|
const mergedProps = React.useMemo(() => {
|
1151
|
-
return _objectSpread2(_objectSpread2({}, rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.options), props);
|
1200
|
+
return _objectSpread2(_objectSpread2({}, cleanRigidBodyPropsForCollider(rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.options)), props);
|
1152
1201
|
}, [props, rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.options]);
|
1153
1202
|
useUpdateColliderOptions(getInstance, mergedProps, colliderStates);
|
1154
|
-
useColliderEvents(getInstance, mergedProps, colliderEvents);
|
1203
|
+
useColliderEvents(getInstance, mergedProps, colliderEvents, getActiveCollisionEventsFromProps(rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.options));
|
1155
1204
|
return /*#__PURE__*/React__default["default"].createElement("object3D", {
|
1156
1205
|
position: position,
|
1157
1206
|
rotation: rotation,
|
@@ -1312,6 +1361,9 @@ const mutableRigidBodyOptions = {
|
|
1312
1361
|
angularDamping: (rb, value) => {
|
1313
1362
|
rb.setAngularDamping(value);
|
1314
1363
|
},
|
1364
|
+
dominanceGroup: (rb, value) => {
|
1365
|
+
rb.setDominanceGroup(value);
|
1366
|
+
},
|
1315
1367
|
enabledRotations: (rb, [x, y, z]) => {
|
1316
1368
|
rb.setEnabledRotations(x, y, z, true);
|
1317
1369
|
},
|
@@ -1396,7 +1448,8 @@ const useRigidBodyEvents = (getRigidBody, props, events) => {
|
|
1396
1448
|
onCollisionEnter,
|
1397
1449
|
onCollisionExit,
|
1398
1450
|
onIntersectionEnter,
|
1399
|
-
onIntersectionExit
|
1451
|
+
onIntersectionExit,
|
1452
|
+
onContactForce
|
1400
1453
|
} = props;
|
1401
1454
|
const eventHandlers = {
|
1402
1455
|
onWake,
|
@@ -1404,7 +1457,8 @@ const useRigidBodyEvents = (getRigidBody, props, events) => {
|
|
1404
1457
|
onCollisionEnter,
|
1405
1458
|
onCollisionExit,
|
1406
1459
|
onIntersectionEnter,
|
1407
|
-
onIntersectionExit
|
1460
|
+
onIntersectionExit,
|
1461
|
+
onContactForce
|
1408
1462
|
};
|
1409
1463
|
React.useEffect(() => {
|
1410
1464
|
const rigidBody = getRigidBody();
|
@@ -1412,7 +1466,7 @@ const useRigidBodyEvents = (getRigidBody, props, events) => {
|
|
1412
1466
|
return () => {
|
1413
1467
|
events.delete(rigidBody.handle);
|
1414
1468
|
};
|
1415
|
-
}, [onWake, onSleep, onCollisionEnter, onCollisionExit, onIntersectionEnter, onIntersectionExit]);
|
1469
|
+
}, [onWake, onSleep, onCollisionEnter, onCollisionExit, onIntersectionEnter, onIntersectionExit, onContactForce]);
|
1416
1470
|
};
|
1417
1471
|
|
1418
1472
|
const _excluded$1 = ["children", "type", "position", "rotation", "scale", "quaternion", "transformState"];
|
@@ -178,6 +178,62 @@ function useConst(initialValue) {
|
|
178
178
|
return ref.current.value;
|
179
179
|
}
|
180
180
|
|
181
|
+
const useRaf = callback => {
|
182
|
+
const cb = React.useRef(callback);
|
183
|
+
const raf = React.useRef(0);
|
184
|
+
const lastFrame = React.useRef(0);
|
185
|
+
React.useEffect(() => {
|
186
|
+
cb.current = callback;
|
187
|
+
}, [callback]);
|
188
|
+
React.useEffect(() => {
|
189
|
+
const loop = () => {
|
190
|
+
const now = performance.now();
|
191
|
+
const delta = now - lastFrame.current;
|
192
|
+
raf.current = requestAnimationFrame(loop);
|
193
|
+
cb.current(delta / 1000);
|
194
|
+
lastFrame.current = now;
|
195
|
+
};
|
196
|
+
|
197
|
+
raf.current = requestAnimationFrame(loop);
|
198
|
+
return () => cancelAnimationFrame(raf.current);
|
199
|
+
}, []);
|
200
|
+
};
|
201
|
+
|
202
|
+
function _objectWithoutPropertiesLoose(source, excluded) {
|
203
|
+
if (source == null) return {};
|
204
|
+
var target = {};
|
205
|
+
var sourceKeys = Object.keys(source);
|
206
|
+
var key, i;
|
207
|
+
|
208
|
+
for (i = 0; i < sourceKeys.length; i++) {
|
209
|
+
key = sourceKeys[i];
|
210
|
+
if (excluded.indexOf(key) >= 0) continue;
|
211
|
+
target[key] = source[key];
|
212
|
+
}
|
213
|
+
|
214
|
+
return target;
|
215
|
+
}
|
216
|
+
|
217
|
+
function _objectWithoutProperties(source, excluded) {
|
218
|
+
if (source == null) return {};
|
219
|
+
var target = _objectWithoutPropertiesLoose(source, excluded);
|
220
|
+
var key, i;
|
221
|
+
|
222
|
+
if (Object.getOwnPropertySymbols) {
|
223
|
+
var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
|
224
|
+
|
225
|
+
for (i = 0; i < sourceSymbolKeys.length; i++) {
|
226
|
+
key = sourceSymbolKeys[i];
|
227
|
+
if (excluded.indexOf(key) >= 0) continue;
|
228
|
+
if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
|
229
|
+
target[key] = source[key];
|
230
|
+
}
|
231
|
+
}
|
232
|
+
|
233
|
+
return target;
|
234
|
+
}
|
235
|
+
|
236
|
+
const _excluded$2 = ["mass", "linearDamping", "angularDamping", "type", "onCollisionEnter", "onCollisionExit", "onIntersectionEnter", "onIntersectionExit", "onContactForce", "children", "canSleep", "ccd", "gravityScale"];
|
181
237
|
const scaleColliderArgs = (shape, args, scale) => {
|
182
238
|
const newArgs = args.slice(); // Heightfield uses a vector
|
183
239
|
|
@@ -344,7 +400,7 @@ const createColliderPropsFromChildren = ({
|
|
344
400
|
ignoreMeshColliders: _ignoreMeshColliders = true,
|
345
401
|
options
|
346
402
|
}) => {
|
347
|
-
const
|
403
|
+
const childColliderProps = [];
|
348
404
|
object.updateWorldMatrix(true, false);
|
349
405
|
const invertedParentMatrixWorld = object.matrixWorld.clone().invert();
|
350
406
|
|
@@ -365,13 +421,16 @@ const createColliderPropsFromChildren = ({
|
|
365
421
|
args,
|
366
422
|
offset
|
367
423
|
} = getColliderArgsFromGeometry(geometry, options.colliders || "cuboid");
|
368
|
-
|
424
|
+
|
425
|
+
const colliderProps = _objectSpread2(_objectSpread2({}, cleanRigidBodyPropsForCollider(options)), {}, {
|
369
426
|
args: args,
|
370
427
|
shape: shape,
|
371
428
|
rotation: [rotationEuler.x, rotationEuler.y, rotationEuler.z],
|
372
429
|
position: [_position.x + offset.x * worldScale.x, _position.y + offset.y * worldScale.y, _position.z + offset.z * worldScale.z],
|
373
430
|
scale: [worldScale.x, worldScale.y, worldScale.z]
|
374
|
-
})
|
431
|
+
});
|
432
|
+
|
433
|
+
childColliderProps.push(colliderProps);
|
375
434
|
}
|
376
435
|
};
|
377
436
|
|
@@ -381,7 +440,7 @@ const createColliderPropsFromChildren = ({
|
|
381
440
|
object.traverseVisible(colliderFromChild);
|
382
441
|
}
|
383
442
|
|
384
|
-
return
|
443
|
+
return childColliderProps;
|
385
444
|
};
|
386
445
|
const getColliderArgsFromGeometry = (geometry, colliders) => {
|
387
446
|
switch (colliders) {
|
@@ -437,7 +496,17 @@ const getColliderArgsFromGeometry = (geometry, colliders) => {
|
|
437
496
|
offset: new three.Vector3()
|
438
497
|
};
|
439
498
|
};
|
440
|
-
const
|
499
|
+
const getActiveCollisionEventsFromProps = props => {
|
500
|
+
return {
|
501
|
+
collision: !!(props !== null && props !== void 0 && props.onCollisionEnter || props !== null && props !== void 0 && props.onCollisionExit || props !== null && props !== void 0 && props.onIntersectionEnter || props !== null && props !== void 0 && props.onIntersectionExit),
|
502
|
+
contactForce: !!(props !== null && props !== void 0 && props.onContactForce)
|
503
|
+
};
|
504
|
+
};
|
505
|
+
const useColliderEvents = (getCollider, props, events,
|
506
|
+
/**
|
507
|
+
* The RigidBody can pass down active events to the collider without attaching the event listners
|
508
|
+
*/
|
509
|
+
activeEvents = {}) => {
|
441
510
|
const {
|
442
511
|
onCollisionEnter,
|
443
512
|
onCollisionExit,
|
@@ -449,8 +518,12 @@ const useColliderEvents = (getCollider, props, events) => {
|
|
449
518
|
const collider = getCollider();
|
450
519
|
|
451
520
|
if (collider) {
|
452
|
-
const
|
453
|
-
|
521
|
+
const {
|
522
|
+
collision: collisionEventsActive,
|
523
|
+
contactForce: contactForceEventsActive
|
524
|
+
} = getActiveCollisionEventsFromProps(props);
|
525
|
+
const hasCollisionEvent = collisionEventsActive || activeEvents.collision;
|
526
|
+
const hasContactForceEvent = contactForceEventsActive || activeEvents.contactForce;
|
454
527
|
|
455
528
|
if (hasCollisionEvent && hasContactForceEvent) {
|
456
529
|
collider.setActiveEvents(rapier3dCompat.ActiveEvents.COLLISION_EVENTS | rapier3dCompat.ActiveEvents.CONTACT_FORCE_EVENTS);
|
@@ -474,7 +547,12 @@ const useColliderEvents = (getCollider, props, events) => {
|
|
474
547
|
events.delete(collider.handle);
|
475
548
|
}
|
476
549
|
};
|
477
|
-
}, [onCollisionEnter, onCollisionExit, onIntersectionEnter, onIntersectionExit, onContactForce]);
|
550
|
+
}, [onCollisionEnter, onCollisionExit, onIntersectionEnter, onIntersectionExit, onContactForce, activeEvents]);
|
551
|
+
};
|
552
|
+
const cleanRigidBodyPropsForCollider = (props = {}) => {
|
553
|
+
const rest = _objectWithoutProperties(props, _excluded$2);
|
554
|
+
|
555
|
+
return rest;
|
478
556
|
};
|
479
557
|
|
480
558
|
const useMutableCallback = fn => {
|
@@ -675,10 +753,12 @@ const Physics = ({
|
|
675
753
|
children,
|
676
754
|
timeStep: _timeStep = 1 / 60,
|
677
755
|
paused: _paused = false,
|
678
|
-
updatePriority,
|
679
756
|
interpolate: _interpolate = true
|
680
757
|
}) => {
|
681
758
|
const rapier = useAsset.useAsset(importRapier);
|
759
|
+
const {
|
760
|
+
invalidate
|
761
|
+
} = fiber.useThree();
|
682
762
|
const worldRef = React.useRef();
|
683
763
|
const getWorldRef = React.useRef(() => {
|
684
764
|
if (!worldRef.current) {
|
@@ -959,10 +1039,13 @@ const Physics = ({
|
|
959
1039
|
maxForceMagnitude: event.maxForceMagnitude()
|
960
1040
|
}));
|
961
1041
|
});
|
1042
|
+
world.forEachActiveRigidBody(body => {
|
1043
|
+
invalidate();
|
1044
|
+
});
|
962
1045
|
}, [_paused, _timeStep, _interpolate]);
|
963
|
-
|
1046
|
+
useRaf(dt => {
|
964
1047
|
if (!_paused) step(dt);
|
965
|
-
}
|
1048
|
+
});
|
966
1049
|
const context = React.useMemo(() => ({
|
967
1050
|
rapier,
|
968
1051
|
world: api,
|
@@ -1002,40 +1085,6 @@ function _extends() {
|
|
1002
1085
|
return _extends.apply(this, arguments);
|
1003
1086
|
}
|
1004
1087
|
|
1005
|
-
function _objectWithoutPropertiesLoose(source, excluded) {
|
1006
|
-
if (source == null) return {};
|
1007
|
-
var target = {};
|
1008
|
-
var sourceKeys = Object.keys(source);
|
1009
|
-
var key, i;
|
1010
|
-
|
1011
|
-
for (i = 0; i < sourceKeys.length; i++) {
|
1012
|
-
key = sourceKeys[i];
|
1013
|
-
if (excluded.indexOf(key) >= 0) continue;
|
1014
|
-
target[key] = source[key];
|
1015
|
-
}
|
1016
|
-
|
1017
|
-
return target;
|
1018
|
-
}
|
1019
|
-
|
1020
|
-
function _objectWithoutProperties(source, excluded) {
|
1021
|
-
if (source == null) return {};
|
1022
|
-
var target = _objectWithoutPropertiesLoose(source, excluded);
|
1023
|
-
var key, i;
|
1024
|
-
|
1025
|
-
if (Object.getOwnPropertySymbols) {
|
1026
|
-
var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
|
1027
|
-
|
1028
|
-
for (i = 0; i < sourceSymbolKeys.length; i++) {
|
1029
|
-
key = sourceSymbolKeys[i];
|
1030
|
-
if (excluded.indexOf(key) >= 0) continue;
|
1031
|
-
if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
|
1032
|
-
target[key] = source[key];
|
1033
|
-
}
|
1034
|
-
}
|
1035
|
-
|
1036
|
-
return target;
|
1037
|
-
}
|
1038
|
-
|
1039
1088
|
/**
|
1040
1089
|
* Initiate an instance and return a safe getter
|
1041
1090
|
*/
|
@@ -1148,10 +1197,10 @@ const AnyCollider = /*#__PURE__*/React.memo( /*#__PURE__*/React.forwardRef((prop
|
|
1148
1197
|
}, []);
|
1149
1198
|
React.useImperativeHandle(forwardedRef, () => getInstance());
|
1150
1199
|
const mergedProps = React.useMemo(() => {
|
1151
|
-
return _objectSpread2(_objectSpread2({}, rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.options), props);
|
1200
|
+
return _objectSpread2(_objectSpread2({}, cleanRigidBodyPropsForCollider(rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.options)), props);
|
1152
1201
|
}, [props, rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.options]);
|
1153
1202
|
useUpdateColliderOptions(getInstance, mergedProps, colliderStates);
|
1154
|
-
useColliderEvents(getInstance, mergedProps, colliderEvents);
|
1203
|
+
useColliderEvents(getInstance, mergedProps, colliderEvents, getActiveCollisionEventsFromProps(rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.options));
|
1155
1204
|
return /*#__PURE__*/React__default["default"].createElement("object3D", {
|
1156
1205
|
position: position,
|
1157
1206
|
rotation: rotation,
|
@@ -1312,6 +1361,9 @@ const mutableRigidBodyOptions = {
|
|
1312
1361
|
angularDamping: (rb, value) => {
|
1313
1362
|
rb.setAngularDamping(value);
|
1314
1363
|
},
|
1364
|
+
dominanceGroup: (rb, value) => {
|
1365
|
+
rb.setDominanceGroup(value);
|
1366
|
+
},
|
1315
1367
|
enabledRotations: (rb, [x, y, z]) => {
|
1316
1368
|
rb.setEnabledRotations(x, y, z, true);
|
1317
1369
|
},
|
@@ -1396,7 +1448,8 @@ const useRigidBodyEvents = (getRigidBody, props, events) => {
|
|
1396
1448
|
onCollisionEnter,
|
1397
1449
|
onCollisionExit,
|
1398
1450
|
onIntersectionEnter,
|
1399
|
-
onIntersectionExit
|
1451
|
+
onIntersectionExit,
|
1452
|
+
onContactForce
|
1400
1453
|
} = props;
|
1401
1454
|
const eventHandlers = {
|
1402
1455
|
onWake,
|
@@ -1404,7 +1457,8 @@ const useRigidBodyEvents = (getRigidBody, props, events) => {
|
|
1404
1457
|
onCollisionEnter,
|
1405
1458
|
onCollisionExit,
|
1406
1459
|
onIntersectionEnter,
|
1407
|
-
onIntersectionExit
|
1460
|
+
onIntersectionExit,
|
1461
|
+
onContactForce
|
1408
1462
|
};
|
1409
1463
|
React.useEffect(() => {
|
1410
1464
|
const rigidBody = getRigidBody();
|
@@ -1412,7 +1466,7 @@ const useRigidBodyEvents = (getRigidBody, props, events) => {
|
|
1412
1466
|
return () => {
|
1413
1467
|
events.delete(rigidBody.handle);
|
1414
1468
|
};
|
1415
|
-
}, [onWake, onSleep, onCollisionEnter, onCollisionExit, onIntersectionEnter, onIntersectionExit]);
|
1469
|
+
}, [onWake, onSleep, onCollisionEnter, onCollisionExit, onIntersectionEnter, onIntersectionExit, onContactForce]);
|
1416
1470
|
};
|
1417
1471
|
|
1418
1472
|
const _excluded$1 = ["children", "type", "position", "rotation", "scale", "quaternion", "transformState"];
|
@@ -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
|
-
import {
|
4
|
-
import React, { useRef,
|
3
|
+
import { useThree, useFrame } from '@react-three/fiber';
|
4
|
+
import React, { useRef, useEffect, useMemo, useContext, useState, memo, createContext, useCallback, forwardRef, useImperativeHandle, Fragment } from 'react';
|
5
5
|
import { Quaternion, Euler, Vector3, Object3D, Matrix4, MathUtils, BufferAttribute, DynamicDrawUsage } from 'three';
|
6
6
|
import { useAsset } from 'use-asset';
|
7
7
|
import { mergeVertices, VertexNormalsHelper } from 'three-stdlib';
|
@@ -153,6 +153,62 @@ function useConst(initialValue) {
|
|
153
153
|
return ref.current.value;
|
154
154
|
}
|
155
155
|
|
156
|
+
const useRaf = callback => {
|
157
|
+
const cb = useRef(callback);
|
158
|
+
const raf = useRef(0);
|
159
|
+
const lastFrame = useRef(0);
|
160
|
+
useEffect(() => {
|
161
|
+
cb.current = callback;
|
162
|
+
}, [callback]);
|
163
|
+
useEffect(() => {
|
164
|
+
const loop = () => {
|
165
|
+
const now = performance.now();
|
166
|
+
const delta = now - lastFrame.current;
|
167
|
+
raf.current = requestAnimationFrame(loop);
|
168
|
+
cb.current(delta / 1000);
|
169
|
+
lastFrame.current = now;
|
170
|
+
};
|
171
|
+
|
172
|
+
raf.current = requestAnimationFrame(loop);
|
173
|
+
return () => cancelAnimationFrame(raf.current);
|
174
|
+
}, []);
|
175
|
+
};
|
176
|
+
|
177
|
+
function _objectWithoutPropertiesLoose(source, excluded) {
|
178
|
+
if (source == null) return {};
|
179
|
+
var target = {};
|
180
|
+
var sourceKeys = Object.keys(source);
|
181
|
+
var key, i;
|
182
|
+
|
183
|
+
for (i = 0; i < sourceKeys.length; i++) {
|
184
|
+
key = sourceKeys[i];
|
185
|
+
if (excluded.indexOf(key) >= 0) continue;
|
186
|
+
target[key] = source[key];
|
187
|
+
}
|
188
|
+
|
189
|
+
return target;
|
190
|
+
}
|
191
|
+
|
192
|
+
function _objectWithoutProperties(source, excluded) {
|
193
|
+
if (source == null) return {};
|
194
|
+
var target = _objectWithoutPropertiesLoose(source, excluded);
|
195
|
+
var key, i;
|
196
|
+
|
197
|
+
if (Object.getOwnPropertySymbols) {
|
198
|
+
var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
|
199
|
+
|
200
|
+
for (i = 0; i < sourceSymbolKeys.length; i++) {
|
201
|
+
key = sourceSymbolKeys[i];
|
202
|
+
if (excluded.indexOf(key) >= 0) continue;
|
203
|
+
if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
|
204
|
+
target[key] = source[key];
|
205
|
+
}
|
206
|
+
}
|
207
|
+
|
208
|
+
return target;
|
209
|
+
}
|
210
|
+
|
211
|
+
const _excluded$2 = ["mass", "linearDamping", "angularDamping", "type", "onCollisionEnter", "onCollisionExit", "onIntersectionEnter", "onIntersectionExit", "onContactForce", "children", "canSleep", "ccd", "gravityScale"];
|
156
212
|
const scaleColliderArgs = (shape, args, scale) => {
|
157
213
|
const newArgs = args.slice(); // Heightfield uses a vector
|
158
214
|
|
@@ -319,7 +375,7 @@ const createColliderPropsFromChildren = ({
|
|
319
375
|
ignoreMeshColliders: _ignoreMeshColliders = true,
|
320
376
|
options
|
321
377
|
}) => {
|
322
|
-
const
|
378
|
+
const childColliderProps = [];
|
323
379
|
object.updateWorldMatrix(true, false);
|
324
380
|
const invertedParentMatrixWorld = object.matrixWorld.clone().invert();
|
325
381
|
|
@@ -340,13 +396,16 @@ const createColliderPropsFromChildren = ({
|
|
340
396
|
args,
|
341
397
|
offset
|
342
398
|
} = getColliderArgsFromGeometry(geometry, options.colliders || "cuboid");
|
343
|
-
|
399
|
+
|
400
|
+
const colliderProps = _objectSpread2(_objectSpread2({}, cleanRigidBodyPropsForCollider(options)), {}, {
|
344
401
|
args: args,
|
345
402
|
shape: shape,
|
346
403
|
rotation: [rotationEuler.x, rotationEuler.y, rotationEuler.z],
|
347
404
|
position: [_position.x + offset.x * worldScale.x, _position.y + offset.y * worldScale.y, _position.z + offset.z * worldScale.z],
|
348
405
|
scale: [worldScale.x, worldScale.y, worldScale.z]
|
349
|
-
})
|
406
|
+
});
|
407
|
+
|
408
|
+
childColliderProps.push(colliderProps);
|
350
409
|
}
|
351
410
|
};
|
352
411
|
|
@@ -356,7 +415,7 @@ const createColliderPropsFromChildren = ({
|
|
356
415
|
object.traverseVisible(colliderFromChild);
|
357
416
|
}
|
358
417
|
|
359
|
-
return
|
418
|
+
return childColliderProps;
|
360
419
|
};
|
361
420
|
const getColliderArgsFromGeometry = (geometry, colliders) => {
|
362
421
|
switch (colliders) {
|
@@ -412,7 +471,17 @@ const getColliderArgsFromGeometry = (geometry, colliders) => {
|
|
412
471
|
offset: new Vector3()
|
413
472
|
};
|
414
473
|
};
|
415
|
-
const
|
474
|
+
const getActiveCollisionEventsFromProps = props => {
|
475
|
+
return {
|
476
|
+
collision: !!(props !== null && props !== void 0 && props.onCollisionEnter || props !== null && props !== void 0 && props.onCollisionExit || props !== null && props !== void 0 && props.onIntersectionEnter || props !== null && props !== void 0 && props.onIntersectionExit),
|
477
|
+
contactForce: !!(props !== null && props !== void 0 && props.onContactForce)
|
478
|
+
};
|
479
|
+
};
|
480
|
+
const useColliderEvents = (getCollider, props, events,
|
481
|
+
/**
|
482
|
+
* The RigidBody can pass down active events to the collider without attaching the event listners
|
483
|
+
*/
|
484
|
+
activeEvents = {}) => {
|
416
485
|
const {
|
417
486
|
onCollisionEnter,
|
418
487
|
onCollisionExit,
|
@@ -424,8 +493,12 @@ const useColliderEvents = (getCollider, props, events) => {
|
|
424
493
|
const collider = getCollider();
|
425
494
|
|
426
495
|
if (collider) {
|
427
|
-
const
|
428
|
-
|
496
|
+
const {
|
497
|
+
collision: collisionEventsActive,
|
498
|
+
contactForce: contactForceEventsActive
|
499
|
+
} = getActiveCollisionEventsFromProps(props);
|
500
|
+
const hasCollisionEvent = collisionEventsActive || activeEvents.collision;
|
501
|
+
const hasContactForceEvent = contactForceEventsActive || activeEvents.contactForce;
|
429
502
|
|
430
503
|
if (hasCollisionEvent && hasContactForceEvent) {
|
431
504
|
collider.setActiveEvents(ActiveEvents.COLLISION_EVENTS | ActiveEvents.CONTACT_FORCE_EVENTS);
|
@@ -449,7 +522,12 @@ const useColliderEvents = (getCollider, props, events) => {
|
|
449
522
|
events.delete(collider.handle);
|
450
523
|
}
|
451
524
|
};
|
452
|
-
}, [onCollisionEnter, onCollisionExit, onIntersectionEnter, onIntersectionExit, onContactForce]);
|
525
|
+
}, [onCollisionEnter, onCollisionExit, onIntersectionEnter, onIntersectionExit, onContactForce, activeEvents]);
|
526
|
+
};
|
527
|
+
const cleanRigidBodyPropsForCollider = (props = {}) => {
|
528
|
+
const rest = _objectWithoutProperties(props, _excluded$2);
|
529
|
+
|
530
|
+
return rest;
|
453
531
|
};
|
454
532
|
|
455
533
|
const useMutableCallback = fn => {
|
@@ -650,10 +728,12 @@ const Physics = ({
|
|
650
728
|
children,
|
651
729
|
timeStep: _timeStep = 1 / 60,
|
652
730
|
paused: _paused = false,
|
653
|
-
updatePriority,
|
654
731
|
interpolate: _interpolate = true
|
655
732
|
}) => {
|
656
733
|
const rapier = useAsset(importRapier);
|
734
|
+
const {
|
735
|
+
invalidate
|
736
|
+
} = useThree();
|
657
737
|
const worldRef = useRef();
|
658
738
|
const getWorldRef = useRef(() => {
|
659
739
|
if (!worldRef.current) {
|
@@ -934,10 +1014,13 @@ const Physics = ({
|
|
934
1014
|
maxForceMagnitude: event.maxForceMagnitude()
|
935
1015
|
}));
|
936
1016
|
});
|
1017
|
+
world.forEachActiveRigidBody(body => {
|
1018
|
+
invalidate();
|
1019
|
+
});
|
937
1020
|
}, [_paused, _timeStep, _interpolate]);
|
938
|
-
|
1021
|
+
useRaf(dt => {
|
939
1022
|
if (!_paused) step(dt);
|
940
|
-
}
|
1023
|
+
});
|
941
1024
|
const context = useMemo(() => ({
|
942
1025
|
rapier,
|
943
1026
|
world: api,
|
@@ -977,40 +1060,6 @@ function _extends() {
|
|
977
1060
|
return _extends.apply(this, arguments);
|
978
1061
|
}
|
979
1062
|
|
980
|
-
function _objectWithoutPropertiesLoose(source, excluded) {
|
981
|
-
if (source == null) return {};
|
982
|
-
var target = {};
|
983
|
-
var sourceKeys = Object.keys(source);
|
984
|
-
var key, i;
|
985
|
-
|
986
|
-
for (i = 0; i < sourceKeys.length; i++) {
|
987
|
-
key = sourceKeys[i];
|
988
|
-
if (excluded.indexOf(key) >= 0) continue;
|
989
|
-
target[key] = source[key];
|
990
|
-
}
|
991
|
-
|
992
|
-
return target;
|
993
|
-
}
|
994
|
-
|
995
|
-
function _objectWithoutProperties(source, excluded) {
|
996
|
-
if (source == null) return {};
|
997
|
-
var target = _objectWithoutPropertiesLoose(source, excluded);
|
998
|
-
var key, i;
|
999
|
-
|
1000
|
-
if (Object.getOwnPropertySymbols) {
|
1001
|
-
var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
|
1002
|
-
|
1003
|
-
for (i = 0; i < sourceSymbolKeys.length; i++) {
|
1004
|
-
key = sourceSymbolKeys[i];
|
1005
|
-
if (excluded.indexOf(key) >= 0) continue;
|
1006
|
-
if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
|
1007
|
-
target[key] = source[key];
|
1008
|
-
}
|
1009
|
-
}
|
1010
|
-
|
1011
|
-
return target;
|
1012
|
-
}
|
1013
|
-
|
1014
1063
|
/**
|
1015
1064
|
* Initiate an instance and return a safe getter
|
1016
1065
|
*/
|
@@ -1123,10 +1172,10 @@ const AnyCollider = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((props, forwarded
|
|
1123
1172
|
}, []);
|
1124
1173
|
useImperativeHandle(forwardedRef, () => getInstance());
|
1125
1174
|
const mergedProps = useMemo(() => {
|
1126
|
-
return _objectSpread2(_objectSpread2({}, rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.options), props);
|
1175
|
+
return _objectSpread2(_objectSpread2({}, cleanRigidBodyPropsForCollider(rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.options)), props);
|
1127
1176
|
}, [props, rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.options]);
|
1128
1177
|
useUpdateColliderOptions(getInstance, mergedProps, colliderStates);
|
1129
|
-
useColliderEvents(getInstance, mergedProps, colliderEvents);
|
1178
|
+
useColliderEvents(getInstance, mergedProps, colliderEvents, getActiveCollisionEventsFromProps(rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.options));
|
1130
1179
|
return /*#__PURE__*/React.createElement("object3D", {
|
1131
1180
|
position: position,
|
1132
1181
|
rotation: rotation,
|
@@ -1287,6 +1336,9 @@ const mutableRigidBodyOptions = {
|
|
1287
1336
|
angularDamping: (rb, value) => {
|
1288
1337
|
rb.setAngularDamping(value);
|
1289
1338
|
},
|
1339
|
+
dominanceGroup: (rb, value) => {
|
1340
|
+
rb.setDominanceGroup(value);
|
1341
|
+
},
|
1290
1342
|
enabledRotations: (rb, [x, y, z]) => {
|
1291
1343
|
rb.setEnabledRotations(x, y, z, true);
|
1292
1344
|
},
|
@@ -1371,7 +1423,8 @@ const useRigidBodyEvents = (getRigidBody, props, events) => {
|
|
1371
1423
|
onCollisionEnter,
|
1372
1424
|
onCollisionExit,
|
1373
1425
|
onIntersectionEnter,
|
1374
|
-
onIntersectionExit
|
1426
|
+
onIntersectionExit,
|
1427
|
+
onContactForce
|
1375
1428
|
} = props;
|
1376
1429
|
const eventHandlers = {
|
1377
1430
|
onWake,
|
@@ -1379,7 +1432,8 @@ const useRigidBodyEvents = (getRigidBody, props, events) => {
|
|
1379
1432
|
onCollisionEnter,
|
1380
1433
|
onCollisionExit,
|
1381
1434
|
onIntersectionEnter,
|
1382
|
-
onIntersectionExit
|
1435
|
+
onIntersectionExit,
|
1436
|
+
onContactForce
|
1383
1437
|
};
|
1384
1438
|
useEffect(() => {
|
1385
1439
|
const rigidBody = getRigidBody();
|
@@ -1387,7 +1441,7 @@ const useRigidBodyEvents = (getRigidBody, props, events) => {
|
|
1387
1441
|
return () => {
|
1388
1442
|
events.delete(rigidBody.handle);
|
1389
1443
|
};
|
1390
|
-
}, [onWake, onSleep, onCollisionEnter, onCollisionExit, onIntersectionEnter, onIntersectionExit]);
|
1444
|
+
}, [onWake, onSleep, onCollisionEnter, onCollisionExit, onIntersectionEnter, onIntersectionExit, onContactForce]);
|
1391
1445
|
};
|
1392
1446
|
|
1393
1447
|
const _excluded$1 = ["children", "type", "position", "rotation", "scale", "quaternion", "transformState"];
|
package/package.json
CHANGED
package/readme.md
CHANGED
@@ -84,6 +84,7 @@ For full API outline and documentation, see 🧩 [API Docs](https://pmndrs.githu
|
|
84
84
|
- [🖼 Joints Example](#-joints-example)
|
85
85
|
- [Advanced hooks usage](#advanced-hooks-usage)
|
86
86
|
- [Manual stepping](#manual-stepping)
|
87
|
+
- [On-demand rendering](#on-demand-rendering)
|
87
88
|
|
88
89
|
---
|
89
90
|
|
@@ -131,7 +132,7 @@ Supported values:
|
|
131
132
|
|
132
133
|
- `"cuboid"`, creates a CuboidCollider based on the bounding box of the mesh
|
133
134
|
- `"ball"`, creates a SphereCollider based on the bounding sphere of the mesh
|
134
|
-
- `"trimesh"`, creates a TrimeshCollider based on the mesh's geometry
|
135
|
+
- `"trimesh"`, creates a TrimeshCollider based on the mesh's geometry
|
135
136
|
- `"hull"`, creates a ConvexHullCollider based on the mesh's geometry
|
136
137
|
- `false`, disables auto-generation
|
137
138
|
|
@@ -758,7 +759,7 @@ const JointedThing = () => {
|
|
758
759
|
[
|
759
760
|
[0, 0, 0], // Position of the joint in bodyA's local space
|
760
761
|
[0, 0, 0], // Position of the joint in bodyB's local space
|
761
|
-
[0,
|
762
|
+
[0, 1, 0], // Axis of the joint, expressed in the local-space of the rigid-bodies it is attached to. Cannot be [0,0,0].
|
762
763
|
]);
|
763
764
|
|
764
765
|
useEffect(() => {
|
@@ -793,7 +794,7 @@ const JointedThing = () => {
|
|
793
794
|
[
|
794
795
|
[0, 0, 0], // Position of the joint in bodyA's local space
|
795
796
|
[0, 0, 0], // Position of the joint in bodyB's local space
|
796
|
-
[0,
|
797
|
+
[0, 1, 0], // Axis of the joint, expressed in the local-space of the rigid-bodies it is attached to. Cannot be [0,0,0].
|
797
798
|
]);
|
798
799
|
|
799
800
|
return (
|
@@ -834,4 +835,7 @@ You can manually step the physics simulation by calling the `step` method from t
|
|
834
835
|
const { step } = useRapier();
|
835
836
|
|
836
837
|
step(1 / 60);
|
837
|
-
```
|
838
|
+
```
|
839
|
+
|
840
|
+
### On-demand rendering
|
841
|
+
`@react-three/rapier` runs the physics simulation independently from the render loop, and will tell `@react-three/fiber` to render if the scene has active (non-sleeping) RigidBodies. This allows you to use the `<Canvas frameloop="demand" />` (https://docs.pmnd.rs/react-three-fiber/advanced/scaling-performance#on-demand-rendering) strategy to only render the scene when needed.
|