Skip to content

Commit 7ecfb3f

Browse files
committed
fix(cannon): remove autoEffect in physics
1 parent 4c730bb commit 7ecfb3f

File tree

1 file changed

+49
-36
lines changed

1 file changed

+49
-36
lines changed

Diff for: libs/cannon/src/lib/physics.ts

+49-36
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
EmbeddedViewRef,
66
Signal,
77
afterNextRender,
8-
computed,
8+
effect,
99
inject,
1010
input,
1111
signal,
@@ -26,8 +26,7 @@ import {
2626
WorkerFrameMessage,
2727
WorkerRayhitEvent,
2828
} from '@pmndrs/cannon-worker-api';
29-
import { injectBeforeRender, injectStore } from 'angular-three';
30-
import { injectAutoEffect } from 'ngxtension/auto-effect';
29+
import { injectBeforeRender, injectStore, pick } from 'angular-three';
3130
import { mergeInputs } from 'ngxtension/inject-inputs';
3231
import { InstancedMesh, Matrix4, Object3D, Quaternion, QuaternionTuple, Vector3 } from 'three';
3332

@@ -81,7 +80,7 @@ export type NgtcCannonEvents = Record<string, Partial<NgtcCallbackByType<NgtcCan
8180

8281
export type ScaleOverrides = Record<string, Vector3>;
8382

84-
export interface NgtcPhysicsInputs extends CannonWorkerProps {
83+
export interface NgtcPhysicsOptions extends CannonWorkerProps {
8584
isPaused?: boolean;
8685
maxSubSteps?: number;
8786
shouldInvalidate?: boolean;
@@ -97,7 +96,7 @@ export interface NgtcPhysicsApi {
9796
worker: Signal<CannonWorkerAPI>;
9897
}
9998

100-
const defaultOptions: NgtcPhysicsInputs = {
99+
const defaultOptions: NgtcPhysicsOptions = {
101100
allowSleep: false,
102101
axisIndex: 0,
103102
broadphase: 'Naive',
@@ -116,6 +115,11 @@ const defaultOptions: NgtcPhysicsInputs = {
116115
tolerance: 0.001,
117116
};
118117

118+
type NgtsPhysicsUpdatableOptions = Extract<
119+
keyof NgtcPhysicsOptions,
120+
'gravity' | 'iterations' | 'tolerance' | 'broadphase' | 'axisIndex'
121+
>;
122+
119123
@Component({
120124
selector: 'ngtc-physics',
121125
standalone: true,
@@ -125,11 +129,16 @@ const defaultOptions: NgtcPhysicsInputs = {
125129
changeDetection: ChangeDetectionStrategy.OnPush,
126130
})
127131
export class NgtcPhysics {
128-
private autoEffect = injectAutoEffect();
129132
private store = injectStore();
130133

131134
options = input(defaultOptions, { transform: mergeInputs(defaultOptions) });
132135

136+
private axisIndex = pick(this.options, 'axisIndex');
137+
private broadphase = pick(this.options, 'broadphase');
138+
private gravity = pick(this.options, 'gravity');
139+
private iterations = pick(this.options, 'iterations');
140+
private tolerance = pick(this.options, 'tolerance');
141+
133142
private invalidate = this.store.select('invalidate');
134143
// @ts-expect-error - worker is not nullable, and we don't want to use ! operator
135144
private worker = signal<CannonWorkerAPI>(null);
@@ -148,12 +157,19 @@ export class NgtcPhysics {
148157
constructor() {
149158
afterNextRender(() => {
150159
this.worker.set(new CannonWorkerAPI(this.options()));
151-
this.connectWorker();
152-
this.updateWorkerState('axisIndex');
153-
this.updateWorkerState('broadphase');
154-
this.updateWorkerState('gravity');
155-
this.updateWorkerState('iterations');
156-
this.updateWorkerState('tolerance');
160+
});
161+
162+
effect((onCleanup) => {
163+
const cleanup = this.connectWorkerEffect();
164+
onCleanup(() => cleanup?.());
165+
});
166+
167+
effect(() => {
168+
this.updateWorkerStateEffect('axisIndex', this.axisIndex);
169+
this.updateWorkerStateEffect('broadphase', this.broadphase);
170+
this.updateWorkerStateEffect('gravity', this.gravity);
171+
this.updateWorkerStateEffect('iterations', this.iterations);
172+
this.updateWorkerStateEffect('tolerance', this.tolerance);
157173
});
158174

159175
let timeSinceLastCalled = 0;
@@ -170,35 +186,32 @@ export class NgtcPhysics {
170186
});
171187
}
172188

173-
private connectWorker() {
174-
this.autoEffect(() => {
175-
const worker = this.worker() as NgtcCannonWorker;
176-
if (!worker) return;
189+
private connectWorkerEffect() {
190+
const worker = this.worker() as NgtcCannonWorker;
191+
if (!worker) return;
177192

178-
worker.connect();
179-
worker.init();
193+
worker.connect();
194+
worker.init();
180195

181-
worker.on('collide', this.collideHandler.bind(this));
182-
worker.on('collideBegin', this.collideBeginHandler.bind(this));
183-
worker.on('collideEnd', this.collideEndHandler.bind(this));
184-
worker.on('frame', this.frameHandler.bind(this));
185-
worker.on('rayhit', this.rayhitHandler.bind(this));
196+
worker.on('collide', this.collideHandler.bind(this));
197+
worker.on('collideBegin', this.collideBeginHandler.bind(this));
198+
worker.on('collideEnd', this.collideEndHandler.bind(this));
199+
worker.on('frame', this.frameHandler.bind(this));
200+
worker.on('rayhit', this.rayhitHandler.bind(this));
186201

187-
return () => {
188-
worker.terminate();
189-
worker.removeAllListeners();
190-
};
191-
});
202+
return () => {
203+
worker.terminate();
204+
worker.removeAllListeners();
205+
};
192206
}
193207

194-
private updateWorkerState(key: keyof NgtcPhysicsInputs) {
195-
const computedValue = computed(() => this.options()[key]);
196-
197-
this.autoEffect(() => {
198-
const [worker, value] = [untracked(this.worker), computedValue()];
199-
// @ts-expect-error - we know key is a valid key of CannonWorkerAPI
200-
worker[key] = value;
201-
});
208+
private updateWorkerStateEffect<TUpdatableKey extends NgtsPhysicsUpdatableOptions>(
209+
key: TUpdatableKey,
210+
option: () => NgtcPhysicsOptions[TUpdatableKey],
211+
) {
212+
const worker = this.worker();
213+
if (!worker) return;
214+
Object.assign(worker, { [key]: option() });
202215
}
203216

204217
private collideHandler({ body, contact: { bi, bj, ...contactRest }, target, ...rest }: WorkerCollideEvent['data']) {

0 commit comments

Comments
 (0)