Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 8d3573f

Browse files
committed
wip
1 parent 59f0dda commit 8d3573f

File tree

58 files changed

+302
-421
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+302
-421
lines changed

libs/cannon/debug/src/lib/debug.ts

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
import { Component, CUSTOM_ELEMENTS_SCHEMA, forwardRef, Input, type OnInit } from '@angular/core';
1+
import { Component, CUSTOM_ELEMENTS_SCHEMA, Input, type OnInit } from '@angular/core';
22
import { propsToBody, type BodyProps, type BodyShapeType } from '@pmndrs/cannon-worker-api';
3-
import { injectBeforeRender, NgtArgs } from 'angular-three';
3+
import { createApiToken, injectBeforeRender, NgtArgs } from 'angular-three';
44
import { injectNgtcPhysicsApi } from 'angular-three-cannon';
55
import type { Body, Quaternion as CQuarternion, Vec3, World } from 'cannon-es';
66
import CannonDebugger from 'cannon-es-debugger';
7-
import { createInjectionToken } from 'ngxtension/create-injection-token';
87
import * as THREE from 'three';
98

109
const q = new THREE.Quaternion();
@@ -20,10 +19,7 @@ function getMatrix(o: THREE.Object3D): THREE.Matrix4 {
2019
return o.matrix;
2120
}
2221

23-
export const [injectNgtcDebugApi, provideNgtcDebugApi] = createInjectionToken((debug: NgtcDebug) => debug.api, {
24-
isRoot: false,
25-
deps: [forwardRef(() => NgtcDebug)],
26-
});
22+
export const [injectNgtcDebugApi, provideNgtcDebugApi] = createApiToken(() => NgtcDebug);
2723

