Skip to content

Commit a8e2966

Browse files
committed
fix(soba): clean up environment; use effect more effectively (no pun)
1 parent 71d4c2c commit a8e2966

File tree

1 file changed

+74
-95
lines changed

1 file changed

+74
-95
lines changed

libs/soba/staging/src/lib/environment/environment.ts

Lines changed: 74 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
import { NgTemplateOutlet } from '@angular/common';
22
import {
3-
afterNextRender,
43
ChangeDetectionStrategy,
54
Component,
65
computed,
76
contentChild,
87
CUSTOM_ELEMENTS_SCHEMA,
8+
DestroyRef,
99
Directive,
10+
effect,
1011
EffectRef,
1112
ElementRef,
1213
inject,
1314
Injector,
1415
input,
1516
output,
16-
signal,
1717
TemplateRef,
1818
viewChild,
1919
} from '@angular/core';
@@ -29,7 +29,6 @@ import {
2929
pick,
3030
prepare,
3131
} from 'angular-three';
32-
import { injectAutoEffect } from 'ngxtension/auto-effect';
3332
import { mergeInputs } from 'ngxtension/inject-inputs';
3433
import { CubeCamera, Euler, HalfFloatType, Scene, Texture, WebGLCubeRenderTarget } from 'three';
3534
import { GroundProjectedEnv } from 'three-stdlib';
@@ -106,46 +105,42 @@ export class NgtsEnvironmentMap {
106105
options = input(defaultBackground, { transform: mergeInputs(defaultBackground) });
107106
envSet = output<void>();
108107

109-
private autoEffect = injectAutoEffect();
110-
private store = injectStore();
111-
private defaultScene = this.store.select('scene');
112-
113-
private envConfig = computed(() => {
114-
const {
115-
background = false,
116-
scene,
117-
blur,
118-
backgroundBlurriness,
119-
backgroundIntensity,
120-
backgroundRotation,
121-
environmentIntensity,
122-
environmentRotation,
123-
} = this.options();
108+
constructor() {
109+
const store = injectStore();
110+
const defaultScene = store.select('scene');
124111

125-
return {
126-
background,
127-
scene,
128-
blur,
129-
backgroundBlurriness,
130-
backgroundIntensity,
131-
backgroundRotation,
132-
environmentIntensity,
133-
environmentRotation,
134-
};
135-
});
112+
const _map = pick(this.options, 'map');
113+
const _envConfig = computed(() => {
114+
const {
115+
background = false,
116+
scene,
117+
blur,
118+
backgroundBlurriness,
119+
backgroundIntensity,
120+
backgroundRotation,
121+
environmentIntensity,
122+
environmentRotation,
123+
} = this.options();
136124

137-
private map = pick(this.options, 'map');
125+
return {
126+
background,
127+
scene,
128+
blur,
129+
backgroundBlurriness,
130+
backgroundIntensity,
131+
backgroundRotation,
132+
environmentIntensity,
133+
environmentRotation,
134+
};
135+
});
138136

139-
constructor() {
140-
afterNextRender(() => {
141-
this.autoEffect(() => {
142-
const map = this.map();
143-
if (!map) return;
144-
const { background = false, scene, ...config } = this.envConfig();
145-
const cleanup = setEnvProps(background, scene, this.defaultScene(), map, config);
146-
this.envSet.emit();
147-
return () => cleanup();
148-
});
137+
effect((onCleanup) => {
138+
const map = _map();
139+
if (!map) return;
140+
const { background = false, scene, ...config } = _envConfig();
141+
const cleanup = setEnvProps(background, scene, defaultScene(), map, config);
142+
this.envSet.emit();
143+
onCleanup(() => cleanup());
149144
});
150145
}
151146
}
@@ -155,10 +150,8 @@ export class NgtsEnvironmentCube {
155150
options = input(defaultBackground, { transform: mergeInputs(defaultBackground) });
156151
envSet = output<void>();
157152

158-
private autoEffect = injectAutoEffect();
159153
private store = injectStore();
160154
private defaultScene = this.store.select('scene');
161-
private injector = inject(Injector);
162155

163156
private envConfig = computed(() => {
164157
const {
@@ -185,17 +178,15 @@ export class NgtsEnvironmentCube {
185178
});
186179

187180
constructor() {
188-
afterNextRender(() => {
189-
const _texture = injectEnvironment(this.options, { injector: this.injector });
190-
191-
this.autoEffect(() => {
192-
const texture = _texture();
193-
if (!texture) return;
194-
const { background = false, scene, ...config } = this.envConfig();
195-
const cleanup = setEnvProps(background, scene, this.defaultScene(), texture, config);
196-
this.envSet.emit();
197-
return () => cleanup();
198-
});
181+
const _texture = injectEnvironment(this.options);
182+
183+
effect((onCleanup) => {
184+
const texture = _texture();
185+
if (!texture) return;
186+
const { background = false, scene, ...config } = this.envConfig();
187+
const cleanup = setEnvProps(background, scene, this.defaultScene(), texture, config);
188+
this.envSet.emit();
189+
onCleanup(() => cleanup());
199190
});
200191
}
201192
}
@@ -238,21 +229,21 @@ export class NgtsEnvironmentPortal {
238229
content = input.required<TemplateRef<unknown>>();
239230
envSet = output<void>();
240231

241-
private autoEffect = injectAutoEffect();
232+
private injector = inject(Injector);
242233
private store = injectStore();
243234
private defaultScene = this.store.select('scene');
244235
private gl = this.store.select('gl');
245236

246-
cameraRef = viewChild<ElementRef<CubeCamera>>('cubeCamera');
237+
private cameraRef = viewChild<ElementRef<CubeCamera>>('cubeCamera');
247238

248-
map = pick(this.options, 'map');
249-
files = pick(this.options, 'files');
250-
preset = pick(this.options, 'preset');
239+
protected map = pick(this.options, 'map');
240+
protected files = pick(this.options, 'files');
241+
protected preset = pick(this.options, 'preset');
251242
private extensions = pick(this.options, 'extensions');
252243
private path = pick(this.options, 'path');
253244

254-
envMapOptions = computed(() => ({ background: true, map: this.map(), extensions: this.extensions() }));
255-
envCubeOptions = computed(() => ({
245+
protected envMapOptions = computed(() => ({ background: true, map: this.map(), extensions: this.extensions() }));
246+
protected envCubeOptions = computed(() => ({
256247
background: true,
257248
files: this.files(),
258249
preset: this.preset(),
@@ -269,22 +260,20 @@ export class NgtsEnvironmentPortal {
269260
return fbo;
270261
});
271262

272-
cameraArgs = computed(() => [this.near(), this.far(), this.fbo()]);
273-
274-
virtualScene = prepare(new Scene());
263+
protected cameraArgs = computed(() => [this.near(), this.far(), this.fbo()]);
264+
protected virtualScene = prepare(new Scene());
275265

276266
private setEnvEffectRef?: EffectRef;
277267

278268
constructor() {
279269
extend({ CubeCamera });
280270

281-
afterNextRender(() => {
282-
this.autoEffect(() => {
283-
const [files, preset, map] = [this.files(), this.preset(), this.map()];
284-
// NOTE: when there's none of this, we don't render cube or map so we need to setEnv here
285-
if (!!files || !!preset || !!map) return;
286-
return this.setPortalEnv();
287-
});
271+
effect((onCleanup) => {
272+
const [files, preset, map] = [this.files(), this.preset(), this.map()];
273+
// NOTE: when there's none of this, we don't render cube or map so we need to setEnv here
274+
if (!!files || !!preset || !!map) return;
275+
const cleanup = this.setPortalEnv();
276+
onCleanup(() => cleanup?.());
288277
});
289278

290279
let count = 1;
@@ -298,16 +287,21 @@ export class NgtsEnvironmentPortal {
298287
}
299288
}
300289
});
290+
291+
inject(DestroyRef).onDestroy(() => {
292+
if (this.setEnvEffectRef) this.setEnvEffectRef.destroy();
293+
});
301294
}
302295

303296
// NOTE: we use onEnvSet here to ensure that EnvironmentCube or EnvironmentMap sets the env before the portal
304297
onEnvSet() {
305298
if (this.setEnvEffectRef) this.setEnvEffectRef.destroy();
306-
this.setEnvEffectRef = this.autoEffect(
307-
() => {
308-
return this.setPortalEnv();
299+
this.setEnvEffectRef = effect(
300+
(onCleanup) => {
301+
const cleanup = this.setPortalEnv();
302+
onCleanup(() => cleanup?.());
309303
},
310-
{ manualCleanup: true },
304+
{ manualCleanup: true, injector: this.injector },
311305
);
312306
}
313307

@@ -361,35 +355,20 @@ export class NgtsEnvironmentGround {
361355
options = input({} as NgtsEnvironmentOptions);
362356
envSet = output<void>();
363357

364-
args = signal<[Texture | null]>([null]);
365-
366-
height = computed(() => (this.options().ground as any)?.height);
367-
radius = computed(() => (this.options().ground as any)?.radius);
368-
scale = computed(() => (this.options().ground as any)?.scale ?? 1000);
358+
private defaultTexture = injectEnvironment(this.options);
369359

370-
envMapOptions = computed(() => {
360+
protected height = computed(() => (this.options().ground as any)?.height);
361+
protected radius = computed(() => (this.options().ground as any)?.radius);
362+
protected scale = computed(() => (this.options().ground as any)?.scale ?? 1000);
363+
protected args = computed(() => [this.options().map || this.defaultTexture()]);
364+
protected envMapOptions = computed(() => {
371365
const { map: _, ...options } = this.options();
372366
const [map] = this.args();
373367
return Object.assign(options, { map }) as NgtsEnvironmentOptions;
374368
});
375369

376370
constructor() {
377371
extend({ GroundProjectedEnv });
378-
379-
const injector = inject(Injector);
380-
const autoEffect = injectAutoEffect();
381-
382-
afterNextRender(() => {
383-
const defaultTexture = injectEnvironment(this.options, { injector });
384-
const texture = computed(() => this.options().map || defaultTexture());
385-
386-
autoEffect(
387-
() => {
388-
this.args.set([texture()]);
389-
},
390-
{ allowSignalWrites: true },
391-
);
392-
});
393372
}
394373
}
395374

0 commit comments

Comments
 (0)