Skip to content

Commit 37edaa3

Browse files
Chau TranChau Tran
Chau Tran
authored and
Chau Tran
committed
fix(cannon): expose worker as signal so it is reactive
1 parent cfaf85e commit 37edaa3

File tree

7 files changed

+120
-115
lines changed

7 files changed

+120
-115
lines changed

libs/cannon/services/src/body.ts

Lines changed: 92 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,13 @@ import type {
2525
Triplet,
2626
VectorName,
2727
} from '@pmndrs/cannon-worker-api';
28-
import { NgtAnyRecord, NgtInjectedRef, assertInjectionContext, injectNgtRef } from 'angular-three';
28+
import {
29+
NgtAnyRecord,
30+
NgtInjectedRef,
31+
assertInjectionContext,
32+
injectNgtRef,
33+
queueMicrotaskInInjectionContext,
34+
} from 'angular-three';
2935
import { NGTC_PHYSICS_API, NgtcCannonEvents } from 'angular-three-cannon';
3036
import { NGTC_DEBUG_API } from 'angular-three-cannon/debug';
3137
import * as THREE from 'three';
@@ -242,72 +248,74 @@ function injectBody<TBodyProps extends BodyProps, TObject extends THREE.Object3D
242248
const physicsApi = inject(NGTC_PHYSICS_API);
243249
const debugApi = inject(NGTC_DEBUG_API, { optional: true });
244250

245-
const { refs, worker, subscriptions, scaleOverrides, events } = physicsApi();
246251
const { add: debugAdd, remove: debugRemove } = debugApi?.() || {};
252+
const { refs, worker, subscriptions, scaleOverrides, events } = physicsApi();
247253

