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' ;
3130import { mergeInputs } from 'ngxtension/inject-inputs' ;
3231import { InstancedMesh , Matrix4 , Object3D , Quaternion , QuaternionTuple , Vector3 } from 'three' ;
3332
@@ -81,7 +80,7 @@ export type NgtcCannonEvents = Record<string, Partial<NgtcCallbackByType<NgtcCan
8180
8281export 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} )
127131export 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