Skip to content

Commit f38281f

Browse files
Chau TranChau Tran
Chau Tran
authored and
Chau Tran
committed
feat(soba): migrate center
1 parent 98e3789 commit f38281f

File tree

7 files changed

+202
-3
lines changed

7 files changed

+202
-3
lines changed

libs/soba/abstractions/src/billboard/billboard.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { CUSTOM_ELEMENTS_SCHEMA, Component, Input } from '@angular/core';
2-
import { NgtGroup, NgtSignalStore, extend, injectBeforeRender, injectNgtRef } from 'angular-three';
2+
import { NgtSignalStore, extend, injectBeforeRender, injectNgtRef, type NgtGroup } from 'angular-three';
33
import { Group } from 'three';
44

55
extend({ Group });

libs/soba/project.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,9 @@
4646
"libs/soba/abstractions/**/*.ts",
4747
"libs/soba/abstractions/**/*.html",
4848
"libs/soba/controls/**/*.ts",
49-
"libs/soba/controls/**/*.html"
49+
"libs/soba/controls/**/*.html",
50+
"libs/soba/staging/**/*.ts",
51+
"libs/soba/staging/**/*.html"
5052
]
5153
}
5254
},

libs/soba/staging/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# angular-three-soba/staging
2+
3+
Secondary entry point of `angular-three-soba`. It can be used by importing from `angular-three-soba/staging`.

