Skip to content

Commit 6fd43ae

Browse files
committed
bounds
1 parent 812d8e4 commit 6fd43ae

File tree

5 files changed

+791
-1
lines changed

5 files changed

+791
-1
lines changed

libs/core/src/index.ts

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

0 commit comments

Comments
 (0)