@vgai/engine 0.5.13 → 0.5.14
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/adapter/adapter-module.d.ts +447 -0
- package/dist/adapter/adapter-module.d.ts.map +1 -0
- package/dist/adapter/adapter-module.js +308 -0
- package/dist/adapter/authoring.d.ts +357 -10
- package/dist/adapter/authoring.d.ts.map +1 -1
- package/dist/adapter/authoring.js +87 -1
- package/dist/adapter/constraint.d.ts +9 -3
- package/dist/adapter/constraint.d.ts.map +1 -1
- package/dist/adapter/finders/finder-result.d.ts +28 -0
- package/dist/adapter/finders/finder-result.d.ts.map +1 -0
- package/dist/adapter/finders/finder-result.js +10 -0
- package/dist/adapter/finders/index.d.ts +38 -0
- package/dist/adapter/finders/index.d.ts.map +1 -0
- package/dist/adapter/finders/index.js +41 -0
- package/dist/adapter/finders/prefabs-from-stories.d.ts +64 -0
- package/dist/adapter/finders/prefabs-from-stories.d.ts.map +1 -0
- package/dist/adapter/finders/prefabs-from-stories.js +92 -0
- package/dist/adapter/finders/scenes-from-entrypoint-selection.d.ts +67 -0
- package/dist/adapter/finders/scenes-from-entrypoint-selection.d.ts.map +1 -0
- package/dist/adapter/finders/scenes-from-entrypoint-selection.js +226 -0
- package/dist/adapter/first-party-systems.d.ts.map +1 -1
- package/dist/adapter/first-party-systems.js +29 -0
- package/dist/adapter/index.d.ts +7 -3
- package/dist/adapter/index.d.ts.map +1 -1
- package/dist/adapter/index.js +5 -2
- package/dist/adapter/ingest/contract-system-adapters.d.ts +24 -1
- package/dist/adapter/ingest/contract-system-adapters.d.ts.map +1 -1
- package/dist/adapter/ingest/contract-system-adapters.js +100 -34
- package/dist/adapter/ingest/game-contract.d.ts +188 -2
- package/dist/adapter/ingest/game-contract.d.ts.map +1 -1
- package/dist/adapter/ingest/game-contract.js +107 -0
- package/dist/adapter/ingest/mount-readiness.d.ts +84 -0
- package/dist/adapter/ingest/mount-readiness.d.ts.map +1 -0
- package/dist/adapter/ingest/mount-readiness.js +81 -0
- package/dist/adapter/ingest/scene-capture.d.ts +91 -2
- package/dist/adapter/ingest/scene-capture.d.ts.map +1 -1
- package/dist/adapter/ingest/scene-capture.js +110 -18
- package/dist/adapter/ingest/structural-ids.d.ts +11 -5
- package/dist/adapter/ingest/structural-ids.d.ts.map +1 -1
- package/dist/adapter/ingest/structural-ids.js +18 -9
- package/dist/adapter/ingest/upstream-pin.d.ts +4 -2
- package/dist/adapter/ingest/upstream-pin.d.ts.map +1 -1
- package/dist/adapter/ingest/upstream-pin.js +4 -2
- package/dist/adapter/ingest/visible-capture-window.d.ts +116 -0
- package/dist/adapter/ingest/visible-capture-window.d.ts.map +1 -0
- package/dist/adapter/ingest/visible-capture-window.js +141 -0
- package/dist/adapter/loop-gate-report.d.ts +3 -4
- package/dist/adapter/loop-gate-report.d.ts.map +1 -1
- package/dist/adapter/loop-gate-report.js +3 -4
- package/dist/adapter/root-adapter.d.ts +22 -2
- package/dist/adapter/root-adapter.d.ts.map +1 -1
- package/dist/adapter/setup-three-root-adapter.d.ts.map +1 -1
- package/dist/adapter/setup-three-root-adapter.js +15 -0
- package/dist/adapter/system-adapter.d.ts +161 -2
- package/dist/adapter/system-adapter.d.ts.map +1 -1
- package/dist/adapter/system-adapter.js +18 -1
- package/dist/animation/camera-ownership.d.ts +4 -2
- package/dist/animation/camera-ownership.d.ts.map +1 -1
- package/dist/animation/camera-ownership.js +58 -1
- package/dist/animation/runtime-inspection.d.ts +70 -0
- package/dist/animation/runtime-inspection.d.ts.map +1 -0
- package/dist/animation/runtime-inspection.js +25 -0
- package/dist/animation/xstate-animation-binding.d.ts +9 -1
- package/dist/animation/xstate-animation-binding.d.ts.map +1 -1
- package/dist/animation/xstate-animation-binding.js +48 -1
- package/dist/asset-formats/material.d.ts +1 -1
- package/dist/asset-formats/mesh.d.ts +1 -1
- package/dist/asset-formats/particles.d.ts +13 -0
- package/dist/asset-formats/particles.d.ts.map +1 -1
- package/dist/asset-formats/particles.js +28 -0
- package/dist/behavior/xstate-inspection.d.ts +24 -0
- package/dist/behavior/xstate-inspection.d.ts.map +1 -0
- package/dist/behavior/xstate-inspection.js +25 -0
- package/dist/core/game-loop.d.ts +7 -5
- package/dist/core/game-loop.d.ts.map +1 -1
- package/dist/core/game-loop.js +39 -18
- package/dist/core/types.d.ts +11 -12
- package/dist/core/types.d.ts.map +1 -1
- package/dist/data/data-asset.js +1 -1
- package/dist/dev/instruments.d.ts.map +1 -1
- package/dist/dev/instruments.js +5 -1
- package/dist/dev/render-debug-adapter.d.ts +19 -2
- package/dist/dev/render-debug-adapter.d.ts.map +1 -1
- package/dist/dev/render-debug-adapter.js +10 -0
- package/dist/ecs/user-data.d.ts +10 -2
- package/dist/ecs/user-data.d.ts.map +1 -1
- package/dist/ecs/user-data.js +6 -2
- package/dist/input/binding-identity.d.ts +10 -0
- package/dist/input/binding-identity.d.ts.map +1 -0
- package/dist/input/binding-identity.js +36 -0
- package/dist/input/input-manager.d.ts +18 -185
- package/dist/input/input-manager.d.ts.map +1 -1
- package/dist/input/input-manager.js +78 -68
- package/dist/manifest/load.d.ts +14 -0
- package/dist/manifest/load.d.ts.map +1 -1
- package/dist/manifest/load.js +6 -1
- package/dist/manifest/schema.d.ts +18 -0
- package/dist/manifest/schema.d.ts.map +1 -1
- package/dist/manifest/schema.js +64 -7
- package/dist/pixi/authoring.d.ts +27 -0
- package/dist/pixi/authoring.d.ts.map +1 -1
- package/dist/pixi/authoring.js +10 -3
- package/dist/pixi/index.d.ts +1 -1
- package/dist/pixi/index.d.ts.map +1 -1
- package/dist/pixi/index.js +1 -1
- package/dist/pixi/ingest.d.ts +8 -0
- package/dist/pixi/ingest.d.ts.map +1 -1
- package/dist/pixi/ingest.js +10 -1
- package/dist/pixi/render-pass-bracket.d.ts +56 -0
- package/dist/pixi/render-pass-bracket.d.ts.map +1 -0
- package/dist/pixi/render-pass-bracket.js +98 -0
- package/dist/pixi/scene-capture.d.ts +32 -1
- package/dist/pixi/scene-capture.d.ts.map +1 -1
- package/dist/pixi/scene-capture.js +21 -9
- package/dist/pixi/system-adapters.d.ts +29 -0
- package/dist/pixi/system-adapters.d.ts.map +1 -1
- package/dist/pixi/system-adapters.js +27 -0
- package/dist/render/particles-factory.d.ts +16 -2
- package/dist/render/particles-factory.d.ts.map +1 -1
- package/dist/render/particles-factory.js +88 -5
- package/dist/render/soft-particle-depth.d.ts +149 -0
- package/dist/render/soft-particle-depth.d.ts.map +1 -0
- package/dist/render/soft-particle-depth.js +305 -0
- package/dist/render/voxel-surface.d.ts +117 -0
- package/dist/render/voxel-surface.d.ts.map +1 -0
- package/dist/render/voxel-surface.js +263 -0
- package/dist/runtime/create-runtime.js +7 -0
- package/dist/runtime/debug-bridge.d.ts +15 -15
- package/dist/runtime/debug-bridge.d.ts.map +1 -1
- package/dist/runtime/debug-bridge.js +27 -26
- package/dist/runtime/game.d.ts.map +1 -1
- package/dist/runtime/game.js +1 -2
- package/dist/setup/setup-particles.d.ts.map +1 -1
- package/dist/setup/setup-particles.js +9 -0
- package/dist/world3d-react/r3f-adapter.d.ts.map +1 -1
- package/dist/world3d-react/r3f-adapter.js +42 -3
- package/dist/world3d-react/rapier-physics-bridge.d.ts.map +1 -1
- package/dist/world3d-react/rapier-physics-bridge.js +201 -11
- package/dist-config/config.js.map +1 -1
- package/package.json +4 -2
- package/schemas/engine-capabilities.json +12 -12
- package/schemas/vgai-project.schema.json +41 -2
- package/src/adapter/adapter-module.ts +607 -0
- package/src/adapter/authoring.ts +440 -10
- package/src/adapter/constraint.ts +10 -3
- package/src/adapter/finders/finder-result.ts +29 -0
- package/src/adapter/finders/index.ts +62 -0
- package/src/adapter/finders/prefabs-from-stories.ts +142 -0
- package/src/adapter/finders/scenes-from-entrypoint-selection.ts +304 -0
- package/src/adapter/first-party-systems.ts +30 -0
- package/src/adapter/index.ts +32 -1
- package/src/adapter/ingest/contract-system-adapters.ts +116 -32
- package/src/adapter/ingest/game-contract.ts +265 -2
- package/src/adapter/ingest/mount-readiness.ts +140 -0
- package/src/adapter/ingest/scene-capture.ts +199 -22
- package/src/adapter/ingest/structural-ids.ts +21 -9
- package/src/adapter/ingest/upstream-pin.ts +4 -2
- package/src/adapter/ingest/visible-capture-window.ts +213 -0
- package/src/adapter/loop-gate-report.ts +3 -4
- package/src/adapter/root-adapter.ts +22 -2
- package/src/adapter/setup-three-root-adapter.ts +16 -0
- package/src/adapter/system-adapter.ts +188 -2
- package/src/animation/camera-ownership.ts +68 -3
- package/src/animation/runtime-inspection.ts +104 -0
- package/src/animation/xstate-animation-binding.ts +53 -1
- package/src/asset-formats/particles.ts +31 -0
- package/src/behavior/xstate-inspection.ts +51 -0
- package/src/core/game-loop.ts +39 -17
- package/src/core/types.ts +11 -12
- package/src/data/data-asset.ts +1 -1
- package/src/dev/instruments.ts +5 -1
- package/src/dev/render-debug-adapter.ts +22 -2
- package/src/ecs/user-data.ts +10 -2
- package/src/input/binding-identity.ts +37 -0
- package/src/input/input-manager.ts +93 -68
- package/src/manifest/load.ts +23 -2
- package/src/manifest/schema.ts +76 -7
- package/src/pixi/authoring.ts +37 -5
- package/src/pixi/index.ts +2 -0
- package/src/pixi/ingest.ts +15 -2
- package/src/pixi/render-pass-bracket.ts +117 -0
- package/src/pixi/scene-capture.ts +63 -13
- package/src/pixi/system-adapters.ts +41 -0
- package/src/render/particles-factory.ts +89 -6
- package/src/render/soft-particle-depth.ts +336 -0
- package/src/render/voxel-surface.ts +358 -0
- package/src/runtime/create-runtime.ts +7 -0
- package/src/runtime/debug-bridge.ts +32 -31
- package/src/runtime/game.ts +1 -2
- package/src/setup/setup-particles.ts +9 -0
- package/src/world3d-react/r3f-adapter.tsx +48 -2
- package/src/world3d-react/rapier-physics-bridge.tsx +249 -11
|
@@ -61,12 +61,18 @@
|
|
|
61
61
|
|
|
62
62
|
import { type RapierRigidBody, useRapier } from '@react-three/rapier';
|
|
63
63
|
import { useEffect } from 'react';
|
|
64
|
-
import
|
|
64
|
+
import * as THREE from 'three';
|
|
65
65
|
import {
|
|
66
66
|
createRapierBodyEditing,
|
|
67
67
|
type RapierEditableBody,
|
|
68
68
|
} from '../adapter/rapier-physics-adapter';
|
|
69
|
-
import type {
|
|
69
|
+
import type {
|
|
70
|
+
PhysicsAdapter,
|
|
71
|
+
PhysicsColliderShape,
|
|
72
|
+
PhysicsColliderSnapshot,
|
|
73
|
+
PhysicsJointSnapshot,
|
|
74
|
+
PhysicsJointType,
|
|
75
|
+
} from '../adapter/system-adapter';
|
|
70
76
|
import { useGameContext } from './engine-bridge';
|
|
71
77
|
|
|
72
78
|
export interface RapierPhysicsBridgeProps {
|
|
@@ -79,6 +85,38 @@ export interface RapierPhysicsBridgeProps {
|
|
|
79
85
|
readonly onDebugChange: (debug: boolean) => void;
|
|
80
86
|
}
|
|
81
87
|
|
|
88
|
+
interface RapierBodyStateLike {
|
|
89
|
+
readonly object: THREE.Object3D;
|
|
90
|
+
readonly rigidBody: RapierRigidBody;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function lateEntityObject(
|
|
94
|
+
states: Iterable<RapierBodyStateLike>,
|
|
95
|
+
nodeId: string,
|
|
96
|
+
): THREE.Object3D | undefined {
|
|
97
|
+
let found: THREE.Object3D | undefined;
|
|
98
|
+
for (const state of states) {
|
|
99
|
+
state.object.traverse((candidate) => {
|
|
100
|
+
if (!found && candidate.userData['entityId'] === nodeId) found = candidate;
|
|
101
|
+
});
|
|
102
|
+
if (found) return found;
|
|
103
|
+
}
|
|
104
|
+
return undefined;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function owningBody(
|
|
108
|
+
object: THREE.Object3D,
|
|
109
|
+
states: Iterable<RapierBodyStateLike>,
|
|
110
|
+
): RapierRigidBody | undefined {
|
|
111
|
+
const byObject = new Map<THREE.Object3D, RapierRigidBody>();
|
|
112
|
+
for (const state of states) byObject.set(state.object, state.rigidBody);
|
|
113
|
+
for (let node: THREE.Object3D | null = object; node; node = node.parent) {
|
|
114
|
+
const body = byObject.get(node);
|
|
115
|
+
if (body) return body;
|
|
116
|
+
}
|
|
117
|
+
return undefined;
|
|
118
|
+
}
|
|
119
|
+
|
|
82
120
|
/**
|
|
83
121
|
* Register this R3F world's `@react-three/rapier` physics as the game's
|
|
84
122
|
* `SystemAdapters.physics`. Mount it once, INSIDE `<Physics>` (it reads
|
|
@@ -86,7 +124,7 @@ export interface RapierPhysicsBridgeProps {
|
|
|
86
124
|
*/
|
|
87
125
|
export function RapierPhysicsBridge({ onDebugChange }: RapierPhysicsBridgeProps): null {
|
|
88
126
|
const ctx = useGameContext();
|
|
89
|
-
const { rigidBodyStates } = useRapier();
|
|
127
|
+
const { colliderStates, rapier, rigidBodyStates, world } = useRapier();
|
|
90
128
|
const registerSystemAdapter = ctx.registerSystemAdapter;
|
|
91
129
|
|
|
92
130
|
useEffect(() => {
|
|
@@ -114,24 +152,224 @@ export function RapierPhysicsBridge({ onDebugChange }: RapierPhysicsBridgeProps)
|
|
|
114
152
|
* `setSceneCamera`), so a destructured copy would be permanently absent.
|
|
115
153
|
*/
|
|
116
154
|
const bodyFor = (nodeId: string): RapierEditableBody | undefined => {
|
|
117
|
-
const
|
|
155
|
+
const indexed = ctx.sceneIndex?.byEntityId(nodeId);
|
|
156
|
+
const object = indexed ?? lateEntityObject(rigidBodyStates.values(), nodeId);
|
|
157
|
+
if (!indexed && object) {
|
|
158
|
+
// The editor assigns its stable authoring entity ids AFTER Fiber's
|
|
159
|
+
// first commit, while the root's SceneIndex is constructed during
|
|
160
|
+
// that commit. Resolve the one late id inside the library-owned body
|
|
161
|
+
// subtrees and immediately reindex it; subsequent gestures take the
|
|
162
|
+
// normal indexed path. This is the SceneIndex's documented escape
|
|
163
|
+
// hatch for a userData id written after construction, not a parallel
|
|
164
|
+
// scene mirror.
|
|
165
|
+
ctx.sceneIndex?.reindex(object);
|
|
166
|
+
}
|
|
118
167
|
if (!object) return undefined;
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
168
|
+
return owningBody(object, rigidBodyStates.values());
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
const colliderShape = (collider: {
|
|
172
|
+
shapeType(): number;
|
|
173
|
+
halfExtents(): { x: number; y: number; z: number };
|
|
174
|
+
radius(): number;
|
|
175
|
+
halfHeight(): number;
|
|
176
|
+
}): PhysicsColliderShape | null => {
|
|
177
|
+
switch (collider.shapeType()) {
|
|
178
|
+
case rapier.ShapeType.Cuboid: {
|
|
179
|
+
const halfExtents = collider.halfExtents();
|
|
180
|
+
return { type: 'cuboid', halfExtents: [halfExtents.x, halfExtents.y, halfExtents.z] };
|
|
181
|
+
}
|
|
182
|
+
case rapier.ShapeType.Ball:
|
|
183
|
+
return { type: 'ball', radius: collider.radius() };
|
|
184
|
+
case rapier.ShapeType.Capsule:
|
|
185
|
+
return {
|
|
186
|
+
type: 'capsule',
|
|
187
|
+
halfHeight: collider.halfHeight(),
|
|
188
|
+
radius: collider.radius(),
|
|
189
|
+
};
|
|
190
|
+
default:
|
|
191
|
+
return null;
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
const colliders = (nodeId: string): PhysicsColliderSnapshot[] => {
|
|
196
|
+
const body = bodyFor(nodeId) as RapierRigidBody | undefined;
|
|
197
|
+
if (!body) return [];
|
|
198
|
+
const result: PhysicsColliderSnapshot[] = [];
|
|
199
|
+
for (const state of colliderStates.values()) {
|
|
200
|
+
if (state.collider.parent()?.handle !== body.handle) continue;
|
|
201
|
+
const shape = colliderShape(state.collider);
|
|
202
|
+
if (!shape) continue;
|
|
203
|
+
state.object.updateWorldMatrix(true, false);
|
|
204
|
+
const position = state.collider.translation();
|
|
205
|
+
const rotation = state.collider.rotation();
|
|
206
|
+
const scale = state.object.getWorldScale(new THREE.Vector3());
|
|
207
|
+
result.push({
|
|
208
|
+
id: String(state.collider.handle),
|
|
209
|
+
shape,
|
|
210
|
+
position: [position.x, position.y, position.z],
|
|
211
|
+
rotation: [rotation.x, rotation.y, rotation.z, rotation.w],
|
|
212
|
+
scale: [Math.abs(scale.x), Math.abs(scale.y), Math.abs(scale.z)],
|
|
213
|
+
sensor: state.collider.isSensor(),
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
return result.sort((a, b) => Number(a.id) - Number(b.id));
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
const previewCollider = (colliderId: string, shape: PhysicsColliderShape): void => {
|
|
220
|
+
const collider = [...colliderStates.values()].find(
|
|
221
|
+
(state) => String(state.collider.handle) === colliderId,
|
|
222
|
+
)?.collider;
|
|
223
|
+
if (!collider || colliderShape(collider)?.type !== shape.type) return;
|
|
224
|
+
switch (shape.type) {
|
|
225
|
+
case 'cuboid':
|
|
226
|
+
collider.setHalfExtents({
|
|
227
|
+
x: shape.halfExtents[0],
|
|
228
|
+
y: shape.halfExtents[1],
|
|
229
|
+
z: shape.halfExtents[2],
|
|
230
|
+
});
|
|
231
|
+
break;
|
|
232
|
+
case 'ball':
|
|
233
|
+
collider.setRadius(shape.radius);
|
|
234
|
+
break;
|
|
235
|
+
case 'capsule':
|
|
236
|
+
collider.setHalfHeight(shape.halfHeight);
|
|
237
|
+
collider.setRadius(shape.radius);
|
|
238
|
+
break;
|
|
124
239
|
}
|
|
125
|
-
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
const jointType = (type: number): PhysicsJointType => {
|
|
243
|
+
switch (type) {
|
|
244
|
+
case rapier.JointType.Revolute:
|
|
245
|
+
return 'revolute';
|
|
246
|
+
case rapier.JointType.Fixed:
|
|
247
|
+
return 'fixed';
|
|
248
|
+
case rapier.JointType.Prismatic:
|
|
249
|
+
return 'prismatic';
|
|
250
|
+
case rapier.JointType.Rope:
|
|
251
|
+
return 'rope';
|
|
252
|
+
case rapier.JointType.Spring:
|
|
253
|
+
return 'spring';
|
|
254
|
+
case rapier.JointType.Spherical:
|
|
255
|
+
return 'spherical';
|
|
256
|
+
default:
|
|
257
|
+
return 'generic';
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
const tuple3 = (value: { x: number; y: number; z: number }): [number, number, number] => [
|
|
262
|
+
value.x,
|
|
263
|
+
value.y,
|
|
264
|
+
value.z,
|
|
265
|
+
];
|
|
266
|
+
const tuple4 = (value: {
|
|
267
|
+
x: number;
|
|
268
|
+
y: number;
|
|
269
|
+
z: number;
|
|
270
|
+
w: number;
|
|
271
|
+
}): [number, number, number, number] => [value.x, value.y, value.z, value.w];
|
|
272
|
+
const worldAnchor = (
|
|
273
|
+
body: RapierRigidBody,
|
|
274
|
+
anchor: { x: number; y: number; z: number },
|
|
275
|
+
): [number, number, number] => {
|
|
276
|
+
const point = new THREE.Vector3(anchor.x, anchor.y, anchor.z)
|
|
277
|
+
.applyQuaternion(new THREE.Quaternion(...tuple4(body.rotation())))
|
|
278
|
+
.add(new THREE.Vector3(...tuple3(body.translation())));
|
|
279
|
+
return tuple3(point);
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
type NativeImpulseJoint = ReturnType<typeof world.impulseJoints.getAll>[number];
|
|
283
|
+
const jointLimits = (
|
|
284
|
+
joint: NativeImpulseJoint,
|
|
285
|
+
type: PhysicsJointType,
|
|
286
|
+
): Pick<PhysicsJointSnapshot, 'limits'> => {
|
|
287
|
+
if (type !== 'revolute' && type !== 'prismatic') return {};
|
|
288
|
+
const unit = joint as unknown as {
|
|
289
|
+
limitsEnabled(): boolean;
|
|
290
|
+
limitsMin(): number;
|
|
291
|
+
limitsMax(): number;
|
|
292
|
+
};
|
|
293
|
+
return unit.limitsEnabled()
|
|
294
|
+
? { limits: { min: unit.limitsMin(), max: unit.limitsMax() } }
|
|
295
|
+
: {};
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
const jointAxis = (
|
|
299
|
+
joint: NativeImpulseJoint,
|
|
300
|
+
type: PhysicsJointType,
|
|
301
|
+
body: RapierRigidBody,
|
|
302
|
+
): Pick<PhysicsJointSnapshot, 'axis' | 'worldAxis'> => {
|
|
303
|
+
if (type !== 'revolute' && type !== 'prismatic') return {};
|
|
304
|
+
const frame = joint.frameX1();
|
|
305
|
+
const axis = new THREE.Vector3(1, 0, 0).applyQuaternion(
|
|
306
|
+
new THREE.Quaternion(frame.x, frame.y, frame.z, frame.w),
|
|
307
|
+
);
|
|
308
|
+
const worldAxis = axis
|
|
309
|
+
.clone()
|
|
310
|
+
.applyQuaternion(new THREE.Quaternion(...tuple4(body.rotation())));
|
|
311
|
+
return { axis: tuple3(axis), worldAxis: tuple3(worldAxis) };
|
|
312
|
+
};
|
|
313
|
+
|
|
314
|
+
const jointSnapshot = (joint: NativeImpulseJoint): PhysicsJointSnapshot => {
|
|
315
|
+
const body1 = joint.body1();
|
|
316
|
+
const body2 = joint.body2();
|
|
317
|
+
const anchor1 = joint.anchor1();
|
|
318
|
+
const anchor2 = joint.anchor2();
|
|
319
|
+
const type = jointType(joint.type());
|
|
320
|
+
return {
|
|
321
|
+
id: String(joint.handle),
|
|
322
|
+
type,
|
|
323
|
+
body1: String(body1.handle),
|
|
324
|
+
body2: String(body2.handle),
|
|
325
|
+
anchor1: tuple3(anchor1),
|
|
326
|
+
anchor2: tuple3(anchor2),
|
|
327
|
+
worldAnchor1: worldAnchor(body1, anchor1),
|
|
328
|
+
worldAnchor2: worldAnchor(body2, anchor2),
|
|
329
|
+
body1Position: tuple3(body1.translation()),
|
|
330
|
+
body2Position: tuple3(body2.translation()),
|
|
331
|
+
body1Rotation: tuple4(body1.rotation()),
|
|
332
|
+
body2Rotation: tuple4(body2.rotation()),
|
|
333
|
+
...jointAxis(joint, type, body1),
|
|
334
|
+
...jointLimits(joint, type),
|
|
335
|
+
contactsEnabled: joint.contactsEnabled(),
|
|
336
|
+
};
|
|
337
|
+
};
|
|
338
|
+
|
|
339
|
+
const joints = (nodeId: string): PhysicsJointSnapshot[] => {
|
|
340
|
+
const body = bodyFor(nodeId) as RapierRigidBody | undefined;
|
|
341
|
+
if (!body) return [];
|
|
342
|
+
const result: PhysicsJointSnapshot[] = [];
|
|
343
|
+
world.impulseJoints.forEachJointHandleAttachedToRigidBody(body.handle, (handle) => {
|
|
344
|
+
const joint = world.impulseJoints.get(handle);
|
|
345
|
+
if (joint) result.push(jointSnapshot(joint));
|
|
346
|
+
});
|
|
347
|
+
return result.sort((a, b) => Number(a.id) - Number(b.id));
|
|
348
|
+
};
|
|
349
|
+
|
|
350
|
+
const previewJointAnchor = (
|
|
351
|
+
jointId: string,
|
|
352
|
+
endpoint: 0 | 1,
|
|
353
|
+
anchor: readonly [number, number, number],
|
|
354
|
+
): void => {
|
|
355
|
+
const joint = world.impulseJoints.get(Number(jointId));
|
|
356
|
+
if (!joint) return;
|
|
357
|
+
const value = { x: anchor[0], y: anchor[1], z: anchor[2] };
|
|
358
|
+
if (endpoint === 0) joint.setAnchor1(value);
|
|
359
|
+
else joint.setAnchor2(value);
|
|
126
360
|
};
|
|
127
361
|
|
|
128
362
|
const adapter: PhysicsAdapter = {
|
|
129
363
|
...createRapierBodyEditing(bodyFor),
|
|
130
364
|
setDebugDrawEnabled: (enabled) => onDebugChange(enabled),
|
|
365
|
+
colliders,
|
|
366
|
+
previewCollider,
|
|
367
|
+
joints,
|
|
368
|
+
previewJointAnchor,
|
|
131
369
|
};
|
|
132
370
|
registerSystemAdapter('physics', adapter);
|
|
133
371
|
return () => registerSystemAdapter('physics', undefined);
|
|
134
|
-
}, [ctx, registerSystemAdapter, rigidBodyStates,
|
|
372
|
+
}, [colliderStates, ctx, onDebugChange, rapier, registerSystemAdapter, rigidBodyStates, world]);
|
|
135
373
|
|
|
136
374
|
return null;
|
|
137
375
|
}
|