Skip to content

Commit 1c69a34

Browse files
Chau TranChau Tran
Chau Tran
authored and
Chau Tran
committed
feat(soba): migrate bounds
1 parent 3f178f0 commit 1c69a34

File tree

4 files changed

+466
-1
lines changed

4 files changed

+466
-1
lines changed

libs/soba/loaders/src/gltf-loader/gltf-loader.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ injectNgtsGLTFLoader['preload'] = <TUrl extends string | string[] | Record<strin
6262
useDraco?: boolean | string;
6363
useMeshOpt?: boolean;
6464
extensions?: (loader: GLTFLoader) => void;
65-
}
65+
} = {}
6666
) => {
6767
injectNgtLoader.preload(() => GLTFLoader, path, _extensions(useDraco, useMeshOpt, extensions));
6868
};
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
import { NgIf } from '@angular/common';
2+
import { Component, computed, CUSTOM_ELEMENTS_SCHEMA, inject, Input, NO_ERRORS_SCHEMA, signal } from '@angular/core';
3+
import { Meta, moduleMetadata } from '@storybook/angular';
4+
import { NgtAnyRecord, NgtArgs, NgtThreeEvent } from 'angular-three';
5+
import { NgtsOrbitControls } from 'angular-three-soba/controls';
6+
import { injectNgtsGLTFLoader } from 'angular-three-soba/loaders';
7+
import { NGTS_BOUNDS_API, NgtsBounds, NgtsContactShadows } from 'angular-three-soba/staging';
8+
import { makeStoryObject, StorybookSetup } from '../setup-canvas';
9+
10+
injectNgtsGLTFLoader.preload(() => 'soba/bounds-assets.glb');
11+
12+
@Component({
13+
selector: 'Model',
14+
standalone: true,
15+
template: `
16+
<ngt-mesh *ngIf="model() as model" ngtCompound [material]="model.material" [geometry]="model.geometry">
17+
<ngt-value [rawValue]="'red'" attach="material.emissive" />
18+
<ngt-value [rawValue]="1" attach="material.roughness" />
19+
</ngt-mesh>
20+
`,
21+
imports: [NgtArgs, NgIf],
22+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
23+
})
24+
class Model {
25+
readonly #models = injectNgtsGLTFLoader(() => 'soba/bounds-assets.glb');
26+
protected readonly model = computed(() => {
27+
if (!this.#name() || !this.#models()) return null;
28+
return this.#models().nodes[this.#name()];
29+
});
30+
31+
readonly #name = signal('');
32+
@Input({ required: true }) set name(name: string) {
33+
this.#name.set(name);
34+
}
35+
}
36+
37+
@Component({
38+
selector: 'Models',
39+
standalone: true,
40+
template: `
41+
<ngt-group (click)="onClick($event)" (pointermissed)="onPointerMissed($event)">
42+
<Model name="Curly" [position]="[1, -11, -20]" [rotation]="[2, 0, -0]" />
43+
<Model name="DNA" [position]="[20, 0, -17]" [rotation]="[1, 1, -2]" />
44+
<Model name="Headphones" [position]="[20, 2, 4]" [rotation]="[1, 0, -1]" />
45+
<Model name="Notebook" [position]="[-21, -15, -13]" [rotation]="[2, 0, 1]" />
46+
<Model name="Rocket003" [position]="[18, 15, -25]" [rotation]="[1, 1, 0]" />
47+
<Model name="Roundcube001" [position]="[-25, -4, 5]" [rotation]="[1, 0, 0]" [scale]="0.5" />
48+
<Model name="Table" [position]="[1, -4, -28]" [rotation]="[1, 0, -1]" [scale]="0.5" />
49+
<Model name="VR_Headset" [position]="[7, -15, 28]" [rotation]="[1, 0, -1]" [scale]="5" />
50+
<Model name="Zeppelin" [position]="[-20, 10, 10]" [rotation]="[3, -1, 3]" [scale]="0.005" />
51+
</ngt-group>
52+
`,
53+
imports: [Model],
54+
schemas: [NO_ERRORS_SCHEMA],
55+
})
56+
class Models {
57+
readonly #boundsApi = inject(NGTS_BOUNDS_API);
58+
59+
onClick(event: NgtThreeEvent<MouseEvent>) {
60+
event.stopPropagation();
61+
event.delta <= 2 && this.#boundsApi.refresh(event.object).fit();
62+
}
63+
64+
onPointerMissed(event: NgtThreeEvent<PointerEvent>) {
65+
(event as NgtAnyRecord)['button'] === 0 && this.#boundsApi.refresh().fit();
66+
}
67+
}
68+
69+
@Component({
70+
standalone: true,
71+
template: `
72+
<ngt-color *args="['pink']" attach="background" />
73+
74+
<ngt-spot-light [position]="-100" [intensity]="0.2" [angle]="0.3" [penumbra]="1" />
75+
<ngt-hemisphere-light color="white" groundColor="#ff0f00" [position]="[-7, 25, 13]" [intensity]="1" />
76+
77+
<ngts-bounds>
78+
<Models />
79+
</ngts-bounds>
80+
81+
<ngts-contact-shadows
82+
[position]="[0, -35, 0]"
83+
[opacity]="1"
84+
[width]="200"
85+
[height]="200"
86+
[blur]="1"
87+
[far]="50"
88+
/>
89+
90+
<ngts-orbit-controls [makeDefault]="true" [minPolarAngle]="0" [maxPolarAngle]="Math.PI * 1.75" />
91+
`,
92+
imports: [NgtsBounds, NgtArgs, NgtsOrbitControls, NgtsContactShadows, Models],
93+
schemas: [NO_ERRORS_SCHEMA],
94+
})
95+
class DefaultBoundsStory {
96+
readonly Math = Math;
97+
}
98+
99+
export default {
100+
title: 'Staging/Bounds',
101+
decorators: [moduleMetadata({ imports: [StorybookSetup] })],
102+
} as Meta;
103+
104+
export const Default = makeStoryObject(DefaultBoundsStory, {
105+
canvasOptions: {
106+
camera: { fov: 50, position: [0, -10, 100] },
107+
controls: false,
108+
lights: false,
109+
compoundPrefixes: ['Model'],
110+
},
111+
});

0 commit comments

Comments
 (0)