Skip to content

Commit 3fcd150

Browse files
committed
feat(rapier): adjust rapier effect usages
1 parent e8510b9 commit 3fcd150

File tree

6 files changed

+75
-41
lines changed

6 files changed

+75
-41
lines changed

Diff for: libs/rapier/src/lib/colliders.ts

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import {
1818
NgtrTrimeshArgs,
1919
} from './types';
2020

21+
// NOTE: this is ok to use here since we're not exporting this short-cut
2122
const ANY_COLLIDER_HOST_DIRECTIVE = {
2223
directive: NgtrAnyCollider,
2324
inputs: ['options', 'name', 'scale', 'position', 'quaternion', 'rotation', 'userData'],

Diff for: libs/rapier/src/lib/frame-stepper.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@ export class NgtrFrameStepper {
1616
const ready = this.ready();
1717
if (!ready) return;
1818

19-
const [type, updatePriority, stepFn] = [this.type(), this.updatePriority(), this.stepFn()];
19+
const [type, stepFn] = [this.type(), this.stepFn()];
20+
2021
if (type === 'follow') {
22+
const updatePriority = this.updatePriority();
2123
const cleanup = store.snapshot.internal.subscribe(
2224
({ delta }) => {
2325
stepFn(delta);

Diff for: libs/rapier/src/lib/instanced-rigid-bodies.ts

+26-9
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,16 @@ import {
1111
viewChild,
1212
viewChildren,
1313
} from '@angular/core';
14-
import { extend, getLocalState, NgtEuler, NgtObject3D, NgtQuaternion, NgtVector3, pick } from 'angular-three';
14+
import {
15+
applyProps,
16+
extend,
17+
getLocalState,
18+
NgtEuler,
19+
NgtObject3D,
20+
NgtQuaternion,
21+
NgtVector3,
22+
pick,
23+
} from 'angular-three';
1524
import { mergeInputs } from 'ngxtension/inject-inputs';
1625
import { DynamicDrawUsage, InstancedMesh, Object3D } from 'three';
1726
import { NgtrPhysics } from './physics';
@@ -70,13 +79,6 @@ const defaultOptions: NgtrRigidBodyOptions = rigidBodyDefaultOptions;
7079
`,
7180
schemas: [CUSTOM_ELEMENTS_SCHEMA],
7281
changeDetection: ChangeDetectionStrategy.OnPush,
73-
host: {
74-
'[position]': 'position()',
75-
'[rotation]': 'rotation()',
76-
'[scale]': 'scale()',
77-
'[quaternion]': 'quaternion()',
78-
'[userData]': 'userData()',
79-
},
8082
imports: [NgtrRigidBody, NgtrAnyCollider],
8183
})
8284
export class NgtrInstancedRigidBodies {
@@ -94,7 +96,17 @@ export class NgtrInstancedRigidBodies {
9496
});
9597
options = input(defaultOptions, { transform: mergeInputs(defaultOptions) });
9698

97-
instanceWrapperRef = viewChild.required<ElementRef<Object3D>>('instanceWrapper');
99+
private object3DParameters = computed(() => {
100+
return {
101+
position: this.position(),
102+
rotation: this.rotation(),
103+
scale: this.scale(),
104+
quaternion: this.quaternion(),
105+
userData: this.userData(),
106+
};
107+
});
108+
109+
private instanceWrapperRef = viewChild.required<ElementRef<Object3D>>('instanceWrapper');
98110
rigidBodyRefs = viewChildren(NgtrRigidBody);
99111

100112
private physics = inject(NgtrPhysics);
@@ -173,6 +185,11 @@ export class NgtrInstancedRigidBodies {
173185
constructor() {
174186
extend({ Object3D });
175187

188+
effect(() => {
189+
const object3DParameters = this.object3DParameters();
190+
applyProps(this.objectRef.nativeElement, object3DParameters);
191+
});
192+
176193
effect(() => {
177194
const instancedMesh = this.instancedMesh();
178195
if (!instancedMesh) return;

Diff for: libs/rapier/src/lib/mesh-collider.ts

+1-3
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import {
99
} from '@angular/core';
1010
import { extend, getLocalState } from 'angular-three';
1111
import { Object3D } from 'three';
12-
import { NgtrPhysics } from './physics';
1312
import { NgtrAnyCollider, NgtrRigidBody } from './rigid-body';
1413
import { NgtrRigidBodyAutoCollider } from './types';
1514
import { createColliderOptions } from './utils';
@@ -39,8 +38,7 @@ export class NgtrMeshCollider {
3938
colliders = input.required<NgtrRigidBodyAutoCollider>({ alias: 'ngtrMeshCollider' });
4039

4140
objectRef = inject<ElementRef<Object3D>>(ElementRef);
42-
rigidBody = inject(NgtrRigidBody);
43-
physics = inject(NgtrPhysics);
41+
private rigidBody = inject(NgtrRigidBody);
4442

4543
protected childColliderOptions = computed(() => {
4644
const rigidBodyOptions = this.rigidBody.options();

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

+10-8
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ export class NgtrPhysicsFallback {
6262
selector: 'ngtr-physics',
6363
standalone: true,
6464
template: `
65+
@let _rapierError = rapierError();
66+
@let _fallbackContent = fallbackContent();
67+
6568
@if (rapierConstruct()) {
6669
@if (debug()) {
6770
<ngtr-debug [world]="worldSingleton()?.proxy" />
@@ -75,8 +78,8 @@ export class NgtrPhysicsFallback {
7578
/>
7679
7780
<ng-container [ngTemplateOutlet]="content()" />
78-
} @else if (rapierError() && !!fallbackContent()) {
79-
<ng-container [ngTemplateOutlet]="$any(fallbackContent())" [ngTemplateOutletContext]="{ error: rapierError() }" />
81+
} @else if (_rapierError && _fallbackContent) {
82+
<ng-container [ngTemplateOutlet]="_fallbackContent" [ngTemplateOutletContext]="{ error: _rapierError }" />
8083
}
8184
`,
8285
changeDetection: ChangeDetectionStrategy.OnPush,
@@ -86,7 +89,7 @@ export class NgtrPhysics {
8689
options = input(defaultOptions, { transform: mergeInputs(defaultOptions) });
8790

8891
content = contentChild.required(TemplateRef);
89-
fallbackContent = contentChild(NgtrPhysicsFallback);
92+
fallbackContent = contentChild(NgtrPhysicsFallback, { read: TemplateRef });
9093

9194
protected updatePriority = pick(this.options, 'updatePriority');
9295
protected updateLoop = pick(this.options, 'updateLoop');
@@ -107,10 +110,9 @@ export class NgtrPhysics {
107110
debug = pick(this.options, 'debug');
108111
colliders = pick(this.options, 'colliders');
109112

110-
private gravity = vector3(this.options, 'gravity');
113+
private vGravity = vector3(this.options, 'gravity');
111114

112115
private store = injectStore();
113-
private destroyRef = inject(DestroyRef);
114116

115117
protected rapierConstruct = signal<typeof RAPIER | null>(null);
116118
protected rapierError = signal<string | null>(null);
@@ -120,7 +122,7 @@ export class NgtrPhysics {
120122
worldSingleton = computed(() => {
121123
const rapier = this.rapier();
122124
if (!rapier) return null;
123-
return createSingletonProxy<World>(() => new rapier.World(untracked(this.gravity)));
125+
return createSingletonProxy<World>(() => new rapier.World(untracked(this.vGravity)));
124126
});
125127

126128
rigidBodyStates: NgtrRigidBodyStateMap = new Map();
@@ -154,7 +156,7 @@ export class NgtrPhysics {
154156
this.updateWorldEffect();
155157
});
156158

157-
this.destroyRef.onDestroy(() => {
159+
inject(DestroyRef).onDestroy(() => {
158160
const world = this.worldSingleton();
159161
if (world) {
160162
world.proxy.free();
@@ -173,7 +175,7 @@ export class NgtrPhysics {
173175
const world = this.worldSingleton();
174176
if (!world) return;
175177

176-
world.proxy.gravity = this.gravity();
178+
world.proxy.gravity = this.vGravity();
177179
world.proxy.integrationParameters.numSolverIterations = this.numSolverIterations();
178180
world.proxy.integrationParameters.numAdditionalFrictionIterations = this.numAdditionalFrictionIterations();
179181
world.proxy.integrationParameters.numInternalPgsIterations = this.numInternalPgsIterations();

Diff for: libs/rapier/src/lib/rigid-body.ts

+34-20
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
} from '@angular/core';
1515
import { ActiveEvents, Collider, ColliderDesc, RigidBody, RigidBodyDesc } from '@dimforge/rapier3d-compat';
1616
import {
17+
applyProps,
1718
extend,
1819
getEmitter,
1920
getLocalState,
@@ -47,18 +48,7 @@ const colliderDefaultOptions: NgtrColliderOptions = {
4748
contactSkin: 0,
4849
};
4950

50-
@Directive({
51-
selector: 'ngt-object3D[ngtrCollider]',
52-
standalone: true,
53-
host: {
54-
'[position]': 'position()',
55-
'[rotation]': 'rotation()',
56-
'[scale]': 'scale()',
57-
'[quaternion]': 'quaternion()',
58-
'[userData]': 'userData()',
59-
'[name]': 'name()',
60-
},
61-
})
51+
@Directive({ selector: 'ngt-object3D[ngtrCollider]', standalone: true })
6252
export class NgtrAnyCollider {
6353
position = input<NgtVector3 | undefined>([0, 0, 0]);
6454
rotation = input<NgtEuler | undefined>([0, 0, 0]);
@@ -68,6 +58,17 @@ export class NgtrAnyCollider {
6858
name = input<NgtObject3D['name'] | undefined>();
6959
options = input(colliderDefaultOptions, { transform: mergeInputs(rigidBodyDefaultOptions) });
7060

61+
private object3DParameters = computed(() => {
62+
return {
63+
position: this.position(),
64+
rotation: this.rotation(),
65+
scale: this.scale(),
66+
quaternion: this.quaternion(),
67+
userData: this.userData(),
68+
name: this.name(),
69+
};
70+
});
71+
7172
// TODO: change this to input required when Angular allows setting hostDirective input
7273
shape = model<NgtrColliderShape | undefined>(undefined, { alias: 'ngtrCollider' });
7374
args = model<unknown[]>([]);
@@ -93,7 +94,7 @@ export class NgtrAnyCollider {
9394

9495
private rigidBody = inject(NgtrRigidBody, { optional: true });
9596
private physics = inject(NgtrPhysics);
96-
objectRef = inject<ElementRef<Object3D>>(ElementRef);
97+
private objectRef = inject<ElementRef<Object3D>>(ElementRef);
9798

9899
private scaledArgs = computed(() => {
99100
const [shape, args] = [
@@ -140,6 +141,11 @@ export class NgtrAnyCollider {
140141
constructor() {
141142
extend({ Object3D });
142143

144+
effect(() => {
145+
const object3DParameters = this.object3DParameters();
146+
applyProps(this.objectRef.nativeElement, object3DParameters);
147+
});
148+
143149
effect((onCleanup) => {
144150
const cleanup = this.createColliderStateEffect();
145151
onCleanup(() => cleanup?.());
@@ -407,13 +413,6 @@ export const rigidBodyDefaultOptions: NgtrRigidBodyOptions = {
407413
`,
408414
schemas: [CUSTOM_ELEMENTS_SCHEMA],
409415
changeDetection: ChangeDetectionStrategy.OnPush,
410-
host: {
411-
'[position]': 'position()',
412-
'[rotation]': 'rotation()',
413-
'[scale]': 'scale()',
414-
'[quaternion]': 'quaternion()',
415-
'[userData]': 'userData()',
416-
},
417416
imports: [NgtrAnyCollider],
418417
})
419418
export class NgtrRigidBody {
@@ -431,6 +430,16 @@ export class NgtrRigidBody {
431430
userData = input<NgtObject3D['userData'] | undefined>({});
432431
options = input(rigidBodyDefaultOptions, { transform: mergeInputs(rigidBodyDefaultOptions) });
433432

433+
private object3DParameters = computed(() => {
434+
return {
435+
position: this.position(),
436+
rotation: this.rotation(),
437+
scale: this.scale(),
438+
quaternion: this.quaternion(),
439+
userData: this.userData(),
440+
};
441+
});
442+
434443
wake = output<void>();
435444
sleep = output<void>();
436445
collisionEnter = output<NgtrCollisionEnterPayload>();
@@ -496,6 +505,11 @@ export class NgtrRigidBody {
496505
constructor() {
497506
extend({ Object3D });
498507

508+
effect(() => {
509+
const object3DParameters = this.object3DParameters();
510+
applyProps(this.objectRef.nativeElement, object3DParameters);
511+
});
512+
499513
effect((onCleanup) => {
500514
const cleanup = this.createRigidBodyStateEffect();
501515
onCleanup(() => cleanup?.());

0 commit comments

Comments
 (0)