2824
@Component({
2925
selector: 'ngtc-debug',

libs/cannon/services/src/lib/body.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { effect, runInInjectionContext, type ElementRef, type Injector } from '@angular/core';
1+
import { effect, type ElementRef, type Injector } from '@angular/core';
22
import type {
33
AtomicName,
44
AtomicProps,
@@ -19,8 +19,8 @@ import type {
1919
SphereArgs,
2020
SphereProps,
2121
SubscriptionName,
22-
SubscriptionTarget,
2322
Subscriptions,
23+
SubscriptionTarget,
2424
TrimeshProps,
2525
Triplet,
2626
VectorName,
@@ -234,8 +234,7 @@ function injectBody<TBodyProps extends BodyProps, TObject extends THREE.Object3D
234234
argsFn: NgtcArgFn<TBodyProps['args']>,
235235
{ ref, injector, deps = () => ({}) }: NgtcBodyOptions<TObject> = {},
236236
): NgtcBodyReturn<TObject> {
237-
injector = assertInjector(injectBody, injector);
238-
return runInInjectionContext(injector, () => {
237+
return assertInjector(injectBody, injector, () => {
239238
const [bodyRef, physicsApi, debugApi] = [
240239
ref || injectNgtRef<TObject>(),
241240
injectNgtcPhysicsApi(),

libs/cannon/services/src/lib/constraints.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { effect, runInInjectionContext, untracked, type Injector } from '@angular/core';
1+
import { effect, untracked, type Injector } from '@angular/core';
22
import type {
33
ConstraintOptns,
44
ConstraintTypes,
@@ -97,8 +97,7 @@ function injectConstraint<
9797
opts = () => ({}) as TOptions,
9898
}: NgtcConstraintOptions<TConstraintType, TOptions> = {},
9999
): NgtcConstraintReturn<TConstraintType, A, B> {
100-
injector = assertInjector(injectConstraint, injector);
101-
return runInInjectionContext(injector, () => {
100+
return assertInjector(injectConstraint, injector, () => {
102101
const physicsApi = injectNgtcPhysicsApi();
103102
const worker = physicsApi.select('worker');
104103

@@ -109,9 +108,10 @@ function injectConstraint<
109108

110109
effect((onCleanup) => {
111110
deps();
112-
if (bodyARef.nativeElement && bodyBRef.nativeElement) {
111+
const [a, b] = [bodyARef.nativeElement, bodyBRef.nativeElement];
112+
if (a && b) {
113113
worker().addConstraint({
114-
props: [bodyARef.untracked.uuid, bodyBRef.untracked.uuid, untracked(opts)],
114+
props: [a.uuid, b.uuid, untracked(opts)],
115115
type,
116116
uuid,
117117
});

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { effect, runInInjectionContext, untracked, type Injector } from '@angular/core';
1+
import { effect, untracked, type Injector } from '@angular/core';
22
import type { ContactMaterialOptions, MaterialOptions } from '@pmndrs/cannon-worker-api';
33
import { makeId, type NgtAnyRecord } from 'angular-three';
44
import { injectNgtcPhysicsApi } from 'angular-three-cannon';
@@ -13,8 +13,7 @@ export function injectContactMaterial(
1313
injector,
1414
}: { opts: () => ContactMaterialOptions; deps?: () => NgtAnyRecord; injector?: Injector },
1515
): void {
16-
injector = assertInjector(injectContactMaterial, injector);
17-
return runInInjectionContext(injector, () => {
16+
return assertInjector(injectContactMaterial, injector, () => {
1817
const physicsApi = injectNgtcPhysicsApi();
1918
const worker = physicsApi.select('worker');
2019
const uuid = makeId();

libs/cannon/services/src/lib/ray.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { effect, runInInjectionContext, untracked, type Injector } from '@angular/core';
1+
import { effect, untracked, type Injector } from '@angular/core';
22
import type { RayMode, RayOptions, RayhitEvent } from '@pmndrs/cannon-worker-api';
33
import { makeId, type NgtAnyRecord } from 'angular-three';
44
import { injectNgtcPhysicsApi } from 'angular-three-cannon';
@@ -24,8 +24,7 @@ export function useRaycastAll(opts: NgtcRayOptions) {
2424
}
2525

2626
function injectRay(mode: RayMode, { options, callback, deps = () => ({}), injector }: NgtcRayOptions) {
27-
injector = assertInjector(injectRay, injector);
28-
return runInInjectionContext(injector, () => {
27+
return assertInjector(injectRay, injector, () => {
2928
const physicsApi = injectNgtcPhysicsApi();
3029
const [worker, events] = [physicsApi.select('worker'), physicsApi.get('events')];
3130
const uuid = makeId();

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { effect, runInInjectionContext, untracked, type Injector } from '@angular/core';
1+
import { effect, untracked, type Injector } from '@angular/core';
22
import type { WheelInfoOptions } from '@pmndrs/cannon-worker-api';
33
import { injectNgtRef, type NgtAnyRecord, type NgtInjectedRef } from 'angular-three';
44
import { injectNgtcPhysicsApi } from 'angular-three-cannon';
@@ -40,8 +40,7 @@ export function injectRaycastVehicle<TObject extends THREE.Object3D = THREE.Obje
4040
deps = () => ({}),
4141
}: { ref?: NgtInjectedRef<TObject>; injector?: Injector; deps?: () => NgtAnyRecord } = {},
4242
): NgtcRaycastVehicleReturn<TObject> {
43-
injector = assertInjector(injectRaycastVehicle, injector);
44-
return runInInjectionContext(injector, () => {
43+
return assertInjector(injectRaycastVehicle, injector, () => {
4544
const physicsApi = injectNgtcPhysicsApi();
4645
const [worker, subscriptions] = [physicsApi.select('worker'), physicsApi.get('subscriptions')];
4746

libs/cannon/services/src/lib/spring.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { effect, runInInjectionContext, untracked, type Injector } from '@angular/core';
1+
import { effect, untracked, type Injector } from '@angular/core';
22
import type { SpringOptns } from '@pmndrs/cannon-worker-api';
33
import { injectNgtRef, is, makeId, type NgtAnyRecord, type NgtInjectedRef } from 'angular-three';
44
import { injectNgtcPhysicsApi } from 'angular-three-cannon';
@@ -29,8 +29,7 @@ export function injectSpring<A extends THREE.Object3D, B extends THREE.Object3D>
2929
deps = () => ({}),
3030
}: { injector?: Injector; deps?: () => NgtAnyRecord; opts?: () => SpringOptns } = {},
3131
): NgtcSpringReturn<A, B> {
32-
injector = assertInjector(injectSpring, injector);
33-
return runInInjectionContext(injector, () => {
32+
return assertInjector(injectSpring, injector, () => {
3433
const physicsApi = injectNgtcPhysicsApi();
3534
const worker = physicsApi.select('worker');
3635

libs/cannon/src/lib/physics.ts

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Component, Injector, Input, NgZone, effect, forwardRef, inject, untracked, type OnInit } from '@angular/core';
1+
import { Component, Injector, Input, NgZone, effect, inject, untracked, type OnInit } from '@angular/core';
22
import {
33
CannonWorkerAPI,
44
type Broadphase,
@@ -18,8 +18,7 @@ import {
1818
type WorkerFrameMessage,
1919
type WorkerRayhitEvent,
2020
} from '@pmndrs/cannon-worker-api';
21-
import { injectBeforeRender, injectNgtStore, signalStore } from 'angular-three';
22-
import { createInjectionToken } from 'ngxtension/create-injection-token';
21+
import { createApiToken, injectBeforeRender, injectNgtStore, signalStore } from 'angular-three';
2322
import * as THREE from 'three';
2423

2524
const v = new THREE.Vector3();
@@ -69,10 +68,7 @@ export type NgtcPhysicsApi = {
6968
worker: CannonWorkerAPI;
7069
};
7170

72-
export const [injectNgtcPhysicsApi, provideNgtcPhysicsApi] = createInjectionToken(
73-
(physics: NgtcPhysics) => physics.api,
74-
{ isRoot: false, deps: [forwardRef(() => NgtcPhysics)] },
75-
);
71+
export const [injectNgtcPhysicsApi, provideNgtcPhysicsApi] = createApiToken(() => NgtcPhysics);
7672

7773
@Component({
7874
selector: 'ngtc-physics',

libs/core/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export * from './lib/three-types';
1616
export * from './lib/types';
1717
export * from './lib/utils/apply-props';
1818
export { createAttachFunction } from './lib/utils/attach';
19+
export * from './lib/utils/create-api-token';
1920
export * from './lib/utils/is';
2021
export * from './lib/utils/make';
2122
export * from './lib/utils/safe-detect-changes';

libs/core/src/lib/before-render.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
1-
import { DestroyRef, Injector, inject, runInInjectionContext } from '@angular/core';
1+
import { DestroyRef, Injector, inject } from '@angular/core';
22
import { assertInjector } from 'ngxtension/assert-injector';
33
import { injectNgtStore, type NgtBeforeRenderRecord } from './store';
44

55
export function injectBeforeRender(
66
cb: NgtBeforeRenderRecord['callback'],
77
{ priority = 0, injector }: { priority?: number; injector?: Injector } = {},
88
) {
9-
injector = assertInjector(injectBeforeRender, injector);
10-
return runInInjectionContext(injector, () => {
9+
return assertInjector(injectBeforeRender, injector, () => {
1110
const store = injectNgtStore();
1211
const sub = store.get('internal').subscribe(cb, priority, store);
1312
inject(DestroyRef).onDestroy(() => void sub());

libs/core/src/lib/canvas.ts

Lines changed: 18 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -254,38 +254,32 @@ export class NgtCanvas implements OnInit, OnChanges {
254254
this.resizeEffectRef?.destroy();
255255

256256
const inputs = this.inputs.select();
257-
// NOTE: go back into zone so that effect runs
258257
// TODO: Double-check when effect is made not depended on zone
259-
this.resizeEffectRef = this.zone.run(() =>
260-
effect(
261-
() => {
262-
this.zone.runOutsideAngular(() => {
263-
if (!this.configurator) this.configurator = this.initRoot(this.glCanvas.nativeElement);
264-
this.configurator.configure({ ...inputs(), size: result });
265-
this.configurator.startInvalidate();
266-
267-
if (this.glRef) {
268-
safeDetectChanges(this.cdr);
269-
} else {
270-
this.render();
271-
}
272-
});
273-
},
274-
{ manualCleanup: true, injector: this.injector },
275-
),
258+
this.resizeEffectRef = effect(
259+
() => {
260+
if (!this.configurator) this.configurator = this.initRoot(this.glCanvas.nativeElement);
261+
this.configurator.configure({ ...inputs(), size: result });
262+
263+
if (this.glRef) {
264+
safeDetectChanges(this.cdr);
265+
} else {
266+
this.render();
267+
}
268+
},
269+
{ manualCleanup: true, injector: this.injector },
276270
);
277271
}
278272
}
279273

274+
// NOTE: render outside of zone
280275
private render() {
281276
this.glEnvironmentInjector?.destroy();
282277
this.glRef?.destroy();
283278

284279
// Flag the canvas active, rendering will now begin
285280
this.store.set((state) => ({ internal: { ...state.internal, active: true } }));
286281

287-
const inputs = this.inputs.get();
288-
const state = this.store.get();
282+
const [inputs, state] = [this.inputs.get(), this.store.get()];
289283

290284
// connect to event source
291285
state.events.connect?.(
@@ -300,11 +294,11 @@ export class NgtCanvas implements OnInit, OnChanges {
300294
if (inputs.eventPrefix) {
301295
state.setEvents({
302296
compute: (event, store) => {
303-
const innerState = store.get();
297+
const { pointer, raycaster, camera, size } = store.get();
304298
const x = event[(inputs.eventPrefix + 'X') as keyof NgtDomEvent] as number;
305299
const y = event[(inputs.eventPrefix + 'Y') as keyof NgtDomEvent] as number;
306-
innerState.pointer.set((x / innerState.size.width) * 2 - 1, -(y / innerState.size.height) * 2 + 1);
307-
innerState.raycaster.setFromCamera(innerState.pointer, innerState.camera);
300+
pointer.set((x / size.width) * 2 - 1, -(y / size.height) * 2 + 1);
301+
raycaster.setFromCamera(pointer, camera);
308302
},
309303
});
310304
}
@@ -337,7 +331,7 @@ export class NgtCanvas implements OnInit, OnChanges {
337331
const originalDetectChanges = this.cdr.detectChanges.bind(this.cdr);
338332
this.cdr.detectChanges = () => {
339333
originalDetectChanges();
340-
safeDetectChanges(this.glRef?.changeDetectorRef);
334+
this.glRef && safeDetectChanges(this.glRef.changeDetectorRef);
341335
};
342336
}
343337

libs/core/src/lib/instance.ts

Lines changed: 45 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { EventEmitter, signal, untracked, type WritableSignal } from '@angular/core';
1+
import { EventEmitter } from '@angular/core';
22
import type { NgtEventHandlers } from './events';
33
import type { NgtState } from './store';
44
import type { NgtAnyRecord } from './types';
@@ -17,19 +17,20 @@ export type NgtAfterAttach<
1717
> = { parent: TParent; node: TChild };
1818

1919
export type NgtInstanceLocalState = {
20-
/** the state getter of the canvas that the instance is being rendered to */
20+
/** the store of the canvas that the instance is being rendered to */
2121
store: NgtSignalStore<NgtState>;
22-
// objects and parent are used when children are added with `attach` instead of being added to the Object3D scene graph
23-
nonObjects: WritableSignal<NgtInstanceNode[]>;
24-
// objects that are Object3D
25-
objects: WritableSignal<NgtInstanceNode[]>;
22+
// objects related to this instance
23+
instanceStore: NgtSignalStore<{
24+
objects: NgtInstanceNode[];
25+
nonObjects: NgtInstanceNode[];
26+
parent: NgtInstanceNode | null;
27+
nativeProps: NgtAnyRecord;
28+
}>;
2629
// shortcut to add/remove object to list
2730
add: (instance: NgtInstanceNode, type: 'objects' | 'nonObjects') => void;
2831
remove: (instance: NgtInstanceNode, type: 'objects' | 'nonObjects') => void;
29-
// native props signal
30-
nativeProps: NgtSignalStore<NgtAnyRecord>;
31-
// parent based on attach three instance
32-
parent: WritableSignal<NgtInstanceNode | null>;
32+
setNativeProps: (key: string, value: any) => void;
33+
setParent: (parent: NgtInstanceNode | null) => void;
3334
// if this THREE instance is a ngt-primitive
3435
primitive?: boolean;
3536
// if this THREE object has any events bound to it
@@ -78,40 +79,48 @@ export function prepare<TInstance extends object = NgtAnyRecord>(
7879

7980
if (localState?.primitive || !instance.__ngt__) {
8081
const {
81-
objects = signal<NgtInstanceNode[]>([]),
82-
nonObjects = signal<NgtInstanceNode[]>([]),
82+
instanceStore = signalStore<{
83+
objects: NgtInstanceNode[];
84+
nonObjects: NgtInstanceNode[];
85+
parent: NgtInstanceNode | null;
86+
nativeProps: NgtAnyRecord;
87+
}>({
88+
nativeProps: {},
89+
parent: null,
90+
objects: [],
91+
nonObjects: [],
92+
}),
8393
...rest
8494
} = localState || {};
8595

8696
instance.__ngt__ = {
8797
previousAttach: null,
8898
store: null,
89-
parent: signal(null),
9099
memoized: {},
91100
eventCount: 0,
92101
handlers: {},
93-
objects,
94-
nonObjects,
95-
nativeProps: signalStore<NgtAnyRecord>(),
102+
instanceStore,
96103
add: (object, type) => {
97-
untracked(() => {
98-
const current = instance.__ngt__[type]();
99-
const foundIndex = current.indexOf((obj: NgtInstanceNode) => obj === object);
100-
if (foundIndex > -1) {
101-
// if we add an object with the same reference, then we switch it out
102-
current.splice(foundIndex, 1, object);
103-
instance.__ngt__[type].set(current);
104-
} else {
105-
instance.__ngt__[type].update((prev) => [...prev, object]);
106-
}
107-
notifyAncestors(instance.__ngt__.parent());
108-
});
104+
const current = instance.__ngt__.instanceStore.get(type);
105+
const foundIndex = current.indexOf((obj: NgtInstanceNode) => obj === object);
106+
if (foundIndex > -1) {
107+
// if we add an object with the same reference, then we switch it out
108+
current.splice(foundIndex, 1, object);
109+
instance.__ngt__.instanceStore.set({ [type]: current });
110+
} else {
111+
instance.__ngt__.instanceStore.set((prev) => ({ [type]: [...prev[type], object] }));
112+
}
113+
notifyAncestors(instance.__ngt__.instanceStore.get('parent'));
109114
},
110115
remove: (object, type) => {
111-
untracked(() => {
112-
instance.__ngt__[type].update((prev) => prev.filter((o) => o !== object));
113-
notifyAncestors(instance.__ngt__.parent());
114-
});
116+
instance.__ngt__.instanceStore.set((prev) => ({ [type]: prev[type].filter((o) => o !== object) }));
117+
notifyAncestors(instance.__ngt__.instanceStore.get('parent'));
118+
},
119+
setNativeProps: (key, value) => {
120+
instance.__ngt__.instanceStore.set((prev) => ({ nativeProps: { ...prev.nativeProps, [key]: value } }));
121+
},
122+
setParent: (parent) => {
123+
instance.__ngt__.instanceStore.set({ parent });
115124
},
116125
...rest,
117126
} as NgtInstanceLocalState;
@@ -123,7 +132,8 @@ export function prepare<TInstance extends object = NgtAnyRecord>(
123132
function notifyAncestors(instance: NgtInstanceNode | null) {
124133
if (!instance) return;
125134
const localState = getLocalState(instance);
126-
if (localState.objects) localState.objects.update((prev) => prev);
127-
if (localState.nonObjects) localState.nonObjects.update((prev) => prev);
128-
notifyAncestors(localState.parent());
135+
if (localState.instanceStore) {
136+
localState.instanceStore.set((prev) => ({ objects: prev.objects, nonObjects: prev.nonObjects }));
137+
notifyAncestors(localState.instanceStore.get('parent'));
138+
}
129139
}

0 commit comments

Comments
 (0)