libs/soba/staging/ng-package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"lib": {
3+
"entryFile": "src/index.ts"
4+
}
5+
}
Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
import {
2+
Component,
3+
computed,
4+
CUSTOM_ELEMENTS_SCHEMA,
5+
effect,
6+
EventEmitter,
7+
inject,
8+
Injector,
9+
Input,
10+
OnInit,
11+
Output,
12+
} from '@angular/core';
13+
import { extend, injectNgtRef, NgtSignalStore, type NgtGroup } from 'angular-three';
14+
import { Box3, Group, Sphere, Vector3 } from 'three';
15+
16+
export type NgtsCenterState = {
17+
top?: boolean;
18+
right?: boolean;
19+
bottom?: boolean;
20+
left?: boolean;
21+
front?: boolean;
22+
back?: boolean;
23+
/** Disable all axes */
24+
disable?: boolean;
25+
/** Disable x-axis centering */
26+
disableX?: boolean;
27+
/** Disable y-axis centering */
28+
disableY?: boolean;
29+
/** Disable z-axis centering */
30+
disableZ?: boolean;
31+
/** See https://threejs.org/docs/index.html?q=box3#api/en/math/Box3.setFromObject */
32+
precise: boolean;
33+
};
34+
35+
extend({ Group });
36+
37+
declare global {
38+
interface HTMLElementTagNameMap {
39+
'ngts-center': NgtsCenterState & NgtGroup;
40+
}
41+
}
42+
43+
@Component({
44+
selector: 'ngts-center',
45+
standalone: true,
46+
template: `
47+
<ngt-group ngtCompound [ref]="centerRef">
48+
<ngt-group [ref]="outerRef">
49+
<ngt-group [ref]="innerRef">
50+
<ng-content />
51+
</ngt-group>
52+
</ngt-group>
53+
</ngt-group>
54+
`,
55+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
56+
})
57+
export class NgtsCenter extends NgtSignalStore<NgtsCenterState> implements OnInit {
58+
@Input() centerRef = injectNgtRef<Group>();
59+
60+
readonly outerRef = injectNgtRef<Group>();
61+
readonly innerRef = injectNgtRef<Group>();
62+
63+
@Input() set top(top: boolean) {
64+
this.set({ top });
65+
}
66+
67+
@Input() set right(right: boolean) {
68+
this.set({ right });
69+
}
70+
71+
@Input() set bottom(bottom: boolean) {
72+
this.set({ bottom });
73+
}
74+
75+
@Input() set left(left: boolean) {
76+
this.set({ left });
77+
}
78+
79+
@Input() set front(front: boolean) {
80+
this.set({ front });
81+
}
82+
83+
@Input() set back(back: boolean) {
84+
this.set({ back });
85+
}
86+
87+
@Input() set disableX(disableX: boolean) {
88+
this.set({ disableX });
89+
}
90+
91+
@Input() set disableY(disableY: boolean) {
92+
this.set({ disableY });
93+
}
94+
95+
@Input() set disableZ(disableZ: boolean) {
96+
this.set({ disableZ });
97+
}
98+
99+
@Input() set disable(disable: boolean) {
100+
this.set({ disable });
101+
}
102+
103+
@Input() set precise(precise: boolean) {
104+
this.set({ precise });
105+
}
106+
107+
@Output() centered = new EventEmitter<{
108+
/** The next parent above <Center> */
109+
parent: THREE.Object3D;
110+
/** The outmost container group of the <Center> component */
111+
container: THREE.Object3D;
112+
width: number;
113+
height: number;
114+
depth: number;
115+
boundingBox: THREE.Box3;
116+
boundingSphere: THREE.Sphere;
117+
center: THREE.Vector3;
118+
verticalAlignment: number;
119+
horizontalAlignment: number;
120+
depthAlignment: number;
121+
}>();
122+
123+
readonly #injector = inject(Injector);
124+
125+
constructor() {
126+
super({ precise: true });
127+
}
128+
129+
ngOnInit(): void {
130+
this.#setPosition();
131+
}
132+
133+
#setPosition() {
134+
const trigger = computed(() => {
135+
const center = this.centerRef.nativeElement;
136+
const outer = this.outerRef.nativeElement;
137+
const inner = this.innerRef.nativeElement;
138+
const innerChildren = this.innerRef.children();
139+
return { center, outer, inner, innerChildren: innerChildren() };
140+
});
141+
142+
effect(
143+
() => {
144+
const { center: centerGroup, outer, inner } = trigger();
145+
const { precise, top, left, front, disable, disableX, disableY, disableZ, back, bottom, right } =
146+
this.get();
147+
outer.matrixWorld.identity();
148+
const box3 = new Box3().setFromObject(inner, precise);
149+
const center = new Vector3();
150+
const sphere = new Sphere();
151+
const width = box3.max.x - box3.min.x;
152+
const height = box3.max.y - box3.min.y;
153+
const depth = box3.max.z - box3.min.z;
154+
155+
box3.getCenter(center);
156+
box3.getBoundingSphere(sphere);
157+
158+
const vAlign = top ? height / 2 : bottom ? -height / 2 : 0;
159+
const hAlign = left ? -width / 2 : right ? width / 2 : 0;
160+
const dAlign = front ? depth / 2 : back ? -depth / 2 : 0;
161+
162+
outer.position.set(
163+
disable || disableX ? 0 : -center.x + hAlign,
164+
disable || disableY ? 0 : -center.y + vAlign,
165+
disable || disableZ ? 0 : -center.z + dAlign
166+
);
167+
168+
if (this.centered.observed) {
169+
this.centered.emit({
170+
parent: centerGroup.parent!,
171+
container: centerGroup,
172+
width,
173+
height,
174+
depth,
175+
boundingBox: box3,
176+
boundingSphere: sphere,
177+
center: center,
178+
verticalAlignment: vAlign,
179+
horizontalAlignment: hAlign,
180+
depthAlignment: dAlign,
181+
});
182+
}
183+
},
184+
{ injector: this.#injector }
185+
);
186+
}
187+
}

libs/soba/staging/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './center/center';

tsconfig.base.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222
"angular-three-postprocessing": ["libs/postprocessing/src/index.ts"],
2323
"angular-three-soba": ["libs/soba/src/index.ts"],
2424
"angular-three-soba/abstractions": ["libs/soba/abstractions/src/index.ts"],
25-
"angular-three-soba/controls": ["libs/soba/controls/src/index.ts"]
25+
"angular-three-soba/controls": ["libs/soba/controls/src/index.ts"],
26+
"angular-three-soba/staging": ["libs/soba/staging/src/index.ts"]
2627
}
2728
},
2829
"exclude": ["node_modules", "tmp"]

0 commit comments

Comments
 (0)