Skip to content

Commit 774fc7b

Browse files
Chau TranChau Tran
Chau Tran
authored and
Chau Tran
committed
feat(core): expose "state" as signal readonly
1 parent 8f70a08 commit 774fc7b

File tree

8 files changed

+37
-55
lines changed

8 files changed

+37
-55
lines changed

libs/angular-three/src/lib/canvas.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -198,11 +198,10 @@ export class NgtCanvas extends NgtSignalStore<NgtCanvasInputs> implements OnInit
198198

199199
if (width > 0 && height > 0) {
200200
if (!this.#store.isInit) this.#store.init();
201-
const inputs = this.select();
202201
this.#resizeRef = this.#zone.run(() =>
203202
effect(
204203
() => {
205-
const canvasInputs = inputs();
204+
const canvasInputs = this.state();
206205
this.#zone.runOutsideAngular(() => {
207206
this.#store.configure(
208207
{ ...canvasInputs, size: { width, height, top, left } },

libs/angular-three/src/lib/portal.ts

Lines changed: 25 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
type OnInit,
2121
} from '@angular/core';
2222
import * as THREE from 'three';
23+
import { injectBeforeRender } from './di/before-render';
2324
import { injectNgtRef } from './di/ref';
2425
import { SPECIAL_INTERNAL_ADD_COMMENT } from './renderer/utils';
2526
import { NgtSignalStore } from './stores/signal.store';
@@ -28,6 +29,7 @@ import type { NgtEventManager, NgtRenderState, NgtSize, NgtState } from './types
2829
import { getLocalState, prepare } from './utils/instance';
2930
import { is } from './utils/is';
3031
import { safeDetectChanges } from './utils/safe-detect-changes';
32+
import { queueMicrotaskInInjectionContext } from './utils/timing';
3133
import { updateCamera } from './utils/update';
3234

3335
const privateKeys = [
@@ -57,7 +59,7 @@ export interface NgtPortalInputs {
5759
}
5860

5961
@Directive({ selector: '[ngtPortalBeforeRender]', standalone: true })
60-
export class NgtPortalBeforeRender implements OnInit {
62+
export class NgtPortalBeforeRender {
6163
readonly #portalStore = inject(NgtStore);
6264

6365
@Input() renderPriority = 1;
@@ -66,36 +68,29 @@ export class NgtPortalBeforeRender implements OnInit {
6668

6769
@Output() beforeRender = new EventEmitter<NgtRenderState>();
6870

69-
#subscription?: () => void;
70-
7171
constructor() {
72-
inject(DestroyRef).onDestroy(() => {
73-
this.#subscription?.();
74-
});
75-
}
76-
77-
ngOnInit() {
7872
let oldClear: boolean;
79-
this.#subscription = this.#portalStore.get('internal').subscribe(
80-
({ delta, frame }) => {
81-
this.beforeRender.emit({ ...this.#portalStore.get(), delta, frame });
82-
const { gl, scene, camera } = this.#portalStore.get();
83-
oldClear = gl.autoClear;
84-
if (this.renderPriority === 1) {
85-
// clear scene and render with default
86-
gl.autoClear = true;
87-
gl.render(this.parentScene, this.parentCamera);
88-
}
89-
// disable cleaning
90-
gl.autoClear = false;
91-
gl.clearDepth();
92-
gl.render(scene, camera);
93-
// restore
94-
gl.autoClear = oldClear;
95-
},
96-
this.renderPriority,
97-
this.#portalStore
98-
);
73+
queueMicrotaskInInjectionContext(() => {
74+
injectBeforeRender(
75+
({ delta, frame }) => {
76+
this.beforeRender.emit({ ...this.#portalStore.get(), delta, frame });
77+
const { gl, scene, camera } = this.#portalStore.get();
78+
oldClear = gl.autoClear;
79+
if (this.renderPriority === 1) {
80+
// clear scene and render with default
81+
gl.autoClear = true;
82+
gl.render(this.parentScene, this.parentCamera);
83+
}
84+
// disable cleaning
85+
gl.autoClear = false;
86+
gl.clearDepth();
87+
gl.render(scene, camera);
88+
// restore
89+
gl.autoClear = oldClear;
90+
},
91+
{ priority: this.renderPriority }
92+
);
93+
});
9994
}
10095
}
10196

@@ -133,7 +128,7 @@ export class NgtPortal extends NgtSignalStore<NgtPortalInputs> implements OnInit
133128
this.set({ container });
134129
}
135130

136-
@Input() set state(state: NgtPortalInputs['state']) {
131+
@Input() set portalState(state: NgtPortalInputs['state']) {
137132
this.set({ state });
138133
}
139134

libs/angular-three/src/lib/stores/signal.store.ts

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ const STORE_COMPUTED_KEY = '__ngt_store_computed__' as const;
1717
export class NgtSignalStore<TState extends object> {
1818
readonly #state: WritableSignal<TState>;
1919
readonly #computedCache = new Map();
20+
readonly state: Signal<TState>;
2021

2122
constructor(
2223
@Optional()
@@ -25,6 +26,7 @@ export class NgtSignalStore<TState extends object> {
2526
) {
2627
initialState ??= {};
2728
this.#state = createSignal(Object.assign(initialState, { __ngt_dummy_state__: Date.now() }) as TState);
29+
this.state = this.#state.asReadonly();
2830
}
2931

3032
select<
@@ -53,12 +55,12 @@ export class NgtSignalStore<TState extends object> {
5355
select<TKey extends keyof TState>(key: TKey, options?: CreateComputedOptions<TState[TKey]>): Signal<TState[TKey]>;
5456
select(options?: CreateComputedOptions<TState>): Signal<TState>;
5557
select(...keysAndOptions: any[]) {
56-
if (keysAndOptions.length === 0) return this.#state.asReadonly();
58+
if (keysAndOptions.length === 0) return this.state;
5759
if (keysAndOptions.length === 1 && typeof keysAndOptions[0] === 'object') {
5860
if (!this.#computedCache.has(STORE_COMPUTED_KEY)) {
5961
this.#computedCache.set(
6062
STORE_COMPUTED_KEY,
61-
computed(() => this.#state(), keysAndOptions as CreateComputedOptions<TState>)
63+
computed(this.state, keysAndOptions as CreateComputedOptions<TState>)
6264
);
6365
return this.#computedCache.get(STORE_COMPUTED_KEY)!;
6466
}
@@ -70,10 +72,7 @@ export class NgtSignalStore<TState extends object> {
7072
if (!this.#computedCache.has(joinedKeys)) {
7173
this.#computedCache.set(
7274
joinedKeys,
73-
computed(() => {
74-
const state = this.#state();
75-
return keys.reduce((value, key) => (value as NgtAnyRecord)[key], state);
76-
}, options)
75+
computed(() => keys.reduce((value, key) => (value as NgtAnyRecord)[key], this.state()), options)
7776
);
7877
}
7978

@@ -95,7 +94,7 @@ export class NgtSignalStore<TState extends object> {
9594
get<TKey extends keyof TState>(key: TKey): TState[TKey];
9695
get(): TState;
9796
get(...keys: string[]) {
98-
const state = untracked(this.#state);
97+
const state = untracked(this.state);
9998
if (keys.length === 0) return state;
10099
return keys.reduce((value, key) => (value as NgtAnyRecord)[key], state);
101100
}

libs/angular-three/src/lib/stores/store.ts

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -457,13 +457,7 @@ export class NgtStore extends NgtSignalStore<NgtState> {
457457
}
458458

459459
#invalidate() {
460-
const state = this.select();
461-
effect(
462-
() => {
463-
state().invalidate();
464-
},
465-
{ injector: this.#injector }
466-
);
460+
effect(() => void this.state().invalidate(), { injector: this.#injector });
467461
}
468462
}
469463

libs/postprocessing/effects/src/ssao/ssao.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,10 +122,8 @@ export class NgtpSSAO extends NgtSignalStore<NgtpSSAOState> {
122122

123123
readonly #effectComposerApi = inject(NGTP_EFFECT_COMPOSER_API);
124124

125-
readonly #state = this.select();
126-
127125
readonly effect = computed(() => {
128-
const state = this.#state();
126+
const state = this.state();
129127
const { camera, normalPass, downSamplingPass, resolutionScale } = this.#effectComposerApi();
130128

131129
if (normalPass === null && downSamplingPass === null) {

libs/soba/abstractions/src/text/text.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -216,8 +216,6 @@ export class NgtsText extends NgtSignalStore<NgtsTextState> {
216216

217217
readonly #store = inject(NgtStore);
218218

219-
readonly state = this.select();
220-
221219
constructor() {
222220
super({ fontSize: 1, sdfGlyphSize: 64, anchorX: 'center', anchorY: 'middle' });
223221
inject(DestroyRef).onDestroy(() => {
@@ -240,9 +238,8 @@ export class NgtsText extends NgtSignalStore<NgtsTextState> {
240238
}
241239

242240
#syncText() {
243-
const state = this.select();
244241
effect(() => {
245-
state();
242+
this.state();
246243
const invalidate = this.#store.get('invalidate');
247244
this.troikaText.sync(() => {
248245
invalidate();

libs/soba/staging/src/accumulative-shadows/accumulative-shadows.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ export class NgtsAccumulativeShadows extends NgtSignalStore<NgtsAccumulativeShad
286286

287287
#resetAndUpdate() {
288288
const trigger = computed(() => ({
289-
state: this.select()(),
289+
state: this.state(),
290290
objects: getLocalState(this.#store.get('scene')).objects(),
291291
mesh: this.meshRef.nativeElement,
292292
}));

libs/soba/staging/src/caustics/caustisc.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ export class NgtsCaustics extends NgtSignalStore<NgtsCausticsState> {
236236
sceneChildren: this.sceneRef.children()(),
237237
caustics: this.causticsRef.nativeElement,
238238
causticsChildren: this.causticsRef.children()(),
239-
state: this.select()(),
239+
state: this.state(),
240240
}));
241241

242242
effect(() => {

0 commit comments

Comments
 (0)