248-
effect(
249-
(onCleanup) => {
250-
// register deps
251-
deps();
252-
253-
if (!bodyRef.untracked) {
254-
bodyRef.nativeElement = new THREE.Object3D() as TObject;
255-
}
256-
257-
const object = bodyRef.untracked;
258-
const currentWorker = worker;
259-
260-
const objectCount =
261-
object instanceof THREE.InstancedMesh
262-
? (object.instanceMatrix.setUsage(THREE.DynamicDrawUsage), object.count)
263-
: 1;
264-
265-
const uuid =
266-
object instanceof THREE.InstancedMesh
267-
? new Array(objectCount).fill(0).map((_, i) => `${object.uuid}/${i}`)
268-
: [object.uuid];
269-
270-
const props: (TBodyProps & { args: unknown })[] =
271-
object instanceof THREE.InstancedMesh
272-
? uuid.map((id, i) => {
273-
const props = getPropsFn(i);
274-
prepare(temp, props);
275-
object.setMatrixAt(i, temp.matrix);
276-
object.instanceMatrix.needsUpdate = true;
277-
refs[id] = object;
278-
debugAdd?.(id, props, type);
279-
setupCollision(events, props, id);
280-
return { ...props, args: argsFn(props.args) };
281-
})
282-
: uuid.map((id, i) => {
283-
const props = getPropsFn(i);
284-
prepare(object, props);
285-
refs[id] = object;
286-
debugAdd?.(id, props, type);
287-
setupCollision(events, props, id);
288-
return { ...props, args: argsFn(props.args) };
289-
});
290-
291-
// Register on mount, unregister on unmount
292-
currentWorker.addBodies({
293-
props: props.map(({ onCollide, onCollideBegin, onCollideEnd, ...serializableProps }) => {
294-
return { onCollide: Boolean(onCollide), ...serializableProps };
295-
}),
296-
type,
297-
uuid,
298-
});
299-
300-
onCleanup(() => {
301-
uuid.forEach((id) => {
302-
delete refs[id];
303-
debugRemove?.(id);
304-
delete events[id];
254+
queueMicrotaskInInjectionContext(() => {
255+
effect(
256+
(onCleanup) => {
257+
// register deps
258+
deps();
259+
260+
if (!bodyRef.nativeElement) {
261+
bodyRef.nativeElement = new THREE.Object3D() as TObject;
262+
}
263+
264+
const object = bodyRef.nativeElement;
265+
const currentWorker = worker();
266+
267+
const objectCount =
268+
object instanceof THREE.InstancedMesh
269+
? (object.instanceMatrix.setUsage(THREE.DynamicDrawUsage), object.count)
270+
: 1;
271+
272+
const uuid =
273+
object instanceof THREE.InstancedMesh
274+
? new Array(objectCount).fill(0).map((_, i) => `${object.uuid}/${i}`)
275+
: [object.uuid];
276+
277+
const props: (TBodyProps & { args: unknown })[] =
278+
object instanceof THREE.InstancedMesh
279+
? uuid.map((id, i) => {
280+
const props = getPropsFn(i);
281+
prepare(temp, props);
282+
object.setMatrixAt(i, temp.matrix);
283+
object.instanceMatrix.needsUpdate = true;
284+
refs[id] = object;
285+
debugAdd?.(id, props, type);
286+
setupCollision(events, props, id);
287+
return { ...props, args: argsFn(props.args) };
288+
})
289+
: uuid.map((id, i) => {
290+
const props = getPropsFn(i);
291+
prepare(object, props);
292+
refs[id] = object;
293+
debugAdd?.(id, props, type);
294+
setupCollision(events, props, id);
295+
return { ...props, args: argsFn(props.args) };
296+
});
297+
298+
// Register on mount, unregister on unmount
299+
currentWorker.addBodies({
300+
props: props.map(({ onCollide, onCollideBegin, onCollideEnd, ...serializableProps }) => {
301+
return { onCollide: Boolean(onCollide), ...serializableProps };
302+
}),
303+
type,
304+
uuid,
305305
});
306-
currentWorker.removeBodies({ uuid });
307-
});
308-
},
309-
{ allowSignalWrites: true }
310-
);
306+
307+
onCleanup(() => {
308+
uuid.forEach((id) => {
309+
delete refs[id];
310+
debugRemove?.(id);
311+
delete events[id];
312+
});
313+
currentWorker.removeBodies({ uuid });
314+
});
315+
},
316+
{ allowSignalWrites: true }
317+
);
318+
});
311319

312320
const api = computed(() => {
313321
const makeAtomic = <T extends AtomicName>(type: T, index?: number) => {
@@ -317,12 +325,12 @@ function injectBody<TBodyProps extends BodyProps, TObject extends THREE.Object3D
317325
set: (value: PropValue<T>) => {
318326
const uuid = getUUID(bodyRef, index);
319327
uuid &&
320-
worker[op]({
328+
worker()[op]({
321329
props: value,
322330
uuid,
323331
} as never);
324332
},
325-
subscribe: subscribe(bodyRef, worker, subscriptions, type, index),
333+
subscribe: subscribe(bodyRef, worker(), subscriptions, type, index),
326334
};
327335
};
328336

@@ -331,25 +339,25 @@ function injectBody<TBodyProps extends BodyProps, TObject extends THREE.Object3D
331339
return {
332340
copy: ({ w, x, y, z }: THREE.Quaternion) => {
333341
const uuid = getUUID(bodyRef, index);
334-
uuid && worker.setQuaternion({ props: [x, y, z, w], uuid });
342+
uuid && worker().setQuaternion({ props: [x, y, z, w], uuid });
335343
},
336344
set: (x: number, y: number, z: number, w: number) => {
337345
const uuid = getUUID(bodyRef, index);
338-
uuid && worker.setQuaternion({ props: [x, y, z, w], uuid });
346+
uuid && worker().setQuaternion({ props: [x, y, z, w], uuid });
339347
},
340-
subscribe: subscribe(bodyRef, worker, subscriptions, type, index),
348+
subscribe: subscribe(bodyRef, worker(), subscriptions, type, index),
341349
};
342350
};
343351

344352
const makeRotation = (index?: number) => {
345353
return {
346354
copy: ({ x, y, z }: THREE.Vector3 | THREE.Euler) => {
347355
const uuid = getUUID(bodyRef, index);
348-
uuid && worker.setRotation({ props: [x, y, z], uuid });
356+
uuid && worker().setRotation({ props: [x, y, z], uuid });
349357
},
350358
set: (x: number, y: number, z: number) => {
351359
const uuid = getUUID(bodyRef, index);
352-
uuid && worker.setRotation({ props: [x, y, z], uuid });
360+
uuid && worker().setRotation({ props: [x, y, z], uuid });
353361
},
354362
subscribe: (callback: (value: Triplet) => void) => {
355363
const id = incrementingId++;
@@ -358,10 +366,10 @@ function injectBody<TBodyProps extends BodyProps, TObject extends THREE.Object3D
358366
const uuid = getUUID(bodyRef, index);
359367

360368
subscriptions[id] = { [type]: quaternionToRotation(callback) };
361-
uuid && worker.subscribe({ props: { id, target, type }, uuid });
369+
uuid && worker().subscribe({ props: { id, target, type }, uuid });
362370
return () => {
363371
delete subscriptions[id];
364-
worker.unsubscribe({ props: id });
372+
worker().unsubscribe({ props: id });
365373
};
366374
},
367375
};
@@ -372,20 +380,20 @@ function injectBody<TBodyProps extends BodyProps, TObject extends THREE.Object3D
372380
return {
373381
copy: ({ x, y, z }: THREE.Vector3 | THREE.Euler) => {
374382
const uuid = getUUID(bodyRef, index);
375-
uuid && worker[op]({ props: [x, y, z], uuid });
383+
uuid && worker()[op]({ props: [x, y, z], uuid });
376384
},
377385
set: (x: number, y: number, z: number) => {
378386
const uuid = getUUID(bodyRef, index);
379-
uuid && worker[op]({ props: [x, y, z], uuid });
387+
uuid && worker()[op]({ props: [x, y, z], uuid });
380388
},
381-
subscribe: subscribe(bodyRef, worker, subscriptions, type, index),
389+
subscribe: subscribe(bodyRef, worker(), subscriptions, type, index),
382390
};
383391
};
384392

385393
const makeRemove = (index?: number) => {
386394
const uuid = getUUID(bodyRef, index);
387395
return () => {
388-
if (uuid) worker.removeBodies({ uuid: [uuid] });
396+
if (uuid) worker().removeBodies({ uuid: [uuid] });
389397
};
390398
};
391399

@@ -397,23 +405,23 @@ function injectBody<TBodyProps extends BodyProps, TObject extends THREE.Object3D
397405
angularVelocity: makeVec('angularVelocity', index),
398406
applyForce(force: Triplet, worldPoint: Triplet) {
399407
const uuid = getUUID(bodyRef, index);
400-
uuid && worker.applyForce({ props: [force, worldPoint], uuid });
408+
uuid && worker().applyForce({ props: [force, worldPoint], uuid });
401409
},
402410
applyImpulse(impulse: Triplet, worldPoint: Triplet) {
403411
const uuid = getUUID(bodyRef, index);
404-
uuid && worker.applyImpulse({ props: [impulse, worldPoint], uuid });
412+
uuid && worker().applyImpulse({ props: [impulse, worldPoint], uuid });
405413
},
406414
applyLocalForce(force: Triplet, localPoint: Triplet) {
407415
const uuid = getUUID(bodyRef, index);
408-
uuid && worker.applyLocalForce({ props: [force, localPoint], uuid });
416+
uuid && worker().applyLocalForce({ props: [force, localPoint], uuid });
409417
},
410418
applyLocalImpulse(impulse: Triplet, localPoint: Triplet) {
411419
const uuid = getUUID(bodyRef, index);
412-
uuid && worker.applyLocalImpulse({ props: [impulse, localPoint], uuid });
420+
uuid && worker().applyLocalImpulse({ props: [impulse, localPoint], uuid });
413421
},
414422
applyTorque(torque: Triplet) {
415423
const uuid = getUUID(bodyRef, index);
416-
uuid && worker.applyTorque({ props: [torque], uuid });
424+
uuid && worker().applyTorque({ props: [torque], uuid });
417425
},
418426
collisionFilterGroup: makeAtomic('collisionFilterGroup', index),
419427
collisionFilterMask: makeAtomic('collisionFilterMask', index),
@@ -433,7 +441,7 @@ function injectBody<TBodyProps extends BodyProps, TObject extends THREE.Object3D
433441
},
434442
sleep() {
435443
const uuid = getUUID(bodyRef, index);
436-
uuid && worker.sleep({ uuid });
444+
uuid && worker().sleep({ uuid });
437445
},
438446
sleepSpeedLimit: makeAtomic('sleepSpeedLimit', index),
439447
sleepTimeLimit: makeAtomic('sleepTimeLimit', index),
@@ -442,7 +450,7 @@ function injectBody<TBodyProps extends BodyProps, TObject extends THREE.Object3D
442450
remove: makeRemove(index),
443451
wakeUp() {
444452
const uuid = getUUID(bodyRef, index);
445-
uuid && worker.wakeUp({ uuid });
453+
uuid && worker().wakeUp({ uuid });
446454
},
447455
};
448456
}

libs/cannon/services/src/constraint.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -113,30 +113,30 @@ function injectConstraint<
113113
effect((onCleanup) => {
114114
deps();
115115
if (bodyARef.nativeElement && bodyBRef.nativeElement) {
116-
worker.addConstraint({
116+
worker().addConstraint({
117117
props: [bodyARef.untracked.uuid, bodyBRef.untracked.uuid, untracked(opts)],
118118
type,
119119
uuid,
120120
});
121-
onCleanup(() => worker.removeConstraint({ uuid }));
121+
onCleanup(() => worker().removeConstraint({ uuid }));
122122
}
123123
});
124124

125125
const api = computed(() => {
126126
deps();
127127
const enableDisable = {
128-
disable: () => worker.disableConstraint({ uuid }),
129-
enable: () => worker.enableConstraint({ uuid }),
130-
remove: () => worker.removeConstraint({ uuid }),
128+
disable: () => worker().disableConstraint({ uuid }),
129+
enable: () => worker().enableConstraint({ uuid }),
130+
remove: () => worker().removeConstraint({ uuid }),
131131
};
132132

133133
if (type === 'Hinge') {
134134
return {
135135
...enableDisable,
136-
disableMotor: () => worker.disableConstraintMotor({ uuid }),
137-
enableMotor: () => worker.enableConstraintMotor({ uuid }),
138-
setMotorMaxForce: (value: number) => worker.setConstraintMotorMaxForce({ props: value, uuid }),
139-
setMotorSpeed: (value: number) => worker.setConstraintMotorSpeed({ props: value, uuid }),
136+
disableMotor: () => worker().disableConstraintMotor({ uuid }),
137+
enableMotor: () => worker().enableConstraintMotor({ uuid }),
138+
setMotorMaxForce: (value: number) => worker().setConstraintMotorMaxForce({ props: value, uuid }),
139+
setMotorSpeed: (value: number) => worker().setConstraintMotorSpeed({ props: value, uuid }),
140140
} as NgtcConstraintORHingeApi<TConstraintType>;
141141
}
142142

libs/cannon/services/src/contact-material.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@ export function injectContactMaterial(
1919
const uuid = makeId();
2020
effect((onCleanup) => {
2121
deps();
22-
worker.addContactMaterial({
22+
worker().addContactMaterial({
2323
props: [materialA, materialB, untracked(opts)],
2424
uuid,
2525
});
26-
onCleanup(() => worker.removeContactMaterial({ uuid }));
26+
onCleanup(() => worker().removeContactMaterial({ uuid }));
2727
});
2828
});
2929
}

libs/cannon/services/src/ray.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@ function injectRay(mode: RayMode, { options, callback, deps = () => ({}), inject
3232
effect((onCleanup) => {
3333
deps();
3434
events[uuid] = { rayhit: callback };
35-
worker.addRay({ props: { ...untracked(options), mode }, uuid });
35+
worker().addRay({ props: { ...untracked(options), mode }, uuid });
3636
onCleanup(() => {
37-
worker.removeRay({ uuid });
37+
worker().removeRay({ uuid });
3838
delete events[uuid];
3939
});
4040
});

libs/cannon/services/src/raycast-vehicle.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ export function injectRaycastVehicle<TObject extends THREE.Object3D = THREE.Obje
5454
instanceRef.nativeElement = new THREE.Object3D() as TObject;
5555
}
5656

57-
const currentWorker = worker;
57+
const currentWorker = worker();
5858
const uuid: string = instanceRef.nativeElement.uuid;
5959
const {
6060
chassisBody,
@@ -87,30 +87,30 @@ export function injectRaycastVehicle<TObject extends THREE.Object3D = THREE.Obje
8787
applyEngineForce(value: number, wheelIndex: number) {
8888
const uuid = getUUID(instanceRef);
8989
uuid &&
90-
worker.applyRaycastVehicleEngineForce({
90+
worker().applyRaycastVehicleEngineForce({
9191
props: [value, wheelIndex],
9292
uuid,
9393
});
9494
},
9595
setBrake(brake: number, wheelIndex: number) {
9696
const uuid = getUUID(instanceRef);
97-
uuid && worker.setRaycastVehicleBrake({ props: [brake, wheelIndex], uuid });
97+
uuid && worker().setRaycastVehicleBrake({ props: [brake, wheelIndex], uuid });
9898
},
9999
setSteeringValue(value: number, wheelIndex: number) {
100100
const uuid = getUUID(instanceRef);
101101
uuid &&
102-
worker.setRaycastVehicleSteeringValue({
102+
worker().setRaycastVehicleSteeringValue({
103103
props: [value, wheelIndex],
104104
uuid,
105105
});
106106
},
107107
sliding: {
108-
subscribe: subscribe(instanceRef, worker, subscriptions, 'sliding', undefined, 'vehicles'),
108+
subscribe: subscribe(instanceRef, worker(), subscriptions, 'sliding', undefined, 'vehicles'),
109109
},
110110

111111
remove: () => {
112112
const uuid = getUUID(instanceRef);
113-
uuid && worker.removeRaycastVehicle({ uuid });
113+
uuid && worker().removeRaycastVehicle({ uuid });
114114
},
115115
};
116116
});

0 commit comments

Comments
 (0)