Skip to content

Commit 0d3245d

Browse files
Chau TranChau Tran
Chau Tran
authored and
Chau Tran
committed
feat(soba): migrate misc
1 parent 25d69b6 commit 0d3245d

File tree

10 files changed

+187
-39
lines changed

10 files changed

+187
-39
lines changed

libs/angular-three/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export * from './lib/stores/store';
1414
export * from './lib/three-types';
1515
export * from './lib/types';
1616
export * from './lib/utils/apply-props';
17+
export * from './lib/utils/assert-in-injection-context';
1718
export { createAttachFunction } from './lib/utils/attach';
1819
export * from './lib/utils/instance';
1920
export * from './lib/utils/is';

libs/angular-three/src/lib/di/before-render.ts

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,13 @@
1-
import { DestroyRef, Injector, assertInInjectionContext, inject, runInInjectionContext } from '@angular/core';
1+
import { DestroyRef, Injector, inject, runInInjectionContext } from '@angular/core';
22
import { NgtStore } from '../stores/store';
33
import { NgtBeforeRenderRecord } from '../types';
4+
import { assertInjectionContext } from '../utils/assert-in-injection-context';
45

56
export function injectBeforeRender(
67
cb: NgtBeforeRenderRecord['callback'],
7-
{ priority = 0, injector }: { priority?: number; injector?: Injector | null } = {}
8+
{ priority = 0, injector }: { priority?: number; injector?: Injector } = {}
89
) {
9-
assertInInjectionContext(injectBeforeRender);
10-
11-
if (!injector) {
12-
injector = inject(Injector);
13-
}
10+
injector = assertInjectionContext(injectBeforeRender, injector);
1411

1512
return runInInjectionContext(injector, () => {
1613
const store = inject(NgtStore);

libs/angular-three/src/lib/di/ref.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ import {
44
ElementRef,
55
Injector,
66
Signal,
7-
assertInInjectionContext,
87
computed,
98
inject,
109
runInInjectionContext,
1110
untracked,
1211
} from '@angular/core';
1312
import { NgtInstanceNode } from '../types';
13+
import { assertInjectionContext } from '../utils/assert-in-injection-context';
1414
import { getLocalState } from '../utils/instance';
1515
import { is } from '../utils/is';
1616
import { safeDetectChanges } from '../utils/safe-detect-changes';
@@ -25,11 +25,7 @@ export function injectNgtRef<TElement>(
2525
initial: ElementRef<TElement> | TElement = null!,
2626
injector?: Injector
2727
): NgtInjectedRef<TElement> {
28-
assertInInjectionContext(injectNgtRef);
29-
30-
if (!injector) {
31-
injector = inject(Injector);
32-
}
28+
injector = assertInjectionContext(injectNgtRef, injector);
3329

3430
return runInInjectionContext(injector, () => {
3531
const cdr = inject(ChangeDetectorRef);

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

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import {
22
ChangeDetectorRef,
33
Injector,
4-
assertInInjectionContext,
54
computed,
65
effect,
76
inject,
@@ -19,6 +18,7 @@ import type {
1918
NgtLoaderReturnType,
2019
NgtObjectMap,
2120
} from './types';
21+
import { assertInjectionContext } from './utils/assert-in-injection-context';
2222
import { makeObjectGraph } from './utils/make';
2323
import { safeDetectChanges } from './utils/safe-detect-changes';
2424

@@ -101,12 +101,7 @@ export function injectNgtLoader<
101101
injector?: Injector;
102102
} = {}
103103
): Signal<NgtLoaderResults<TUrl, NgtBranchingReturn<TReturn, GLTF, GLTF & NgtObjectMap>>> {
104-
assertInInjectionContext(injectNgtLoader);
105-
106-
if (!injector) {
107-
injector = inject(Injector);
108-
}
109-
104+
injector = assertInjectionContext(injectNgtLoader, injector);
110105
return runInInjectionContext(injector, () => {
111106
const cdr = inject(ChangeDetectorRef);
112107
const response = signal<NgtLoaderResults<TUrl, NgtBranchingReturn<TReturn, GLTF, GLTF & NgtObjectMap>>>(null!);
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { Injector, assertInInjectionContext, inject } from '@angular/core';
2+
3+
export function assertInjectionContext(fn: Function, injector?: Injector): Injector {
4+
try {
5+
if (!injector) {
6+
return inject(Injector);
7+
}
8+
return injector;
9+
} catch {
10+
!injector && assertInInjectionContext(fn);
11+
return null!;
12+
}
13+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import { DestroyRef, Injector, effect, inject, runInInjectionContext } from '@angular/core';
2+
import { assertInjectionContext, injectBeforeRender, injectNgtRef, type NgtInjectedRef } from 'angular-three';
3+
import * as THREE from 'three';
4+
5+
export function injectNgtsAnimations(
6+
animationsFactory: () => THREE.AnimationClip[],
7+
{
8+
ref,
9+
injector,
10+
}: {
11+
ref?: NgtInjectedRef<THREE.Object3D> | THREE.Object3D;
12+
injector?: Injector;
13+
}
14+
) {
15+
injector = assertInjectionContext(injectNgtsAnimations, injector);
16+
return runInInjectionContext(injector, () => {
17+
let actualRef = injectNgtRef<THREE.Object3D>();
18+
19+
if (ref) {
20+
if (ref instanceof THREE.Object3D) {
21+
actualRef.nativeElement = ref;
22+
} else {
23+
actualRef = ref;
24+
}
25+
}
26+
27+
const mixer = new THREE.AnimationMixer(null!);
28+
const actions = {} as Record<string, THREE.AnimationAction>;
29+
let cached = {} as Record<string, THREE.AnimationAction>;
30+
31+
const clips = [] as THREE.AnimationClip[];
32+
const names = [] as string[];
33+
34+
inject(DestroyRef).onDestroy(() => {
35+
// clear cached
36+
cached = {};
37+
// uncache actions
38+
Object.values(actions).forEach((action) => {
39+
mixer.uncacheAction(action as unknown as THREE.AnimationClip, actualRef.untracked);
40+
});
41+
// stop all actions
42+
mixer.stopAllAction();
43+
});
44+
45+
injectBeforeRender(({ delta }) => mixer.update(delta));
46+
47+
effect(() => {
48+
const actual = actualRef.nativeElement;
49+
const animations = animationsFactory();
50+
51+
for (let i = 0; i < animations.length; i++) {
52+
const clip = animations[i];
53+
54+
names.push(clip.name);
55+
clips.push(clip);
56+
57+
Object.defineProperty(actions, clip.name, {
58+
enumerable: true,
59+
get: () => {
60+
return cached[clip.name] || (cached[clip.name] = mixer.clipAction(clip, actual));
61+
},
62+
});
63+
64+
if (i === 0) {
65+
actions[clip.name].play();
66+
}
67+
}
68+
});
69+
70+
return { ref: actualRef, actions, mixer, names, clips };
71+
});
72+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { Directive, effect, inject } from '@angular/core';
2+
import { NgtStore } from 'angular-three';
3+
4+
@Directive({ selector: 'ngts-bake-shadows', standalone: true })
5+
export class NgtsBakeShadows {
6+
constructor() {
7+
const store = inject(NgtStore);
8+
effect((onCleanup) => {
9+
const gl = store.select('gl')();
10+
gl.shadowMap.autoUpdate = false;
11+
gl.shadowMap.needsUpdate = true;
12+
onCleanup(() => {
13+
gl.shadowMap.autoUpdate = gl.shadowMap.needsUpdate = true;
14+
});
15+
});
16+
}
17+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { ChangeDetectorRef, computed, effect, inject, Injector, runInInjectionContext } from '@angular/core';
2+
import { assertInjectionContext, injectBeforeRender, injectNgtRef, NgtStore, safeDetectChanges } from 'angular-three';
3+
import * as THREE from 'three';
4+
import { injectNgtsFBO } from '../fbo/fbo';
5+
6+
export interface NgtsDepthBufferParams {
7+
size: number;
8+
frames: number;
9+
}
10+
11+
export function injectNgtsDepthBuffer(
12+
paramsFactory: () => NgtsDepthBufferParams = () => ({ size: 256, frames: Infinity }),
13+
{ injector }: { injector?: Injector } = {}
14+
) {
15+
injector = assertInjectionContext(injectNgtsDepthBuffer, injector);
16+
return runInInjectionContext(injector, () => {
17+
const depthBufferRef = injectNgtRef<THREE.DepthTexture>();
18+
const store = inject(NgtStore);
19+
const cdr = inject(ChangeDetectorRef);
20+
21+
const fboParams = computed(() => {
22+
const params = paramsFactory();
23+
const size = store.select('size')();
24+
const dpr = store.select('viewport', 'dpr')();
25+
26+
const width = params.size || size.width * dpr;
27+
const height = params.size || size.height * dpr;
28+
const depthTexture = new THREE.DepthTexture(width, height);
29+
depthTexture.format = THREE.DepthFormat;
30+
depthTexture.type = THREE.UnsignedShortType;
31+
return { width, height, settings: { depthTexture } };
32+
});
33+
34+
const fboRef = injectNgtsFBO(fboParams);
35+
36+
let count = 0;
37+
injectBeforeRender(({ gl, scene, camera }) => {
38+
const params = paramsFactory();
39+
if ((params.frames === Infinity || count < params.frames) && fboRef.untracked) {
40+
gl.setRenderTarget(fboRef.untracked);
41+
gl.render(scene, camera);
42+
gl.setRenderTarget(null);
43+
count++;
44+
}
45+
});
46+
47+
effect(
48+
() => {
49+
const fbo = fboRef.nativeElement;
50+
if (fbo) {
51+
depthBufferRef.nativeElement = fbo.depthTexture;
52+
safeDetectChanges(cdr);
53+
}
54+
},
55+
{ allowSignalWrites: true }
56+
);
57+
58+
return depthBufferRef;
59+
});
60+
}

libs/soba/misc/src/fbo/fbo.ts

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import {
2-
assertInInjectionContext,
32
ChangeDetectorRef,
43
computed,
54
DestroyRef,
@@ -8,7 +7,7 @@ import {
87
Injector,
98
runInInjectionContext,
109
} from '@angular/core';
11-
import { injectNgtRef, NgtStore, safeDetectChanges } from 'angular-three';
10+
import { assertInjectionContext, injectNgtRef, NgtStore, safeDetectChanges } from 'angular-three';
1211
import * as THREE from 'three';
1312

1413
interface FBOSettings extends THREE.WebGLRenderTargetOptions {
@@ -25,12 +24,7 @@ export interface NgtsFBOParams {
2524
}
2625

2726
export function injectNgtsFBO(fboParams: () => NgtsFBOParams, { injector }: { injector?: Injector } = {}) {
28-
assertInInjectionContext(injectNgtsFBO);
29-
30-
if (!injector) {
31-
injector = inject(Injector);
32-
}
33-
27+
injector = assertInjectionContext(injectNgtsFBO, injector);
3428
return runInInjectionContext(injector, () => {
3529
const store = inject(NgtStore);
3630
const cdr = inject(ChangeDetectorRef);
@@ -41,33 +35,33 @@ export function injectNgtsFBO(fboParams: () => NgtsFBOParams, { injector }: { in
4135

4236
const trigger = computed(() => {
4337
const size = store.select('size');
44-
const viewport = store.select('viewport');
38+
const dpr = store.select('viewport', 'dpr');
4539
const { width, height, settings } = fboParams();
46-
return { size: size(), viewport: viewport(), width, height, settings };
40+
const _width = typeof width === 'number' ? width : size().width * dpr();
41+
const _height = typeof height === 'number' ? height : size().height * dpr();
42+
const _settings = (typeof width === 'number' ? settings : (width as FBOSettings)) || {};
43+
44+
return { width: _width, height: _height, settings: _settings };
4745
});
4846

4947
effect(
5048
() => {
51-
const { size, width, height, settings, viewport } = trigger();
52-
const _width = typeof width === 'number' ? width : size.width * viewport.dpr;
53-
const _height = typeof height === 'number' ? height : size.height * viewport.dpr;
54-
const _settings = (typeof width === 'number' ? settings : (width as FBOSettings)) || {};
55-
const { samples = 0, depth, ...targetSettings } = _settings;
56-
49+
const { width, height, settings } = trigger();
50+
const { samples = 0, depth, ...targetSettings } = settings;
5751
if (!targetRef.untracked) {
58-
const target = new THREE.WebGLRenderTarget(_width, _height, {
52+
const target = new THREE.WebGLRenderTarget(width, height, {
5953
minFilter: THREE.LinearFilter,
6054
magFilter: THREE.LinearFilter,
6155
type: THREE.HalfFloatType,
6256
...targetSettings,
6357
});
64-
if (depth) target.depthTexture = new THREE.DepthTexture(_width, _height, THREE.FloatType);
58+
if (depth) target.depthTexture = new THREE.DepthTexture(width, height, THREE.FloatType);
6559

6660
target.samples = samples;
6761
targetRef.nativeElement = target;
6862
}
6963

70-
targetRef.untracked.setSize(_width, _height);
64+
targetRef.untracked.setSize(width, height);
7165
if (samples) targetRef.nativeElement.samples = samples;
7266
safeDetectChanges(cdr);
7367
},

libs/soba/misc/src/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,4 @@
1+
export * from './animations/animations';
2+
export * from './bake-shadows/bake-shadows';
3+
export * from './depth-buffer/depth-buffer';
14
export * from './fbo/fbo';

0 commit comments

Comments
 (0)