@hatiolab/figure-model 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,360 @@
1
+ /** 저작에 쓰는 프리미티브. mesh 계열과 extrude 계열로 갈린다. */
2
+ export declare const PRIMITIVE_KINDS: readonly ["cube", "wall", "cylinder", "sphere", "rect", "polygon"];
3
+ export type PrimitiveKind = (typeof PRIMITIVE_KINDS)[number];
4
+ /** extrude 계열은 2D 단면이 필요하다. */
5
+ export declare const EXTRUDE_PRIMITIVES: readonly PrimitiveKind[];
6
+ /** mesh 계열은 치수만으로 선다. 분할 수를 갖는다. */
7
+ export declare const MESH_PRIMITIVES: readonly PrimitiveKind[];
8
+ /** 분할 수를 갖는 프리미티브 — 곡면이 있는 것만. */
9
+ export declare const SEGMENTED_PRIMITIVES: readonly PrimitiveKind[];
10
+ /**
11
+ * 재질 슬롯. extrude 계열의 재질 인덱스가 둘로 정해져 있다.
12
+ * `threed/real-object-extrude.ts:105-111` — 0 = cap(fillStyle), 1 = side(strokeStyle)
13
+ */
14
+ export declare const MATERIAL_SLOTS: readonly ["cap", "side"];
15
+ export type MaterialSlot = (typeof MATERIAL_SLOTS)[number];
16
+ /** 재질 프리셋. `threed/material-3d.ts:9` 의 preset 과 같은 집합. */
17
+ export declare const MATERIAL_PRESETS: readonly ["default", "metal", "glass", "plastic", "wood", "ceramic", "rubber"];
18
+ export type MaterialPreset = (typeof MATERIAL_PRESETS)[number];
19
+ /**
20
+ * 크기 반응 규칙 — 인스턴스 크기가 바뀔 때 부품이 어떻게 변하는가.
21
+ *
22
+ * scale 비례 확대. 탱크 몸체 같은 단일 덩어리
23
+ * fixed 크기는 그대로, 자리만 따라간다. 모터·계기·노즐
24
+ * stretch 한 축만 늘어난다. 프레임·벨트·레일
25
+ * repeat 개수가 늘어난다. 롤러·선반 단 ← 새 geometry 가 생기지 않는다
26
+ */
27
+ export declare const SIZING_RULES: readonly ["scale", "fixed", "stretch", "repeat"];
28
+ export type SizingRule = (typeof SIZING_RULES)[number];
29
+ /** 디테일 등급. 부품 수 상한을 정한다. */
30
+ export declare const DETAIL_LEVELS: readonly ["S", "M", "L"];
31
+ export type DetailLevel = (typeof DETAIL_LEVELS)[number];
32
+ /** 등급별 부품 수 상한. */
33
+ export declare const PART_LIMIT: Record<DetailLevel, number>;
34
+ /** 애니메이션 종류. `animation/animations/` 에 있는 것과 같은 집합. */
35
+ export declare const ANIMATION_KINDS: readonly ["fade", "heartbeat", "moving", "outline", "rotation", "vibration", "waypoint"];
36
+ export type AnimationKind = (typeof ANIMATION_KINDS)[number];
37
+ /** 피봇이 없으면 뜻이 달라지는 애니메이션. 회전은 중심이 어디냐로 결과가 완전히 바뀐다. */
38
+ export declare const PIVOT_REQUIRED: readonly AnimationKind[];
39
+ export declare const AXES: readonly ["x", "y", "z"];
40
+ export type Axis = (typeof AXES)[number];
41
+ /** 텍스트를 언제 보이나. 표현 수단(sprite·overlay)은 런타임이 고른다. */
42
+ export declare const LABEL_WHENS: readonly ["always", "zoomed", "selected", "abnormal"];
43
+ export type LabelWhen = (typeof LABEL_WHENS)[number];
44
+ export interface Vec3 {
45
+ x: number;
46
+ y: number;
47
+ z: number;
48
+ }
49
+ export interface Point2 {
50
+ x: number;
51
+ y: number;
52
+ }
53
+ /**
54
+ * 부품의 자리와 크기.
55
+ *
56
+ * **`x`·`y`·`z` 는 부품의 최소 모서리다** — 중심이 아니다. `x` 는 왼쪽, `y` 는 위,
57
+ * `z` 는 바닥이며, 부품은 거기서 `width`·`height`·`depth` 만큼 뻗는다. 기준은
58
+ * `FigureBlueprint.base` 상자의 최소 모서리(0,0,0)다.
59
+ *
60
+ * 축의 뜻은 things-scene 의 2D·3D 규약과 같다 — `x` 오른쪽, `y` 아래(2D 캔버스와 같은
61
+ * 방향), `z` 위. `height` 는 평면상의 세로이고 **`depth` 가 높이**다.
62
+ *
63
+ * 중심이 아니라 최소 모서리로 두는 이유는 격자 스냅 때문이다. 저작이 그리드에
64
+ * 맞추는 것은 모서리이고, 중심 기준이면 홀수 크기 부품이 격자에서 반 칸씩 밀린다.
65
+ */
66
+ export interface PartTransform extends Vec3 {
67
+ width: number;
68
+ height: number;
69
+ depth: number;
70
+ /** 축별 회전(도). 없으면 회전 없음. */
71
+ rotation?: Partial<Vec3>;
72
+ }
73
+ /**
74
+ * 부품 재질.
75
+ *
76
+ * 색은 **팔레트 토큰**으로 둔다(`token`). 값을 굽으면 StyleKit 을 바꿔도 따라오지
77
+ * 않는다. 토큰 해석은 그리는 시점에 한다.
78
+ */
79
+ /**
80
+ * 팔레트 밖 표면의 종류.
81
+ *
82
+ * 둘 다 **이름으로 가리키는 자산**이다. 같은 이름이면 같은 텍스처이고, 따라서 재질도
83
+ * 나눠 쓴다 — `MaterialBank` 가 텍스처를 spec 서명에 넣기 때문이다.
84
+ */
85
+ export declare const SURFACE_KINDS: readonly ["gradient", "pattern"];
86
+ export type SurfaceKind = (typeof SURFACE_KINDS)[number];
87
+ /**
88
+ * 팔레트 밖의 표면 — **미감의 예외다.**
89
+ *
90
+ * 라벨 판이나 표시창처럼 단색으로는 안 되는 자리에 쓴다.
91
+ *
92
+ * ## 재질은 나눠 쓴다
93
+ *
94
+ * 이름으로 가리키는 자산이므로 같은 `ref` 를 쓰는 부품끼리 텍스처와 재질을 나눠 쓴다.
95
+ * **인스턴스가 늘어도 재질이 늘지 않는다.**
96
+ *
97
+ * 처음에 이것을 `unsharedSurface` 라 부르고 「재질을 나눠 쓸 수 없다」고 셌는데
98
+ * 틀렸다. things-scene 의 컴포넌트는 텍스처를 **자기 bounds 와 상태로부터** 만들어
99
+ * 인스턴스마다 다르지만, 이 형식의 것은 이름으로 가리키는 고정 자산이다.
100
+ *
101
+ * ## 그래도 한도를 둔다
102
+ *
103
+ * 이유가 재질 공유가 아니라 둘이다.
104
+ *
105
+ * 미감 단색 규칙의 예외다. 늘어나면 로우폴리가 무너진다
106
+ * 메모리 텍스처마다 GPU 메모리와 샘플러를 쓴다
107
+ */
108
+ export interface PartSurface {
109
+ kind: SurfaceKind;
110
+ /** 무엇을 쓰나. 텍스처 이름·이미지 키. 해석은 그리는 쪽이 한다. */
111
+ ref: string;
112
+ }
113
+ export interface PartMaterial {
114
+ /** 팔레트 토큰. 예: 'palette.primary' */
115
+ token?: string;
116
+ preset?: MaterialPreset;
117
+ flatShading?: boolean;
118
+ transparent?: boolean;
119
+ /**
120
+ * 팔레트 밖의 표면. **미감의 예외다.**
121
+ *
122
+ * 없는 것이 정상이다. 재질은 나눠 쓰지만 텍스처 메모리를 쓰고 단색 규칙을 벗어나므로
123
+ * 셈에 들어간다.
124
+ */
125
+ surface?: PartSurface;
126
+ }
127
+ /** `sizing === 'repeat'` 일 때 어느 축으로 얼마 간격으로 늘어나나. */
128
+ export interface RepeatSpec {
129
+ axis: Axis;
130
+ /** 부품 사이 간격. 비례 그리드 단위로 두면 늘려도 정돈된다. */
131
+ gap: number;
132
+ }
133
+ /**
134
+ * 애니메이션 포인트.
135
+ *
136
+ * `pivot` 을 적지 않으면 회전이 부품 자기 중심으로 돈다 —
137
+ * `threed/real-object-extrude.ts:98` 의 `geometry.center()` 때문이다. 교반 축이
138
+ * 몸체 가운데를 돌아야 하면 피봇을 명시해야 한다.
139
+ */
140
+ export interface AnimationPoint {
141
+ kind: AnimationKind;
142
+ axis?: Axis;
143
+ /** 부품 기준 로컬 좌표. `PIVOT_REQUIRED` 종류에는 필수. */
144
+ pivot?: Vec3;
145
+ }
146
+ /** 텍스트 표현 자리. 무엇을·언제만 정하고 수단은 런타임이 고른다. */
147
+ export interface LabelSpec {
148
+ name: string;
149
+ /** 태그의 어느 값을 보이나. */
150
+ source: string;
151
+ when: LabelWhen;
152
+ }
153
+ /** extrude 계열의 2D 단면. */
154
+ export interface PartShape {
155
+ /** `polygon` 에 필요. 3 점 이상. */
156
+ path?: Point2[];
157
+ /** 코너 라운드. `rect` · `polygon` 공통. */
158
+ round?: number;
159
+ }
160
+ export interface FigurePart {
161
+ /**
162
+ * 부품 이름. **저장되는 식별자다** — 바인딩·애니메이션·슬롯이 이 이름을 가리킨다.
163
+ * 바꾸면 인스턴스의 바인딩이 조용히 끊긴다.
164
+ */
165
+ name: string;
166
+ primitive: PrimitiveKind;
167
+ transform: PartTransform;
168
+ /** mesh 계열 곡면의 분할 수. 로우폴리는 8·12·16. */
169
+ segments?: number;
170
+ /** extrude 계열의 단면. */
171
+ shape?: PartShape;
172
+ material: PartMaterial;
173
+ /** 상태 색이 연동될 재질 슬롯. 없으면 상태를 표현하지 않는다. */
174
+ slot?: MaterialSlot;
175
+ sizing?: SizingRule;
176
+ repeat?: RepeatSpec;
177
+ animation?: AnimationPoint;
178
+ label?: LabelSpec;
179
+ }
180
+ /** 저작 결과 — 편집 가능한 정본. */
181
+ export interface FigureSource {
182
+ /** 컴포넌트 타입 이름. **저장되는 식별자다.** */
183
+ type: string;
184
+ /** 기준 치수. 배치 크기는 이 비율에서 산출된다. */
185
+ base: {
186
+ width: number;
187
+ height: number;
188
+ depth: number;
189
+ };
190
+ anchor?: Vec3;
191
+ detailLevel?: DetailLevel;
192
+ /** StyleKit 참조. 팔레트·분할 수·그리드·등급을 한 벌로 받는다. */
193
+ styleKit?: string;
194
+ parts: FigurePart[];
195
+ }
196
+ /** 청사진 스키마 버전. 형식이 바뀌면 올린다. */
197
+ export declare const BLUEPRINT_VERSION = 1;
198
+ export interface BlueprintMember {
199
+ name: string;
200
+ primitive: PrimitiveKind;
201
+ /** GeometryBank 키. 실체가 아니라 참조다. */
202
+ geometryKey: string;
203
+ transform: PartTransform;
204
+ /**
205
+ * 곡면의 분할 수. `SEGMENTED_PRIMITIVES` 인 부품에만 있다.
206
+ *
207
+ * `geometryKey` 안에도 들어 있지만 키는 문자열이라 다시 파싱해야 한다. 그리는 쪽이
208
+ * 2D 톱뷰를 3D 와 **같은 분할 수**로 근사하려면 이 값이 필요하므로 따로 낸다.
209
+ */
210
+ segments?: number;
211
+ sizing: SizingRule;
212
+ repeat?: RepeatSpec;
213
+ shape?: PartShape;
214
+ /** 이 부품의 삼각형 수 추정. */
215
+ triangles: number;
216
+ }
217
+ /**
218
+ * 재질별로 병합된 묶음. 2D · 3D 공통.
219
+ *
220
+ * `members` 가 병합 대상이다 — 3D 는 geometry 를 합치고, 2D 는 윤곽을 한 path 로
221
+ * 합쳐 한 번에 채운다.
222
+ */
223
+ export interface BlueprintGroup {
224
+ /** MaterialBank 키. */
225
+ materialKey: string;
226
+ material: PartMaterial;
227
+ slot?: MaterialSlot;
228
+ /** 애니메이션 포인트에 걸린 묶음. 걸리면 부품 하나만 든다. */
229
+ animated: boolean;
230
+ members: BlueprintMember[];
231
+ }
232
+ export interface BlueprintPoint {
233
+ /** 어느 부품인가. `FigurePart.name`. */
234
+ name: string;
235
+ kind: AnimationKind;
236
+ axis?: Axis;
237
+ pivot?: Vec3;
238
+ }
239
+ export interface BlueprintLabel extends LabelSpec {
240
+ /** 어느 부품에 붙나. `FigurePart.name`. */
241
+ at: string;
242
+ }
243
+ /** 형식은 맞으나 정책을 넘은 것. 컴파일을 막지 않는다. */
244
+ export interface Violation {
245
+ code: ViolationCode;
246
+ message: string;
247
+ /** 넘은 값과 한도. */
248
+ actual?: number;
249
+ limit?: number;
250
+ }
251
+ /**
252
+ * 오류 코드 전부. **여기 없는 코드는 낼 수 없다** — `FigureError.code` 가 이 목록의
253
+ * 값으로 좁혀져 있어, 코드를 새로 쓰면 타입 검사가 막는다.
254
+ *
255
+ * 목록을 두는 이유는 소비처 때문이다. 오류를 사용자에게 보이는 쪽은 코드마다 문구와
256
+ * 처리를 정해야 하는데, 코드가 조용히 늘면 그 대응이 빠진다. 뜻은
257
+ * `docs/validation.md` 에 있고, 문서와 이 목록이 어긋나면 시험이 깨진다.
258
+ */
259
+ export declare const ERROR_CODES: readonly ["not-object", "not-finite", "not-positive", "not-integer", "not-boolean", "not-allowed", "missing-type", "missing-base", "missing-parts", "bad-style-kit", "missing-name", "duplicate-name", "missing-transform", "missing-depth", "too-few-segments", "missing-shape-path", "bad-shape-point", "missing-material", "material-unresolvable", "missing-repeat", "missing-axis", "missing-pivot", "missing-surface-ref", "missing-label-name", "missing-label-source"];
260
+ export type ErrorCode = (typeof ERROR_CODES)[number];
261
+ /**
262
+ * 위반 코드 전부. 위반은 컴파일을 막지 않는다 — 저작 화면이 알려 주는 데 쓴다.
263
+ * 뜻과 한도는 `docs/validation.md` 에 있다.
264
+ */
265
+ export declare const VIOLATION_CODES: readonly ["segments-off-preset", "segments-ignored", "repeat-ignored", "detail-level-missing", "too-many-parts", "too-many-animation-points", "too-many-material-groups", "too-many-transparent", "too-many-surface-textures", "too-many-always-labels"];
266
+ export type ViolationCode = (typeof VIOLATION_CODES)[number];
267
+ /** 형식·정합성 오류. 이것이 있으면 컴파일할 수 없다. */
268
+ export interface FigureError {
269
+ code: ErrorCode;
270
+ /** 어디서 났나. 예: `parts[2].transform.width` */
271
+ path: string;
272
+ message: string;
273
+ }
274
+ export interface FigureBlueprint {
275
+ version: number;
276
+ type: string;
277
+ base: {
278
+ width: number;
279
+ height: number;
280
+ depth: number;
281
+ };
282
+ anchor?: Vec3;
283
+ /**
284
+ * 디테일 등급. **부품 수 한도가 여기서 나온다** — 소비처가 「이 Figure 가 예산 안에
285
+ * 있나」를 판단하려면 등급을 알아야 한다. 정본이 정하지 않았으면 없다.
286
+ */
287
+ detailLevel?: DetailLevel;
288
+ budget: {
289
+ triangles: number;
290
+ /** 묶음 수 = 재질·슬롯 조합 수 + 애니메이션 포인트 수. **재는 것은 이것이다.** */
291
+ groups: number;
292
+ };
293
+ groups: BlueprintGroup[];
294
+ points: BlueprintPoint[];
295
+ labels: BlueprintLabel[];
296
+ violations: Violation[];
297
+ }
298
+ /**
299
+ * 보드 모델에 저장되는 인스턴스.
300
+ *
301
+ * **여느 컴포넌트와 같은 모양이다.** 청사진도 정본도 보드에 들어가지 않는다 —
302
+ * `type` 이 청사진을 찾는 키이고, 청사진은 실행 시점에 바깥에서 받아 이미 알고 있다.
303
+ *
304
+ * ```json
305
+ * { "type": "MIXER", "left": 1200, "top": 800, "width": 300, "height": 300,
306
+ * "zPos": 0, "tag": "EQ-003" }
307
+ * ```
308
+ *
309
+ * 이렇게 두는 이유가 셋이다.
310
+ *
311
+ * 1. 보드가 부풀지 않는다. 자산 500 개의 부품 정본을 보드에 넣으면 거대해진다.
312
+ * 2. Figure 를 고치면 배치된 것에 반영된다. 보드에 사본이 없으므로.
313
+ * 3. **보드는 이것이 저작된 자산인지 코드로 만든 컴포넌트인지 알 필요가 없다.**
314
+ * `Component.register` 로 타입이 등록되므로 여느 타입처럼 다룬다.
315
+ *
316
+ * `mappings` · `eventHandlers` · `data` 는 씬 공통 상태 키라 여기 적지 않는다.
317
+ * 그것들도 여느 컴포넌트와 같은 자리에 같은 모양으로 들어간다.
318
+ */
319
+ export interface FigureInstanceModel {
320
+ /** 청사진을 찾는 키. 저작한 Figure 의 `type`. */
321
+ type: string;
322
+ left: number;
323
+ top: number;
324
+ width: number;
325
+ height: number;
326
+ zPos?: number;
327
+ rotation?: Partial<Vec3>;
328
+ /** 데이터 바인딩 식별자. 값은 인스턴스가 갖는다. */
329
+ tag?: string;
330
+ }
331
+ /**
332
+ * 성능을 담보하는 한도.
333
+ *
334
+ * 로우폴리에서 병목은 삼각형이 아니라 **묶음 수**다. 자산 500 개 × 부품 8 개면
335
+ * 4000 draw call 이지만, 재질 3 종으로 병합하면 1500 이다.
336
+ *
337
+ * 자산당 묶음 수 = 재질·슬롯 조합 수 + 애니메이션 포인트 수
338
+ */
339
+ export declare const LIMITS: {
340
+ /** 재질·슬롯 조합 수. */
341
+ readonly materialGroups: 3;
342
+ /** 애니메이션 포인트 수. 프레임마다 매트릭스를 갱신한다. */
343
+ readonly animationPoints: 2;
344
+ /** 투명 재질. 정렬 비용이 크다. */
345
+ readonly transparentMaterials: 1;
346
+ /**
347
+ * 팔레트 밖 표면(무늬·그라디언트)의 종류 수.
348
+ *
349
+ * 1 인 이유 — 라벨 판이나 표시창처럼 정말 그것이어야 하는 자리가 한 군데쯤은 있을 수
350
+ * 있다. 둘을 넘으면 단색 규칙과 싸우는 것이고, 텍스처마다 GPU 메모리를 쓴다.
351
+ *
352
+ * **재질 공유 때문이 아니다** — 이름으로 가리키는 자산이라 재질은 나눠 쓴다.
353
+ */
354
+ readonly surfaceTextures: 1;
355
+ /** 분할 수 하한 — 이보다 낮으면 형상이 아니다. */
356
+ readonly minSegments: 3;
357
+ };
358
+ /** 로우폴리 분할 수 프리셋. 자유 입력보다 이 중 하나를 권한다. */
359
+ export declare const SEGMENT_PRESETS: readonly number[];
360
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,162 @@
1
+ /*
2
+ * Copyright © HatioLab Inc. All rights reserved.
3
+ *
4
+ * Figure 계약 — 저작 결과(정본)와 보드가 소비하는 산출물(청사진)의 형식.
5
+ *
6
+ * **이 모듈은 의존이 없다.** things-scene 의 Component·THREE 를 쓰지 않는 순수
7
+ * 데이터 정의이므로, 서버·클라이언트·저작도구가 모두 같은 형식을 본다. 필요하면
8
+ * 별도 패키지로 떼어낼 수 있다.
9
+ *
10
+ * 두 형식을 가른다.
11
+ *
12
+ * FigureSource 저작 결과. 편집 가능한 정본. DB 에 저장된다.
13
+ * FigureBlueprint 보드가 세우는 형태. 정본에서 파생되는 캐시. 저장하지 않는다.
14
+ *
15
+ * 청사진은 2D 와 3D 를 한 구조로 다룬다 — 재질별로 묶고(`groups`), 3D 는 그
16
+ * 묶음의 geometry 를 합쳐 draw call 을 줄이고, 2D 는 윤곽을 합쳐 `fill()` 호출을
17
+ * 줄인다. 병목이 양쪽 다 「묶음 수」이므로 같은 병합이 함께 값을 한다.
18
+ *
19
+ * 설계 문서: things-scene/docs/plans/figure-blueprint.md
20
+ */
21
+ /** 저작에 쓰는 프리미티브. mesh 계열과 extrude 계열로 갈린다. */
22
+ export const PRIMITIVE_KINDS = ['cube', 'wall', 'cylinder', 'sphere', 'rect', 'polygon'];
23
+ /** extrude 계열은 2D 단면이 필요하다. */
24
+ export const EXTRUDE_PRIMITIVES = ['rect', 'polygon'];
25
+ /** mesh 계열은 치수만으로 선다. 분할 수를 갖는다. */
26
+ export const MESH_PRIMITIVES = ['cube', 'wall', 'cylinder', 'sphere'];
27
+ /** 분할 수를 갖는 프리미티브 — 곡면이 있는 것만. */
28
+ export const SEGMENTED_PRIMITIVES = ['cylinder', 'sphere'];
29
+ /**
30
+ * 재질 슬롯. extrude 계열의 재질 인덱스가 둘로 정해져 있다.
31
+ * `threed/real-object-extrude.ts:105-111` — 0 = cap(fillStyle), 1 = side(strokeStyle)
32
+ */
33
+ export const MATERIAL_SLOTS = ['cap', 'side'];
34
+ /** 재질 프리셋. `threed/material-3d.ts:9` 의 preset 과 같은 집합. */
35
+ export const MATERIAL_PRESETS = ['default', 'metal', 'glass', 'plastic', 'wood', 'ceramic', 'rubber'];
36
+ /**
37
+ * 크기 반응 규칙 — 인스턴스 크기가 바뀔 때 부품이 어떻게 변하는가.
38
+ *
39
+ * scale 비례 확대. 탱크 몸체 같은 단일 덩어리
40
+ * fixed 크기는 그대로, 자리만 따라간다. 모터·계기·노즐
41
+ * stretch 한 축만 늘어난다. 프레임·벨트·레일
42
+ * repeat 개수가 늘어난다. 롤러·선반 단 ← 새 geometry 가 생기지 않는다
43
+ */
44
+ export const SIZING_RULES = ['scale', 'fixed', 'stretch', 'repeat'];
45
+ /** 디테일 등급. 부품 수 상한을 정한다. */
46
+ export const DETAIL_LEVELS = ['S', 'M', 'L'];
47
+ /** 등급별 부품 수 상한. */
48
+ export const PART_LIMIT = { S: 3, M: 8, L: 20 };
49
+ /** 애니메이션 종류. `animation/animations/` 에 있는 것과 같은 집합. */
50
+ export const ANIMATION_KINDS = ['fade', 'heartbeat', 'moving', 'outline', 'rotation', 'vibration', 'waypoint'];
51
+ /** 피봇이 없으면 뜻이 달라지는 애니메이션. 회전은 중심이 어디냐로 결과가 완전히 바뀐다. */
52
+ export const PIVOT_REQUIRED = ['rotation'];
53
+ export const AXES = ['x', 'y', 'z'];
54
+ /** 텍스트를 언제 보이나. 표현 수단(sprite·overlay)은 런타임이 고른다. */
55
+ export const LABEL_WHENS = ['always', 'zoomed', 'selected', 'abnormal'];
56
+ /**
57
+ * 부품 재질.
58
+ *
59
+ * 색은 **팔레트 토큰**으로 둔다(`token`). 값을 굽으면 StyleKit 을 바꿔도 따라오지
60
+ * 않는다. 토큰 해석은 그리는 시점에 한다.
61
+ */
62
+ /**
63
+ * 팔레트 밖 표면의 종류.
64
+ *
65
+ * 둘 다 **이름으로 가리키는 자산**이다. 같은 이름이면 같은 텍스처이고, 따라서 재질도
66
+ * 나눠 쓴다 — `MaterialBank` 가 텍스처를 spec 서명에 넣기 때문이다.
67
+ */
68
+ export const SURFACE_KINDS = ['gradient', 'pattern'];
69
+ // ─── 청사진 ────────────────────────────────────────────────────────────────
70
+ /** 청사진 스키마 버전. 형식이 바뀌면 올린다. */
71
+ export const BLUEPRINT_VERSION = 1;
72
+ /**
73
+ * 오류 코드 전부. **여기 없는 코드는 낼 수 없다** — `FigureError.code` 가 이 목록의
74
+ * 값으로 좁혀져 있어, 코드를 새로 쓰면 타입 검사가 막는다.
75
+ *
76
+ * 목록을 두는 이유는 소비처 때문이다. 오류를 사용자에게 보이는 쪽은 코드마다 문구와
77
+ * 처리를 정해야 하는데, 코드가 조용히 늘면 그 대응이 빠진다. 뜻은
78
+ * `docs/validation.md` 에 있고, 문서와 이 목록이 어긋나면 시험이 깨진다.
79
+ */
80
+ export const ERROR_CODES = [
81
+ // 형태
82
+ 'not-object',
83
+ 'not-finite',
84
+ 'not-positive',
85
+ 'not-integer',
86
+ 'not-boolean',
87
+ 'not-allowed',
88
+ // 정본 뼈대
89
+ 'missing-type',
90
+ 'missing-base',
91
+ 'missing-parts',
92
+ 'bad-style-kit',
93
+ // 부품
94
+ 'missing-name',
95
+ 'duplicate-name',
96
+ 'missing-transform',
97
+ 'missing-depth',
98
+ 'too-few-segments',
99
+ // 단면
100
+ 'missing-shape-path',
101
+ 'bad-shape-point',
102
+ // 재질
103
+ 'missing-material',
104
+ 'material-unresolvable',
105
+ // 크기 반응
106
+ 'missing-repeat',
107
+ // 애니메이션
108
+ 'missing-axis',
109
+ 'missing-pivot',
110
+ // 예외 표면
111
+ 'missing-surface-ref',
112
+ // 라벨
113
+ 'missing-label-name',
114
+ 'missing-label-source'
115
+ ];
116
+ /**
117
+ * 위반 코드 전부. 위반은 컴파일을 막지 않는다 — 저작 화면이 알려 주는 데 쓴다.
118
+ * 뜻과 한도는 `docs/validation.md` 에 있다.
119
+ */
120
+ export const VIOLATION_CODES = [
121
+ 'segments-off-preset',
122
+ 'segments-ignored',
123
+ 'repeat-ignored',
124
+ 'detail-level-missing',
125
+ 'too-many-parts',
126
+ 'too-many-animation-points',
127
+ 'too-many-material-groups',
128
+ 'too-many-transparent',
129
+ 'too-many-surface-textures',
130
+ 'too-many-always-labels'
131
+ ];
132
+ // ─── 정책 한도 ─────────────────────────────────────────────────────────────
133
+ /**
134
+ * 성능을 담보하는 한도.
135
+ *
136
+ * 로우폴리에서 병목은 삼각형이 아니라 **묶음 수**다. 자산 500 개 × 부품 8 개면
137
+ * 4000 draw call 이지만, 재질 3 종으로 병합하면 1500 이다.
138
+ *
139
+ * 자산당 묶음 수 = 재질·슬롯 조합 수 + 애니메이션 포인트 수
140
+ */
141
+ export const LIMITS = {
142
+ /** 재질·슬롯 조합 수. */
143
+ materialGroups: 3,
144
+ /** 애니메이션 포인트 수. 프레임마다 매트릭스를 갱신한다. */
145
+ animationPoints: 2,
146
+ /** 투명 재질. 정렬 비용이 크다. */
147
+ transparentMaterials: 1,
148
+ /**
149
+ * 팔레트 밖 표면(무늬·그라디언트)의 종류 수.
150
+ *
151
+ * 1 인 이유 — 라벨 판이나 표시창처럼 정말 그것이어야 하는 자리가 한 군데쯤은 있을 수
152
+ * 있다. 둘을 넘으면 단색 규칙과 싸우는 것이고, 텍스처마다 GPU 메모리를 쓴다.
153
+ *
154
+ * **재질 공유 때문이 아니다** — 이름으로 가리키는 자산이라 재질은 나눠 쓴다.
155
+ */
156
+ surfaceTextures: 1,
157
+ /** 분할 수 하한 — 이보다 낮으면 형상이 아니다. */
158
+ minSegments: 3
159
+ };
160
+ /** 로우폴리 분할 수 프리셋. 자유 입력보다 이 중 하나를 권한다. */
161
+ export const SEGMENT_PRESETS = [8, 12, 16];
162
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import { type FigureError, type Violation } from './types.ts';
2
+ export interface ValidateResult {
3
+ errors: FigureError[];
4
+ violations: Violation[];
5
+ }
6
+ /**
7
+ * 정본을 검증한다.
8
+ *
9
+ * 바깥에서 온 데이터(DB · API · 파일)를 받으므로 `unknown` 을 받는다.
10
+ * `errors` 가 비어 있으면 `source` 는 `FigureSource` 로 다룰 수 있다.
11
+ */
12
+ export declare function validate(source: unknown): ValidateResult;
13
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"AAqBA,OAAO,EAgBL,KAAK,WAAW,EAGhB,KAAK,SAAS,EAEf,MAAM,YAAY,CAAA;AAMnB,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,WAAW,EAAE,CAAA;IACrB,UAAU,EAAE,SAAS,EAAE,CAAA;CACxB;AA4SD;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,OAAO,GAAG,cAAc,CAwCxD"}