@things-factory/figure-ui 10.1.65 → 10.1.67
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.
- package/client/graphql/index.ts +0 -45
- package/client/modeller/figure-history-panel.ts +6 -145
- package/client/modeller/figure-v3-capability.ts +2 -2
- package/client/modeller/figure-v3-clips.ts +2 -2
- package/client/modeller/figure-v3-controls.ts +2 -2
- package/client/modeller/figure-v3-first-save.ts +1 -1
- package/client/modeller/figure-v3-links.ts +6 -6
- package/client/modeller/figure-v3-material.ts +11 -11
- package/client/modeller/figure-v3-parts.ts +7 -10
- package/client/modeller/figure-v3-preview.ts +3 -3
- package/client/modeller/figure-v3-properties.ts +5 -6
- package/client/modeller/figure-v3-verdict.ts +9 -10
- package/client/modeller/figure-view.ts +2 -3
- package/client/modeller/modeller-route.ts +2 -3
- package/client/modeller/scene-budget.ts +0 -14
- package/client/modeller/side-panel-styles.ts +5 -5
- package/client/modeller/v3-align.ts +16 -6
- package/client/modeller/v3-canvas.ts +12 -12
- package/client/modeller/v3-clips.ts +1 -1
- package/client/modeller/v3-controls.ts +1 -1
- package/client/modeller/v3-editor.ts +21 -21
- package/client/modeller/v3-fields.ts +1 -1
- package/client/modeller/v3-figure-facts.ts +1 -1
- package/client/modeller/v3-first-save.ts +3 -4
- package/client/modeller/v3-gizmo.ts +5 -5
- package/client/modeller/v3-help.ts +1 -1
- package/client/modeller/v3-joint-fan.ts +4 -5
- package/client/modeller/v3-keys.ts +1 -1
- package/client/modeller/v3-links.ts +9 -12
- package/client/modeller/v3-maturity.ts +22 -26
- package/client/modeller/v3-refusals.ts +17 -0
- package/client/modeller/v3-renderer.ts +1 -1
- package/client/modeller/v3-stage-model.ts +2 -2
- package/client/modeller/v3-thumbnail.ts +1 -3
- package/client/pages/figure-v3-modeller-page.ts +8 -11
- package/client/types.ts +2 -31
- package/dist-client/graphql/index.js +0 -45
- package/dist-client/graphql/index.js.map +1 -1
- package/dist-client/modeller/figure-history-panel.d.ts +4 -37
- package/dist-client/modeller/figure-history-panel.js +8 -154
- package/dist-client/modeller/figure-history-panel.js.map +1 -1
- package/dist-client/modeller/figure-v3-capability.d.ts +1 -1
- package/dist-client/modeller/figure-v3-capability.js +1 -1
- package/dist-client/modeller/figure-v3-capability.js.map +1 -1
- package/dist-client/modeller/figure-v3-clips.d.ts +2 -2
- package/dist-client/modeller/figure-v3-clips.js +2 -2
- package/dist-client/modeller/figure-v3-clips.js.map +1 -1
- package/dist-client/modeller/figure-v3-controls.d.ts +1 -1
- package/dist-client/modeller/figure-v3-controls.js +2 -2
- package/dist-client/modeller/figure-v3-controls.js.map +1 -1
- package/dist-client/modeller/figure-v3-first-save.d.ts +1 -1
- package/dist-client/modeller/figure-v3-first-save.js +1 -1
- package/dist-client/modeller/figure-v3-first-save.js.map +1 -1
- package/dist-client/modeller/figure-v3-links.d.ts +5 -5
- package/dist-client/modeller/figure-v3-links.js +6 -6
- package/dist-client/modeller/figure-v3-links.js.map +1 -1
- package/dist-client/modeller/figure-v3-material.d.ts +6 -6
- package/dist-client/modeller/figure-v3-material.js +11 -11
- package/dist-client/modeller/figure-v3-material.js.map +1 -1
- package/dist-client/modeller/figure-v3-parts.d.ts +6 -8
- package/dist-client/modeller/figure-v3-parts.js +1 -1
- package/dist-client/modeller/figure-v3-parts.js.map +1 -1
- package/dist-client/modeller/figure-v3-preview.js.map +1 -1
- package/dist-client/modeller/figure-v3-properties.d.ts +4 -5
- package/dist-client/modeller/figure-v3-properties.js +5 -6
- package/dist-client/modeller/figure-v3-properties.js.map +1 -1
- package/dist-client/modeller/figure-v3-verdict.d.ts +2 -2
- package/dist-client/modeller/figure-v3-verdict.js +9 -10
- package/dist-client/modeller/figure-v3-verdict.js.map +1 -1
- package/dist-client/modeller/figure-view.d.ts +2 -3
- package/dist-client/modeller/figure-view.js.map +1 -1
- package/dist-client/modeller/modeller-route.d.ts +2 -3
- package/dist-client/modeller/modeller-route.js +2 -3
- package/dist-client/modeller/modeller-route.js.map +1 -1
- package/dist-client/modeller/scene-budget.d.ts +0 -11
- package/dist-client/modeller/scene-budget.js +0 -12
- package/dist-client/modeller/scene-budget.js.map +1 -1
- package/dist-client/modeller/side-panel-styles.d.ts +2 -2
- package/dist-client/modeller/side-panel-styles.js +5 -5
- package/dist-client/modeller/side-panel-styles.js.map +1 -1
- package/dist-client/modeller/v3-align.d.ts +9 -5
- package/dist-client/modeller/v3-align.js +13 -3
- package/dist-client/modeller/v3-align.js.map +1 -1
- package/dist-client/modeller/v3-canvas.d.ts +4 -4
- package/dist-client/modeller/v3-canvas.js +9 -9
- package/dist-client/modeller/v3-canvas.js.map +1 -1
- package/dist-client/modeller/v3-clips.js.map +1 -1
- package/dist-client/modeller/v3-controls.js.map +1 -1
- package/dist-client/modeller/v3-editor.d.ts +13 -13
- package/dist-client/modeller/v3-editor.js +19 -18
- package/dist-client/modeller/v3-editor.js.map +1 -1
- package/dist-client/modeller/v3-fields.js.map +1 -1
- package/dist-client/modeller/v3-figure-facts.d.ts +1 -1
- package/dist-client/modeller/v3-figure-facts.js +1 -1
- package/dist-client/modeller/v3-figure-facts.js.map +1 -1
- package/dist-client/modeller/v3-first-save.js +3 -4
- package/dist-client/modeller/v3-first-save.js.map +1 -1
- package/dist-client/modeller/v3-gizmo.d.ts +5 -5
- package/dist-client/modeller/v3-gizmo.js +1 -1
- package/dist-client/modeller/v3-gizmo.js.map +1 -1
- package/dist-client/modeller/v3-help.d.ts +1 -1
- package/dist-client/modeller/v3-help.js +1 -1
- package/dist-client/modeller/v3-help.js.map +1 -1
- package/dist-client/modeller/v3-joint-fan.js +4 -5
- package/dist-client/modeller/v3-joint-fan.js.map +1 -1
- package/dist-client/modeller/v3-keys.js.map +1 -1
- package/dist-client/modeller/v3-links.d.ts +5 -7
- package/dist-client/modeller/v3-links.js +6 -8
- package/dist-client/modeller/v3-links.js.map +1 -1
- package/dist-client/modeller/v3-maturity.d.ts +7 -7
- package/dist-client/modeller/v3-maturity.js +20 -24
- package/dist-client/modeller/v3-maturity.js.map +1 -1
- package/dist-client/modeller/v3-refusals.d.ts +6 -0
- package/dist-client/modeller/v3-refusals.js +18 -0
- package/dist-client/modeller/v3-refusals.js.map +1 -1
- package/dist-client/modeller/v3-renderer.js +1 -1
- package/dist-client/modeller/v3-renderer.js.map +1 -1
- package/dist-client/modeller/v3-stage-model.js.map +1 -1
- package/dist-client/modeller/v3-thumbnail.js +1 -3
- package/dist-client/modeller/v3-thumbnail.js.map +1 -1
- package/dist-client/pages/figure-v3-modeller-page.d.ts +4 -5
- package/dist-client/pages/figure-v3-modeller-page.js +8 -11
- package/dist-client/pages/figure-v3-modeller-page.js.map +1 -1
- package/dist-client/route.d.ts +1 -1
- package/dist-client/tsconfig.fui.tsbuildinfo +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-client/types.d.ts +2 -29
- package/dist-client/types.js +3 -0
- package/dist-client/types.js.map +1 -1
- package/docs/v3-product-cutover.md +14 -24
- package/package.json +5 -5
- package/test/browser/modeller-page.js +6 -7
- package/test/browser/modeller.check.mjs +9 -16
- package/test/fixtures/joint-column.json +1138 -0
- package/test/fixtures/joint-roller.json +872 -0
- package/test/fixtures/robot-arm-6dof.json +2776 -0
- package/test/i18n-prefix-guard.test.ts +0 -31
- package/test/modeller-route.test.ts +2 -3
- package/test/v3-align.test.ts +9 -4
- package/test/v3-clips.test.ts +1 -1
- package/test/v3-controls.test.ts +1 -1
- package/test/v3-fields.test.ts +4 -4
- package/test/v3-first-save.test.ts +1 -1
- package/test/v3-gizmo.test.ts +5 -5
- package/test/v3-joint-fan.test.ts +12 -42
- package/test/v3-keys.test.ts +1 -1
- package/test/v3-layout.test.ts +4 -5
- package/test/v3-links.test.ts +3 -3
- package/test/v3-material.test.ts +3 -3
- package/test/v3-maturity.test.ts +8 -9
- package/test/v3-parts-wiring.test.ts +3 -3
- package/test/v3-preview.test.ts +1 -1
- package/test/v3-product-write.test.ts +1 -1
- package/test/v3-properties.test.ts +3 -3
- package/test/v3-refusals.test.ts +12 -0
- package/test/v3-release-panel.test.ts +5 -5
- package/test/v3-scene-canvas.test.ts +2 -2
- package/test/v3-theme.test.ts +2 -2
- package/test/v3-verdict.test.ts +2 -2
- package/test/v3-view.test.ts +2 -2
- package/translations/en.json +2 -143
- package/translations/ja.json +2 -143
- package/translations/ko.json +2 -143
- package/translations/ms.json +2 -143
- package/translations/zh.json +2 -143
- package/client/modeller/figure-source.ts +0 -437
- package/client/modeller/part-edits.ts +0 -312
- package/dist-client/modeller/figure-source.d.ts +0 -238
- package/dist-client/modeller/figure-source.js +0 -193
- package/dist-client/modeller/figure-source.js.map +0 -1
- package/dist-client/modeller/part-edits.d.ts +0 -89
- package/dist-client/modeller/part-edits.js +0 -270
- package/dist-client/modeller/part-edits.js.map +0 -1
- package/test/expect.ts +0 -57
- package/test/figure-source.test.ts +0 -511
- package/test/part-edits.test.ts +0 -350
package/dist-client/types.d.ts
CHANGED
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* 화면이 다루는 모양.
|
|
3
|
-
*
|
|
4
|
-
* 정본 형식(`FigureSource`)의 타입은 **여기서 다시 정의하지 않는다** —
|
|
5
|
-
* `@hatiolab/figure-model` 에서 가져온다. 두 벌이면 갈리고, 갈리면 화면이 서버가
|
|
6
|
-
* 거절할 것을 만들어 낸다.
|
|
2
|
+
* 화면이 다루는 모양. 도형 자산의 타입은 `@hatiolab/figure-model` 이 정한다 — 여기서 다시 적지 않는다.
|
|
7
3
|
*/
|
|
8
|
-
export type { FigureSource, FigureBlueprint, FigurePart, ErrorCode, ViolationCode } from '@hatiolab/figure-model';
|
|
9
4
|
/** 서버가 돌려주는 Figure 한 벌. `source` 는 저작면에서만 받는다. */
|
|
10
5
|
export interface Figure {
|
|
11
6
|
id: string;
|
|
@@ -29,9 +24,7 @@ export interface Figure {
|
|
|
29
24
|
id: string;
|
|
30
25
|
name: string;
|
|
31
26
|
};
|
|
32
|
-
/**
|
|
33
|
-
format?: 'v2' | 'v3' | null;
|
|
34
|
-
/** `FigureSource` JSON 문자열. 목록 질의에는 실려 오지 않는다. */
|
|
27
|
+
/** 도형 자산 JSON 문자열. 목록 질의에는 실려 오지 않는다. */
|
|
35
28
|
source?: string;
|
|
36
29
|
properties?: string;
|
|
37
30
|
version?: number;
|
|
@@ -108,23 +101,6 @@ export interface FigureFinding {
|
|
|
108
101
|
* 발행 판정은 막는 것과 알리는 것을 함께 내므로 어느 쪽인지를 값이 스스로 말한다 — 코드를 보고
|
|
109
102
|
* 화면이 다시 분류하면 규칙이 두 벌이 된다.
|
|
110
103
|
*/
|
|
111
|
-
/** One reversible anchor edit the sizing gate has measured against this exact source. */
|
|
112
|
-
export interface FigureGateFix {
|
|
113
|
-
findingWay: string;
|
|
114
|
-
part: string;
|
|
115
|
-
axis: 'x' | 'y' | 'z';
|
|
116
|
-
from?: string;
|
|
117
|
-
to: 'min' | 'center' | 'max' | 'span';
|
|
118
|
-
resolved: number;
|
|
119
|
-
/** All blocking sizing cases clear after this exact edit was remeasured server-side. */
|
|
120
|
-
safe: boolean;
|
|
121
|
-
}
|
|
122
|
-
/** A server-remeasured set of draft-only changes that clears every blocking sizing split. */
|
|
123
|
-
export interface FigureGateFixPlan {
|
|
124
|
-
fixes: FigureGateFix[];
|
|
125
|
-
resolved: number;
|
|
126
|
-
safe: boolean;
|
|
127
|
-
}
|
|
128
104
|
export interface FigureGateFinding {
|
|
129
105
|
code: string;
|
|
130
106
|
message: string;
|
|
@@ -134,9 +110,6 @@ export interface FigureGateFinding {
|
|
|
134
110
|
how?: string;
|
|
135
111
|
/** 갈라진 부품 이름들, 또는 정본 안의 경로. */
|
|
136
112
|
at?: string;
|
|
137
|
-
/** Candidate edits; the UI must preview and explicitly apply these, never auto-save them. */
|
|
138
|
-
fixes?: FigureGateFix[];
|
|
139
|
-
fixPlan?: FigureGateFixPlan;
|
|
140
113
|
blocking: boolean;
|
|
141
114
|
}
|
|
142
115
|
/** 발행해도 되나. `blocked` 면 서버가 거절한다. */
|
package/dist-client/types.js
CHANGED
package/dist-client/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../client/types.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * 화면이 다루는
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../client/types.ts"],"names":[],"mappings":"AAAA;;GAEG","sourcesContent":["/**\n * 화면이 다루는 모양. 도형 자산의 타입은 `@hatiolab/figure-model` 이 정한다 — 여기서 다시 적지 않는다.\n */\n\n/** 서버가 돌려주는 Figure 한 벌. `source` 는 저작면에서만 받는다. */\nexport interface Figure {\n id: string\n /** 컴포넌트 타입 이름. **만든 뒤에 고칠 수 없다.** */\n type: string\n name: string\n description?: string\n /** 분류 하나 — 팔레트에서 묶어 보이는 기준. */\n category?: string\n /** 태그 여럿 — 분류로는 못 하는 찾기. */\n tags?: string[]\n state?: 'draft' | 'released'\n /** 재활용 점수 0~100. 서버가 정본에서 계산한다 — 화면이 보내는 값이 아니다. */\n score?: number\n triangles?: number\n groups?: number\n thumbnail?: string\n thumbnailUpdatedAt?: string\n updatedAt?: string\n updater?: { id: string; name: string }\n /** 도형 자산 JSON 문자열. 목록 질의에는 실려 오지 않는다. */\n source?: string\n properties?: string\n version?: number\n}\n\n/**\n * 발행된 판 하나.\n *\n * 저작 중 저장은 여기 오지 않는다 — 판본은 발행에서만 생긴다.\n */\nexport interface FigureVersion {\n version: number\n /** 발행하며 남긴 말. */\n comment?: string\n state?: 'draft' | 'released'\n updatedAt?: string\n updater?: { id: string; name: string }\n score?: number\n triangles?: number\n groups?: number\n}\n\nexport interface FigureListResult {\n items: Figure[]\n total: number\n}\n\n/**\n * 새 Figure.\n *\n * `score`·`triangles`·`groups` 가 없다 — **서버가 정본에서 계산한다.** 화면이 보내면\n * 거짓이 들어오고 목록이 실물과 다른 것을 보여 준다.\n */\nexport interface NewFigure {\n type: string\n name: string\n description?: string\n category?: string\n tags?: string[]\n source: string\n properties?: string\n state?: 'draft' | 'released'\n thumbnail?: string\n}\n\n/**\n * 수정.\n *\n * `type` 이 없다 — 저장되는 식별자라 고칠 수 없다. 배치된 도면이 그 이름으로 타입을\n * 찾으므로, 바꾸면 그 도면이 빈 화면이 된다.\n */\nexport interface FigurePatch {\n /** 발행 전 초안에서만 받는다 — 발행된 뒤에는 문이 거절한다(ADR-0063 결정 4). */\n type?: string\n name?: string\n description?: string\n category?: string\n /** 빈 배열은 「전부 지운다」, 안 주는 것은 「건드리지 않는다」. */\n tags?: string[]\n source?: string\n properties?: string\n state?: 'draft' | 'released'\n thumbnail?: string\n}\n\n/** 검증 결과 한 줄. 코드는 figure-model 의 것을 그대로 쓴다. */\nexport interface FigureFinding {\n code: string\n message: string\n at?: string\n}\n\n/**\n * 발행 판정 한 줄.\n *\n * `FigureFinding` 과 달리 **`blocking` 이 있다.** 저장 쪽 발견은 정의상 막지 않는 것들이고,\n * 발행 판정은 막는 것과 알리는 것을 함께 내므로 어느 쪽인지를 값이 스스로 말한다 — 코드를 보고\n * 화면이 다시 분류하면 규칙이 두 벌이 된다.\n */\nexport interface FigureGateFinding {\n code: string\n message: string\n /** 왜 그것이 문제인가 — 사람이 무엇을 보게 되나. */\n why?: string\n /** 무엇을 바꾸면 되나 — 부품 이름과 값으로. */\n how?: string\n /** 갈라진 부품 이름들, 또는 정본 안의 경로. */\n at?: string\n blocking: boolean\n}\n\n/** 발행해도 되나. `blocked` 면 서버가 거절한다. */\nexport interface FigureInspection {\n blocked: boolean\n findings: FigureGateFinding[]\n}\n"]}
|
|
@@ -1,35 +1,25 @@
|
|
|
1
|
-
# V3 제품
|
|
1
|
+
# V3 제품 현황
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
형식은 V3(`figure-v3-asset-1`) 하나다. V1·V2 형식은 2026-09-26 코드와 명세에서 제거했다.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## 제품 코드
|
|
6
6
|
|
|
7
7
|
- `client/modeller/v3-product-session.ts`: 모델 ID·로드·저장 경계를 V3 workspace에 연결한다. 다른 모델의 지연 응답을 버리며 로드 실패 시 이전 형상을 노출하지 않는다. UI/AI는 같은 리비전과 undo/redo를 사용한다. AI 편집은 요청 당시 context/revision을 필수로 받는다.
|
|
8
|
-
- `client/modeller/v3-canvas.ts`:
|
|
9
|
-
- `client/modeller/v3-editor.ts`:
|
|
10
|
-
- `client/graphql/v3-store.ts`: 정본을
|
|
11
|
-
- figure-service의 `saveFigureV3`: 도메인 권한 검사, V3 검증, 정확한 이전 정본을 조건으로 하는 atomic UPDATE, 생성 요청 ID를 이용한 재시도. SQLite에서 지원하지 않는 행 잠금은 사용하지 않는다.
|
|
12
|
-
- `client/pages/figure-v3-modeller-page.ts`: 위 요소를 묶는
|
|
8
|
+
- `client/modeller/v3-canvas.ts`: things-scene 편집 모드의 판 위에 평가된 V3 형상을 부품마다 `figure-v3-part` 컴포넌트로 세운다. 새 문맥에서 렌더링이 실패하면 이전 모델을 지운다.
|
|
9
|
+
- `client/modeller/v3-editor.ts`: 부품 목록 · 캔버스 · 오른쪽 탭(속성 · 능력 · 움직임 · 판정 · 환경 · 이력). 실행 취소/다시 실행과 저장 연결.
|
|
10
|
+
- `client/graphql/v3-store.ts`: 정본을 그대로 `saveFigureV3`로 보낸다.
|
|
11
|
+
- figure-service의 `saveFigureV3`: 도메인 권한 검사, V3 검증, 정확한 이전 정본을 조건으로 하는 atomic UPDATE, 생성 요청 ID를 이용한 재시도. SQLite에서 지원하지 않는 행 잠금은 사용하지 않는다. 재지 않은 성능 점수/삼각형 수는 null로 둔다. 실제 운영 DB 저장 테스트는 아직 하지 않았다.
|
|
12
|
+
- `client/pages/figure-v3-modeller-page.ts`: 위 요소를 묶는 페이지. `route.ts`의 `figure-modeller`와 `figure-v3-modeller`가 이 페이지를 연다.
|
|
13
13
|
|
|
14
|
-
##
|
|
14
|
+
## 남은 항목
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
V3의 네 렌더링 공급자만으로 기존 모델 전체가 보존된다고 주장할 수 없다. 구·일반 단면뿐 아니라 관절, 반복, 부품 간 배치 관계, capability, 기본 동작값을 검증해야 한다. 버전 숫자만 변경하거나 형상을 정적 메시로 평탄화하는 것은 전체 전환이 아니다.
|
|
19
|
-
|
|
20
|
-
## 활성화 전에 끝낼 항목
|
|
21
|
-
|
|
22
|
-
1. 기존 32개 자산과 발행 이력의 전환 계획·복구본·미지원 항목 보고. 형상 및 움직임을 비교 검증한다.
|
|
23
|
-
2. 새 페이지의 저작 기능 누락을 채우고 실제 브라우저에서 생성·편집·로드·저장·전환을 확인한다.
|
|
24
|
-
3. operato-figure의 AI-dock과 figure-service 도구/제안 생성기를 V3 정본 및 승인된 트랜잭션 계약으로 전환한다. 페이지 이벤트만 추가한 것은 AI 통합 완료가 아니다.
|
|
25
|
-
4. 발행 게이트, 썸네일, 카탈로그/배치 소비처도 V3 평가 결과를 사용하도록 연결한다. V2 평가 함수에 V3 정본을 전달하지 않는다.
|
|
26
|
-
5. 위 작업을 마친 뒤 기본 모델러 route를 새 페이지로 교체하고 이전 구현을 제거한다. 데이터 미전환 상태에서 route만 먼저 바꾸지 않는다.
|
|
16
|
+
1. operato-figure의 AI-dock과 figure-service 도구/제안 생성기를 V3 정본 및 승인된 트랜잭션 계약으로 연결한다. 페이지 이벤트만 추가한 것은 AI 통합 완료가 아니다.
|
|
17
|
+
2. 발행 게이트, 썸네일, 카탈로그/배치 소비처가 V3 평가 결과를 사용하는지 확인한다.
|
|
27
18
|
|
|
28
19
|
## 검증
|
|
29
20
|
|
|
30
|
-
- figure-ui `npm test`:
|
|
31
|
-
- figure-ui client 및 figure-service `tsc --noEmit`: 통과.
|
|
21
|
+
- figure-ui `npm test`: 251개 통과(2026-09-26).
|
|
32
22
|
- SQLite in-memory 테스트: 테넌트 경계·이전 정본 비교·오래된 편집 거절. 실제 TypeORM 리졸버/제품 DB end-to-end 검증을 대체하지 않는다.
|
|
33
|
-
-
|
|
23
|
+
- 브라우저 검사(`npm run test:browser`): 기즈모 끌기 · 자세 슬라이더를 실제 마우스로 조작한다.
|
|
34
24
|
|
|
35
|
-
배포는 사용자가 담당한다.
|
|
25
|
+
배포는 사용자가 담당한다.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@things-factory/figure-ui",
|
|
3
|
-
"version": "10.1.
|
|
3
|
+
"version": "10.1.67",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public",
|
|
6
6
|
"@things-factory:registry": "https://registry.npmjs.org"
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
"clean": "npm run clean:server && npm run clean:client"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@hatiolab/figure-model": "^0.1.
|
|
31
|
-
"@hatiolab/things-scene": "^10.1.
|
|
30
|
+
"@hatiolab/figure-model": "^0.1.78",
|
|
31
|
+
"@hatiolab/things-scene": "^10.1.52",
|
|
32
32
|
"@material/web": "^2.0.0",
|
|
33
33
|
"@operato/data-grist": "^10.0.0",
|
|
34
34
|
"@operato/graphql": "^10.0.0",
|
|
@@ -40,8 +40,8 @@
|
|
|
40
40
|
"@operato/styles": "^10.0.0",
|
|
41
41
|
"@operato/utils": "^10.0.0",
|
|
42
42
|
"@things-factory/ai-assistant": "^10.1.58",
|
|
43
|
-
"@things-factory/figure-service": "^10.1.
|
|
43
|
+
"@things-factory/figure-service": "^10.1.67",
|
|
44
44
|
"three": "^0.185.1"
|
|
45
45
|
},
|
|
46
|
-
"gitHead": "
|
|
46
|
+
"gitHead": "cd3f81fbf667f513dfcfb90906cb97ba935373f5"
|
|
47
47
|
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import 'figure-ui-client/modeller/v3-editor.js'
|
|
7
7
|
import { createV3ProductSession } from 'figure-ui-client/modeller/v3-product-session.js'
|
|
8
|
-
import { addV3Box,
|
|
8
|
+
import { addV3Box, createV3Asset, robotArmV3, serializeV3Asset } from '@hatiolab/figure-model'
|
|
9
9
|
|
|
10
10
|
const PALETTE = {
|
|
11
11
|
'palette.dark': '#2b2b2b',
|
|
@@ -15,16 +15,15 @@ const PALETTE = {
|
|
|
15
15
|
'palette.light': '#dddddd'
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
function sourceOf(kind,
|
|
18
|
+
function sourceOf(kind, text) {
|
|
19
|
+
if (text) return text
|
|
19
20
|
if (kind === 'arm') return serializeV3Asset(robotArmV3())
|
|
20
21
|
if (kind === 'box') {
|
|
21
22
|
const asset = createV3Asset('Probe')
|
|
22
23
|
asset.palette = { ...asset.palette, ...PALETTE }
|
|
23
24
|
return serializeV3Asset(addV3Box(asset, { id: 'box', size: { x: 400, y: 400, z: 400 }, position: { x: 0, y: 200, z: 0 } }))
|
|
24
25
|
}
|
|
25
|
-
|
|
26
|
-
if (result.status !== 'converted') throw Error(`not converted: ${JSON.stringify(result.refusals)}`)
|
|
27
|
-
return serializeV3Asset(result.asset)
|
|
26
|
+
throw Error(`no figure for ${kind}`)
|
|
28
27
|
}
|
|
29
28
|
|
|
30
29
|
function deep(selector, root = document) {
|
|
@@ -179,8 +178,8 @@ window.probe = {
|
|
|
179
178
|
}
|
|
180
179
|
|
|
181
180
|
window.harness = {
|
|
182
|
-
async mount(kind,
|
|
183
|
-
const source = sourceOf(kind,
|
|
181
|
+
async mount(kind, text) {
|
|
182
|
+
const source = sourceOf(kind, text)
|
|
184
183
|
const session = createV3ProductSession({
|
|
185
184
|
load: async id => ({ id, source }),
|
|
186
185
|
save: async request => ({ id: request.id ?? 'probe', source: request.source })
|
|
@@ -3,13 +3,11 @@
|
|
|
3
3
|
*
|
|
4
4
|
* The unit suite proves the rules; it cannot prove what happens between a pointer going down on a gizmo handle and
|
|
5
5
|
* coming up -- the scene writes the component on every move, the editor must not fight it, and the drag must land as
|
|
6
|
-
* one step that stays. Every failure the user found in the gizmo (2026-09-24: selection lost, a
|
|
7
|
-
* springing back, scale growing then snapping back) lived there, and each had been declared working from code. So
|
|
6
|
+
* one step that stays. Every failure the user found in the gizmo (2026-09-24: selection lost, a part placed by a
|
|
7
|
+
* rule springing back, scale growing then snapping back) lived there, and each had been declared working from code. So
|
|
8
8
|
* here the check does what a person does: clicks the part, presses the mode key, hovers until the gizmo holds the
|
|
9
9
|
* handle, drags, lets go -- and then reads the session.
|
|
10
10
|
*
|
|
11
|
-
* Needs the sibling figure-model checkout for the V2 robot arm it converts (as things-scene's browser checks do).
|
|
12
|
-
*
|
|
13
11
|
* Run: npm run test:browser
|
|
14
12
|
* FIGURE_MODEL=../../../figure-model npm run test:browser (a figure-model build not published yet)
|
|
15
13
|
*/
|
|
@@ -23,17 +21,10 @@ import { buildPage } from './build.mjs'
|
|
|
23
21
|
import { openPage } from './serve.mjs'
|
|
24
22
|
|
|
25
23
|
const HERE = dirname(fileURLToPath(import.meta.url))
|
|
26
|
-
const
|
|
24
|
+
const SIX_AXIS = resolve(HERE, '../fixtures/robot-arm-6dof.json')
|
|
27
25
|
|
|
28
26
|
const sleep = ms => new Promise(done => setTimeout(done, ms))
|
|
29
27
|
|
|
30
|
-
/** The V2 six-axis arm, without the tool-seat marker (a slot anchor with no material, which V3 carries as a place). */
|
|
31
|
-
function robotArm() {
|
|
32
|
-
const source = JSON.parse(readFileSync(FIXTURE, 'utf-8'))
|
|
33
|
-
source.parts = source.parts.filter(part => part.material)
|
|
34
|
-
delete source.slots
|
|
35
|
-
return source
|
|
36
|
-
}
|
|
37
28
|
|
|
38
29
|
let opened
|
|
39
30
|
before(async () => {
|
|
@@ -50,7 +41,9 @@ const body = id => read(id => probe.body(id), id)
|
|
|
50
41
|
const fields = id => read(id => probe.fields(id + '.'), id)
|
|
51
42
|
|
|
52
43
|
async function mount(kind) {
|
|
53
|
-
|
|
44
|
+
/* The six-axis arm is a saved asset: its parts are placed by worked-out rules and joints. */
|
|
45
|
+
const text = kind === 'six-axis' ? readFileSync(SIX_AXIS, 'utf-8') : null
|
|
46
|
+
await read((kind, text) => harness.mount(kind, text), kind, text)
|
|
54
47
|
/* The board is built and the camera fitted after the first frames. */
|
|
55
48
|
await sleep(2500)
|
|
56
49
|
}
|
|
@@ -160,9 +153,9 @@ describe('the gizmo on a part the modeller made (own numbers)', () => {
|
|
|
160
153
|
})
|
|
161
154
|
})
|
|
162
155
|
|
|
163
|
-
describe('the gizmo on a
|
|
156
|
+
describe('the gizmo on a part placed by worked-out rules', () => {
|
|
164
157
|
before(async () => {
|
|
165
|
-
await mount('
|
|
158
|
+
await mount('six-axis')
|
|
166
159
|
await click(await read(() => probe.row('pedestal')))
|
|
167
160
|
assert.equal((await state()).selected, 'pedestal', 'a click on the row selects it')
|
|
168
161
|
})
|
|
@@ -225,7 +218,7 @@ describe('the gizmo on a converted part (worked-out rules)', () => {
|
|
|
225
218
|
|
|
226
219
|
describe('a pose slider dragged with the mouse (user 2026-09-24: the arm jumped on release)', () => {
|
|
227
220
|
before(async () => {
|
|
228
|
-
await mount('
|
|
221
|
+
await mount('six-axis')
|
|
229
222
|
await click(await read(() => probe.tab('figure.label.motion')))
|
|
230
223
|
})
|
|
231
224
|
|