Skip to content

Commit

Permalink
feat: add animations inject function
Browse files Browse the repository at this point in the history
  • Loading branch information
nartc committed Mar 8, 2023
1 parent fe1b809 commit 9375300
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 0 deletions.
1 change: 1 addition & 0 deletions libs/angular-three-soba/misc/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './lib/animations/animations';
export * from './lib/bake-shadows/bake-shadows';
export * from './lib/depth-buffer/depth-buffer';
export * from './lib/fbo/fbo';
68 changes: 68 additions & 0 deletions libs/angular-three-soba/misc/src/lib/animations/animations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { injectBeforeRender, injectNgtDestroy, injectNgtRef, is, NgtInjectedRef } from 'angular-three';
import { isObservable, Observable, Subscription } from 'rxjs';
import { AnimationMixer } from 'three';

type Api<T extends THREE.AnimationClip> = {
ref: NgtInjectedRef<THREE.Object3D>;
clips: THREE.AnimationClip[];
mixer: THREE.AnimationMixer;
names: T['name'][];
actions: { [key in T['name']]: THREE.AnimationAction | null };
};

export function injectNgtsAnimations<T extends THREE.AnimationClip>(
clips: T[],
object?: Observable<THREE.Object3D> | THREE.Object3D | NgtInjectedRef<THREE.Object3D>
): Api<T> {
let ref = injectNgtRef<THREE.Object3D>();

let sub: Subscription;

if (object) {
if (isObservable(object)) {
sub = object.subscribe((val) => {
ref.nativeElement = val;
});
} else if (is.ref(object)) {
ref = object;
} else {
ref.nativeElement = object;
}
}

const mixer = new AnimationMixer(ref.nativeElement);

let cached = {} as { [key in T['name']]: THREE.AnimationAction | null };
const actions = {} as { [key in T['name']]: THREE.AnimationAction | null };
const names = [] as T['name'][];

for (const clip of clips) {
names.push(clip.name);
Object.defineProperty(actions, clip.name, {
enumerable: true,
get: () => {
if (ref.nativeElement) {
const name = clip.name as keyof typeof cached;
return cached[name] || (cached[name] = mixer.clipAction(clip, ref.nativeElement));
}
},
});
}

const api = { ref, clips, actions, names, mixer };

injectNgtDestroy(() => {
if (sub) sub.unsubscribe();
cached = {} as { [key in T['name']]: THREE.AnimationAction | null };
Object.values(api.actions).forEach((action) => {
if (ref.nativeElement) {
mixer.uncacheAction(action as THREE.AnimationClip, ref.nativeElement);
}
});
mixer.stopAllAction();
});

injectBeforeRender(({ delta }) => mixer.update(delta));

return api;
}

0 comments on commit 9375300

Please sign in to comment.