@react-three/rapier 0.16.0-canary.0 → 1.0.0-canary.2
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/InstancedRigidBodies.d.ts +1 -1
- package/dist/declarations/src/components/Physics.d.ts +3 -4
- package/dist/declarations/src/hooks/use-forwarded-ref.d.ts +2 -0
- package/dist/declarations/src/index.d.ts +0 -1
- package/dist/declarations/src/utils/singleton-proxy.d.ts +10 -0
- package/dist/declarations/src/utils/utils-collider.d.ts +2 -3
- package/dist/react-three-rapier.cjs.dev.js +127 -97
- package/dist/react-three-rapier.cjs.prod.js +127 -97
- package/dist/react-three-rapier.esm.js +128 -98
- package/package.json +2 -4
- package/dist/declarations/src/utils/api.d.ts +0 -17
@@ -72,40 +72,6 @@ function _objectSpread2(target) {
|
|
72
72
|
return target;
|
73
73
|
}
|
74
74
|
|
75
|
-
const createWorldApi = getWorld => {
|
76
|
-
return {
|
77
|
-
raw: () => getWorld(),
|
78
|
-
getCollider: handle => getWorld().getCollider(handle),
|
79
|
-
getRigidBody: handle => getWorld().getRigidBody(handle),
|
80
|
-
createRigidBody: desc => getWorld().createRigidBody(desc),
|
81
|
-
createCollider: (desc, rigidBody) => getWorld().createCollider(desc, rigidBody),
|
82
|
-
removeRigidBody: rigidBody => {
|
83
|
-
if (!getWorld().bodies.contains(rigidBody.handle)) return;
|
84
|
-
getWorld().removeRigidBody(rigidBody);
|
85
|
-
},
|
86
|
-
removeCollider: (collider, wakeUp = true) => {
|
87
|
-
if (!getWorld().colliders.contains(collider.handle)) return;
|
88
|
-
getWorld().removeCollider(collider, wakeUp);
|
89
|
-
},
|
90
|
-
createImpulseJoint: (params, rigidBodyA, rigidBodyB, wakeUp = true) => getWorld().createImpulseJoint(params, rigidBodyA, rigidBodyB, wakeUp),
|
91
|
-
removeImpulseJoint: (joint, wakeUp = true) => {
|
92
|
-
if (!getWorld().impulseJoints.contains(joint.handle)) return;
|
93
|
-
getWorld().removeImpulseJoint(joint, wakeUp);
|
94
|
-
},
|
95
|
-
forEachCollider: callback => getWorld().forEachCollider(callback),
|
96
|
-
setGravity: ({
|
97
|
-
x,
|
98
|
-
y,
|
99
|
-
z
|
100
|
-
}) => getWorld().gravity = {
|
101
|
-
x,
|
102
|
-
y,
|
103
|
-
z
|
104
|
-
},
|
105
|
-
debugRender: () => getWorld().debugRender()
|
106
|
-
};
|
107
|
-
};
|
108
|
-
|
109
75
|
const _quaternion = new three.Quaternion();
|
110
76
|
new three.Euler();
|
111
77
|
const _vector3 = new three.Vector3();
|
@@ -684,30 +650,37 @@ const Debug = /*#__PURE__*/React.memo(() => {
|
|
684
650
|
});
|
685
651
|
|
686
652
|
/**
|
687
|
-
*
|
653
|
+
* Creates a proxy that will create a singleton instance of the given class
|
654
|
+
* when a property is accessed, and not before.
|
655
|
+
*
|
656
|
+
* @returns A proxy and a reset function, so that the instance can created again
|
688
657
|
*/
|
658
|
+
const createSingletonProxy = createInstance => {
|
659
|
+
let instance;
|
660
|
+
const handler = {
|
661
|
+
get(target, prop) {
|
662
|
+
if (!instance) {
|
663
|
+
instance = createInstance();
|
664
|
+
}
|
689
665
|
|
690
|
-
|
691
|
-
const ref = React.useRef();
|
692
|
-
const getInstance = React.useCallback(() => {
|
693
|
-
if (!ref.current) {
|
694
|
-
ref.current = createFn();
|
666
|
+
return Reflect.get(instance, prop);
|
695
667
|
}
|
696
668
|
|
697
|
-
|
698
|
-
},
|
699
|
-
React.useEffect(() => {
|
700
|
-
// Save the destroy function and instance
|
701
|
-
const instance = getInstance();
|
669
|
+
};
|
670
|
+
const proxy = new Proxy({}, handler);
|
702
671
|
|
703
|
-
|
672
|
+
const reset = () => {
|
673
|
+
instance = undefined;
|
674
|
+
};
|
675
|
+
/**
|
676
|
+
* Return the proxy and a reset function
|
677
|
+
*/
|
704
678
|
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
}
|
710
|
-
return getInstance;
|
679
|
+
|
680
|
+
return {
|
681
|
+
proxy,
|
682
|
+
reset
|
683
|
+
};
|
711
684
|
};
|
712
685
|
|
713
686
|
const rapierContext = /*#__PURE__*/React.createContext(undefined);
|
@@ -759,38 +732,42 @@ const Physics = ({
|
|
759
732
|
const rapier = useAsset.useAsset(importRapier);
|
760
733
|
const {
|
761
734
|
invalidate
|
762
|
-
} = fiber.useThree();
|
763
|
-
|
764
|
-
const getWorld = useImperativeInstance(() => {
|
765
|
-
return new rapier.World(vectorArrayToVector3(_gravity));
|
766
|
-
}, world => {
|
767
|
-
world.free();
|
768
|
-
}, []);
|
735
|
+
} = fiber.useThree();
|
769
736
|
const rigidBodyStates = useConst(() => new Map());
|
770
737
|
const colliderStates = useConst(() => new Map());
|
771
738
|
const rigidBodyEvents = useConst(() => new Map());
|
772
739
|
const colliderEvents = useConst(() => new Map());
|
773
740
|
const eventQueue = useConst(() => new rapier3dCompat.EventQueue(false));
|
774
741
|
const beforeStepCallbacks = useConst(() => new Set());
|
775
|
-
const afterStepCallbacks = useConst(() => new Set());
|
742
|
+
const afterStepCallbacks = useConst(() => new Set());
|
743
|
+
/**
|
744
|
+
* Initiate the world
|
745
|
+
* This creates a singleton proxy, so that the world is only created when
|
746
|
+
* something within it is accessed.
|
747
|
+
*/
|
776
748
|
|
749
|
+
const {
|
750
|
+
proxy: worldProxy,
|
751
|
+
reset: resetWorldProxy
|
752
|
+
} = useConst(() => createSingletonProxy(() => new rapier.World(vectorArrayToVector3(_gravity))));
|
777
753
|
React.useEffect(() => {
|
778
|
-
|
754
|
+
return () => {
|
755
|
+
worldProxy.free();
|
756
|
+
resetWorldProxy();
|
757
|
+
};
|
758
|
+
}, []); // Update gravity
|
779
759
|
|
780
|
-
|
781
|
-
|
782
|
-
}
|
760
|
+
React.useEffect(() => {
|
761
|
+
worldProxy.gravity = vectorArrayToVector3(_gravity);
|
783
762
|
}, [_gravity]);
|
784
|
-
const api = React.useMemo(() => createWorldApi(getWorld), []);
|
785
763
|
const getSourceFromColliderHandle = React.useCallback(handle => {
|
786
764
|
var _collider$parent;
|
787
765
|
|
788
|
-
const
|
789
|
-
const collider = world.getCollider(handle);
|
766
|
+
const collider = worldProxy.getCollider(handle);
|
790
767
|
const colEvents = colliderEvents.get(handle);
|
791
768
|
const colliderState = colliderStates.get(handle);
|
792
769
|
const rigidBodyHandle = collider === null || collider === void 0 ? void 0 : (_collider$parent = collider.parent()) === null || _collider$parent === void 0 ? void 0 : _collider$parent.handle;
|
793
|
-
const rigidBody = rigidBodyHandle !== undefined ?
|
770
|
+
const rigidBody = rigidBodyHandle !== undefined ? worldProxy.getRigidBody(rigidBodyHandle) : undefined;
|
794
771
|
const rbEvents = rigidBody && rigidBodyHandle !== undefined ? rigidBodyEvents.get(rigidBodyHandle) : undefined;
|
795
772
|
const rigidBodyState = rigidBodyHandle !== undefined ? rigidBodyStates.get(rigidBodyHandle) : undefined;
|
796
773
|
const source = {
|
@@ -812,7 +789,7 @@ const Physics = ({
|
|
812
789
|
accumulator: 0
|
813
790
|
});
|
814
791
|
const step = React.useCallback(dt => {
|
815
|
-
const world =
|
792
|
+
const world = worldProxy;
|
816
793
|
/* Check if the timestep is supposed to be variable. We'll do this here
|
817
794
|
once so we don't have to string-check every frame. */
|
818
795
|
|
@@ -827,12 +804,12 @@ const Physics = ({
|
|
827
804
|
const stepWorld = () => {
|
828
805
|
// Trigger beforeStep callbacks
|
829
806
|
beforeStepCallbacks.forEach(callback => {
|
830
|
-
callback.current(
|
807
|
+
callback.current(worldProxy);
|
831
808
|
});
|
832
809
|
world.step(eventQueue); // Trigger afterStep callbacks
|
833
810
|
|
834
811
|
afterStepCallbacks.forEach(callback => {
|
835
|
-
callback.current(
|
812
|
+
callback.current(worldProxy);
|
836
813
|
});
|
837
814
|
};
|
838
815
|
|
@@ -1022,7 +999,7 @@ const Physics = ({
|
|
1022
999
|
}, [_paused, _timeStep, _interpolate]);
|
1023
1000
|
const context = React.useMemo(() => ({
|
1024
1001
|
rapier,
|
1025
|
-
world:
|
1002
|
+
world: worldProxy,
|
1026
1003
|
physicsOptions: {
|
1027
1004
|
colliders: _colliders,
|
1028
1005
|
gravity: _gravity
|
@@ -1068,6 +1045,33 @@ function _extends() {
|
|
1068
1045
|
return _extends.apply(this, arguments);
|
1069
1046
|
}
|
1070
1047
|
|
1048
|
+
/**
|
1049
|
+
* Initiate an instance and return a safe getter
|
1050
|
+
*/
|
1051
|
+
|
1052
|
+
const useImperativeInstance = (createFn, destroyFn, dependencyList) => {
|
1053
|
+
const ref = React.useRef();
|
1054
|
+
const getInstance = React.useCallback(() => {
|
1055
|
+
if (!ref.current) {
|
1056
|
+
ref.current = createFn();
|
1057
|
+
}
|
1058
|
+
|
1059
|
+
return ref.current;
|
1060
|
+
}, dependencyList);
|
1061
|
+
React.useEffect(() => {
|
1062
|
+
// Save the destroy function and instance
|
1063
|
+
const instance = getInstance();
|
1064
|
+
|
1065
|
+
const destroy = () => destroyFn(instance);
|
1066
|
+
|
1067
|
+
return () => {
|
1068
|
+
destroy();
|
1069
|
+
ref.current = undefined;
|
1070
|
+
};
|
1071
|
+
}, [getInstance]);
|
1072
|
+
return getInstance;
|
1073
|
+
};
|
1074
|
+
|
1071
1075
|
/**
|
1072
1076
|
* Takes an object resembling a Vector3 and returs a Three.Vector3
|
1073
1077
|
* @category Math helpers
|
@@ -1119,6 +1123,20 @@ const euler = ({
|
|
1119
1123
|
return new three.Euler(x, y, z);
|
1120
1124
|
};
|
1121
1125
|
|
1126
|
+
const useForwardedRef = (forwardedRef, defaultValue = null) => {
|
1127
|
+
const innerRef = React.useRef(defaultValue); // Update the forwarded ref when the inner ref changes
|
1128
|
+
|
1129
|
+
if (forwardedRef && typeof forwardedRef !== "function") {
|
1130
|
+
if (!forwardedRef.current) {
|
1131
|
+
forwardedRef.current = innerRef.current;
|
1132
|
+
}
|
1133
|
+
|
1134
|
+
return forwardedRef;
|
1135
|
+
}
|
1136
|
+
|
1137
|
+
return innerRef;
|
1138
|
+
};
|
1139
|
+
|
1122
1140
|
/**
|
1123
1141
|
* A collider is a shape that can be attached to a rigid body to define its physical properties.
|
1124
1142
|
* @internal
|
@@ -1138,24 +1156,30 @@ const AnyCollider = /*#__PURE__*/React.memo( /*#__PURE__*/React.forwardRef((prop
|
|
1138
1156
|
colliderStates
|
1139
1157
|
} = useRapier();
|
1140
1158
|
const rigidBodyContext = useRigidBodyContext();
|
1141
|
-
const
|
1159
|
+
const colliderRef = useForwardedRef(forwardedRef);
|
1160
|
+
const objectRef = React.useRef(null); // We spread the props out here to make sure that the ref is updated when the props change.
|
1142
1161
|
|
1143
1162
|
const immutablePropArray = immutableColliderOptions.flatMap(key => Array.isArray(props[key]) ? [...props[key]] : props[key]);
|
1144
1163
|
const getInstance = useImperativeInstance(() => {
|
1145
|
-
const worldScale =
|
1164
|
+
const worldScale = objectRef.current.getWorldScale(vec3());
|
1146
1165
|
const collider = createColliderFromOptions(props, world, worldScale, rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.getRigidBody);
|
1166
|
+
|
1167
|
+
if (typeof forwardedRef == "function") {
|
1168
|
+
forwardedRef(collider);
|
1169
|
+
}
|
1170
|
+
|
1171
|
+
colliderRef.current = collider;
|
1147
1172
|
return collider;
|
1148
1173
|
}, collider => {
|
1149
|
-
world.removeCollider(collider);
|
1174
|
+
world.removeCollider(collider, true);
|
1150
1175
|
}, [...immutablePropArray, rigidBodyContext]);
|
1151
1176
|
React.useEffect(() => {
|
1152
1177
|
const collider = getInstance();
|
1153
|
-
colliderStates.set(collider.handle, createColliderState(collider,
|
1178
|
+
colliderStates.set(collider.handle, createColliderState(collider, objectRef.current, rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.ref.current));
|
1154
1179
|
return () => {
|
1155
1180
|
colliderStates.delete(collider.handle);
|
1156
1181
|
};
|
1157
1182
|
}, [getInstance]);
|
1158
|
-
React.useImperativeHandle(forwardedRef, () => getInstance(), [getInstance]);
|
1159
1183
|
const mergedProps = React.useMemo(() => {
|
1160
1184
|
return _objectSpread2(_objectSpread2({}, cleanRigidBodyPropsForCollider(rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.options)), props);
|
1161
1185
|
}, [props, rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.options]);
|
@@ -1166,7 +1190,7 @@ const AnyCollider = /*#__PURE__*/React.memo( /*#__PURE__*/React.forwardRef((prop
|
|
1166
1190
|
rotation: rotation,
|
1167
1191
|
quaternion: quaternion,
|
1168
1192
|
scale: scale,
|
1169
|
-
ref:
|
1193
|
+
ref: objectRef,
|
1170
1194
|
name: name
|
1171
1195
|
}, children);
|
1172
1196
|
}));
|
@@ -1454,7 +1478,8 @@ const RigidBody = /*#__PURE__*/React.memo( /*#__PURE__*/React.forwardRef((props,
|
|
1454
1478
|
} = props,
|
1455
1479
|
objectProps = _objectWithoutProperties(props, _excluded$1);
|
1456
1480
|
|
1457
|
-
const
|
1481
|
+
const objectRef = React.useRef(null);
|
1482
|
+
const rigidBodyRef = useForwardedRef(forwardedRef);
|
1458
1483
|
const {
|
1459
1484
|
world,
|
1460
1485
|
rigidBodyStates,
|
@@ -1469,11 +1494,17 @@ const RigidBody = /*#__PURE__*/React.memo( /*#__PURE__*/React.forwardRef((props,
|
|
1469
1494
|
const immutablePropArray = immutableRigidBodyOptions.flatMap(key => {
|
1470
1495
|
return Array.isArray(mergedOptions[key]) ? [...mergedOptions[key]] : mergedOptions[key];
|
1471
1496
|
});
|
1472
|
-
const childColliderProps = useChildColliderProps(
|
1497
|
+
const childColliderProps = useChildColliderProps(objectRef, mergedOptions); // Provide a way to eagerly create rigidbody
|
1473
1498
|
|
1474
1499
|
const getRigidBody = useImperativeInstance(() => {
|
1475
1500
|
const desc = rigidBodyDescFromOptions(mergedOptions);
|
1476
1501
|
const rigidBody = world.createRigidBody(desc);
|
1502
|
+
|
1503
|
+
if (typeof forwardedRef === "function") {
|
1504
|
+
forwardedRef(rigidBody);
|
1505
|
+
}
|
1506
|
+
|
1507
|
+
rigidBodyRef.current = rigidBody;
|
1477
1508
|
return rigidBody;
|
1478
1509
|
}, rigidBody => {
|
1479
1510
|
world.removeRigidBody(rigidBody);
|
@@ -1483,7 +1514,7 @@ const RigidBody = /*#__PURE__*/React.memo( /*#__PURE__*/React.forwardRef((props,
|
|
1483
1514
|
const rigidBody = getRigidBody();
|
1484
1515
|
const state = createRigidBodyState({
|
1485
1516
|
rigidBody,
|
1486
|
-
object:
|
1517
|
+
object: objectRef.current
|
1487
1518
|
});
|
1488
1519
|
rigidBodyStates.set(rigidBody.handle, props.transformState ? props.transformState(state) : state);
|
1489
1520
|
return () => {
|
@@ -1492,10 +1523,9 @@ const RigidBody = /*#__PURE__*/React.memo( /*#__PURE__*/React.forwardRef((props,
|
|
1492
1523
|
}, [getRigidBody]);
|
1493
1524
|
useUpdateRigidBodyOptions(getRigidBody, mergedOptions, rigidBodyStates);
|
1494
1525
|
useRigidBodyEvents(getRigidBody, mergedOptions, rigidBodyEvents);
|
1495
|
-
React.useImperativeHandle(forwardedRef, () => getRigidBody(), [getRigidBody]);
|
1496
1526
|
const contextValue = React.useMemo(() => {
|
1497
1527
|
return {
|
1498
|
-
ref,
|
1528
|
+
ref: objectRef,
|
1499
1529
|
getRigidBody: getRigidBody,
|
1500
1530
|
options: mergedOptions
|
1501
1531
|
};
|
@@ -1503,7 +1533,7 @@ const RigidBody = /*#__PURE__*/React.memo( /*#__PURE__*/React.forwardRef((props,
|
|
1503
1533
|
return /*#__PURE__*/React__default["default"].createElement(RigidBodyContext.Provider, {
|
1504
1534
|
value: contextValue
|
1505
1535
|
}, /*#__PURE__*/React__default["default"].createElement("object3D", _extends({
|
1506
|
-
ref:
|
1536
|
+
ref: objectRef
|
1507
1537
|
}, objectProps, {
|
1508
1538
|
position: position,
|
1509
1539
|
rotation: rotation,
|
@@ -1550,9 +1580,10 @@ const MeshCollider = /*#__PURE__*/React.memo(props => {
|
|
1550
1580
|
MeshCollider.displayName = "MeshCollider";
|
1551
1581
|
|
1552
1582
|
const _excluded = ["children", "instances", "colliderNodes", "position", "rotation", "quaternion", "scale"];
|
1553
|
-
const InstancedRigidBodies = /*#__PURE__*/React.memo( /*#__PURE__*/React.forwardRef((props,
|
1554
|
-
const
|
1555
|
-
const
|
1583
|
+
const InstancedRigidBodies = /*#__PURE__*/React.memo( /*#__PURE__*/React.forwardRef((props, forwardedRef) => {
|
1584
|
+
const rigidBodiesRef = useForwardedRef(forwardedRef, []);
|
1585
|
+
const objectRef = React.useRef(null);
|
1586
|
+
const instanceWrapperRef = React.useRef(null);
|
1556
1587
|
|
1557
1588
|
const {
|
1558
1589
|
// instanced props
|
@@ -1567,14 +1598,12 @@ const InstancedRigidBodies = /*#__PURE__*/React.memo( /*#__PURE__*/React.forward
|
|
1567
1598
|
} = props,
|
1568
1599
|
rigidBodyProps = _objectWithoutProperties(props, _excluded);
|
1569
1600
|
|
1570
|
-
const
|
1571
|
-
React.useImperativeHandle(ref, () => rigidBodyApis.current, [instances]);
|
1572
|
-
const childColliderProps = useChildColliderProps(object, _objectSpread2(_objectSpread2({}, props), {}, {
|
1601
|
+
const childColliderProps = useChildColliderProps(objectRef, _objectSpread2(_objectSpread2({}, props), {}, {
|
1573
1602
|
children: undefined
|
1574
1603
|
}));
|
1575
1604
|
|
1576
1605
|
const getInstancedMesh = () => {
|
1577
|
-
const firstChild =
|
1606
|
+
const firstChild = instanceWrapperRef.current.children[0];
|
1578
1607
|
|
1579
1608
|
if (firstChild && "isInstancedMesh" in firstChild) {
|
1580
1609
|
return firstChild;
|
@@ -1614,16 +1643,16 @@ const InstancedRigidBodies = /*#__PURE__*/React.memo( /*#__PURE__*/React.forward
|
|
1614
1643
|
};
|
1615
1644
|
|
1616
1645
|
return /*#__PURE__*/React__default["default"].createElement("object3D", _extends({
|
1617
|
-
ref:
|
1646
|
+
ref: objectRef
|
1618
1647
|
}, rigidBodyProps, {
|
1619
1648
|
position: position,
|
1620
1649
|
rotation: rotation,
|
1621
1650
|
quaternion: quaternion,
|
1622
1651
|
scale: scale
|
1623
1652
|
}), /*#__PURE__*/React__default["default"].createElement("object3D", {
|
1624
|
-
ref:
|
1653
|
+
ref: instanceWrapperRef
|
1625
1654
|
}, children), instances === null || instances === void 0 ? void 0 : instances.map((instance, index) => /*#__PURE__*/React__default["default"].createElement(RigidBody, _extends({}, rigidBodyProps, instance, {
|
1626
|
-
ref: body =>
|
1655
|
+
ref: body => rigidBodiesRef.current[index] = body,
|
1627
1656
|
transformState: state => applyInstancedState(state, index)
|
1628
1657
|
}), /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, colliderNodes.map((node, index) => /*#__PURE__*/React__default["default"].createElement(React.Fragment, {
|
1629
1658
|
key: index
|
@@ -1644,14 +1673,15 @@ const useImpulseJoint = (body1, body2, params) => {
|
|
1644
1673
|
const jointRef = React.useRef();
|
1645
1674
|
useImperativeInstance(() => {
|
1646
1675
|
if (body1.current && body2.current) {
|
1647
|
-
const newJoint = world.createImpulseJoint(params, body1.current, body2.current);
|
1648
|
-
jointRef.current = newJoint;
|
1676
|
+
const newJoint = world.createImpulseJoint(params, body1.current, body2.current, true);
|
1677
|
+
jointRef.current = newJoint; // console.log(body1.current, body2.current, newJoint);
|
1678
|
+
|
1649
1679
|
return newJoint;
|
1650
1680
|
}
|
1651
1681
|
}, joint => {
|
1652
1682
|
if (joint) {
|
1653
1683
|
jointRef.current = undefined;
|
1654
|
-
world.removeImpulseJoint(joint);
|
1684
|
+
world.removeImpulseJoint(joint, true);
|
1655
1685
|
}
|
1656
1686
|
}, []);
|
1657
1687
|
return jointRef;
|