@things-factory/figure-ui 10.1.16 → 10.1.18
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/modeller/figure-animations.ts +331 -124
- package/client/modeller/figure-canvas.ts +32 -48
- package/client/modeller/figure-capabilities.ts +10 -10
- package/client/modeller/figure-inspector.ts +39 -28
- package/client/modeller/figure-parts.ts +1 -1
- package/client/modeller/figure-preview.ts +151 -41
- package/client/modeller/figure-report.ts +24 -6
- package/client/modeller/figure-settings.ts +45 -2
- package/client/modeller/figure-side.ts +6 -6
- package/client/modeller/figure-source.ts +62 -32
- package/client/modeller/figure-thumbnail.ts +5 -5
- package/client/modeller/figure-view.ts +53 -0
- package/client/modeller/part-edits.ts +36 -36
- package/client/modeller/proposal.ts +27 -4
- package/client/pages/figure-modeller-page.ts +65 -58
- package/dist-client/modeller/figure-animations.d.ts +37 -8
- package/dist-client/modeller/figure-animations.js +293 -122
- package/dist-client/modeller/figure-animations.js.map +1 -1
- package/dist-client/modeller/figure-canvas.d.ts +7 -7
- package/dist-client/modeller/figure-canvas.js +27 -40
- package/dist-client/modeller/figure-canvas.js.map +1 -1
- package/dist-client/modeller/figure-capabilities.d.ts +2 -2
- package/dist-client/modeller/figure-capabilities.js +9 -9
- package/dist-client/modeller/figure-capabilities.js.map +1 -1
- package/dist-client/modeller/figure-inspector.d.ts +16 -5
- package/dist-client/modeller/figure-inspector.js +38 -27
- package/dist-client/modeller/figure-inspector.js.map +1 -1
- package/dist-client/modeller/figure-parts.d.ts +1 -1
- package/dist-client/modeller/figure-parts.js +1 -1
- package/dist-client/modeller/figure-parts.js.map +1 -1
- package/dist-client/modeller/figure-preview.d.ts +56 -6
- package/dist-client/modeller/figure-preview.js +132 -39
- package/dist-client/modeller/figure-preview.js.map +1 -1
- package/dist-client/modeller/figure-report.d.ts +9 -0
- package/dist-client/modeller/figure-report.js +23 -5
- package/dist-client/modeller/figure-report.js.map +1 -1
- package/dist-client/modeller/figure-settings.js +42 -2
- package/dist-client/modeller/figure-settings.js.map +1 -1
- package/dist-client/modeller/figure-side.d.ts +2 -2
- package/dist-client/modeller/figure-side.js +5 -5
- package/dist-client/modeller/figure-side.js.map +1 -1
- package/dist-client/modeller/figure-source.d.ts +25 -15
- package/dist-client/modeller/figure-source.js +42 -21
- package/dist-client/modeller/figure-source.js.map +1 -1
- package/dist-client/modeller/figure-thumbnail.d.ts +2 -2
- package/dist-client/modeller/figure-thumbnail.js +3 -3
- package/dist-client/modeller/figure-thumbnail.js.map +1 -1
- package/dist-client/modeller/figure-view.d.ts +45 -0
- package/dist-client/modeller/figure-view.js +27 -0
- package/dist-client/modeller/figure-view.js.map +1 -1
- package/dist-client/modeller/part-edits.d.ts +16 -16
- package/dist-client/modeller/part-edits.js +35 -35
- package/dist-client/modeller/part-edits.js.map +1 -1
- package/dist-client/modeller/proposal.d.ts +1 -1
- package/dist-client/modeller/proposal.js +16 -3
- package/dist-client/modeller/proposal.js.map +1 -1
- package/dist-client/pages/figure-modeller-page.d.ts +9 -10
- package/dist-client/pages/figure-modeller-page.js +61 -54
- package/dist-client/pages/figure-modeller-page.js.map +1 -1
- package/dist-client/route.d.ts +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +5 -5
- package/test/ai-proposal-contract.test.ts +433 -12
- package/test/expect.ts +55 -0
- package/test/figure-source.test.ts +572 -0
- package/test/i18n-prefix-guard.test.ts +9 -12
- package/{client/modeller → test}/part-edits.test.ts +50 -45
- package/translations/en.json +46 -35
- package/translations/ja.json +16 -21
- package/translations/ko.json +56 -45
- package/translations/ms.json +16 -21
- package/translations/zh.json +16 -21
- package/client/modeller/figure-ask.ts +0 -265
- package/client/modeller/figure-source.test.ts +0 -352
- package/dist-client/modeller/figure-ask.d.ts +0 -40
- package/dist-client/modeller/figure-ask.js +0 -282
- package/dist-client/modeller/figure-ask.js.map +0 -1
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { __decorate, __metadata } from "tslib";
|
|
2
2
|
import '@material/web/icon/icon.js';
|
|
3
3
|
import '../modeller/figure-side.js';
|
|
4
|
-
import '../modeller/figure-ask.js';
|
|
5
4
|
import '../modeller/figure-canvas.js';
|
|
6
5
|
import { captureThumbnail } from '../modeller/figure-thumbnail.js';
|
|
7
6
|
import '../modeller/figure-preview.js';
|
|
@@ -66,7 +65,7 @@ function rememberPanes(panes) {
|
|
|
66
65
|
*/
|
|
67
66
|
function startingModel(type) {
|
|
68
67
|
return {
|
|
69
|
-
|
|
68
|
+
draft: { width: 300, height: 300, depth: 300, figureType: type, detailLevel: 'M' },
|
|
70
69
|
parts: []
|
|
71
70
|
};
|
|
72
71
|
}
|
|
@@ -84,7 +83,7 @@ function startingModel(type) {
|
|
|
84
83
|
*
|
|
85
84
|
* ## 편집 데이터는 씬 모델 하나뿐이다
|
|
86
85
|
*
|
|
87
|
-
* 이 페이지가 갖는 것은
|
|
86
|
+
* 이 페이지가 갖는 것은 초안 하나와 부품 목록 — 미리보기에 그대로 세워지는 씬 모델이다.
|
|
88
87
|
* 저장 형식(`FigureSource`)으로 바꾸는 것은 **경계에서만** 한다: 저장할 때, 판단할 때,
|
|
89
88
|
* AI 후보와 비교할 때. 그 변환은 `figure-source.ts` 한 곳에서만 일어난다.
|
|
90
89
|
*
|
|
@@ -701,14 +700,14 @@ let FigureModellerPage = class FigureModellerPage extends FigureModellerPageBase
|
|
|
701
700
|
}
|
|
702
701
|
`; }
|
|
703
702
|
willUpdate(changed) {
|
|
704
|
-
if (changed.has('
|
|
705
|
-
this.folded = this.
|
|
703
|
+
if (changed.has('draft') || changed.has('parts')) {
|
|
704
|
+
this.folded = this.draft ? toFigureSource(this.draft, this.parts) : undefined;
|
|
706
705
|
}
|
|
707
706
|
}
|
|
708
707
|
/**
|
|
709
708
|
* 페이지 밖 AI 도크에도 **지금 손에 든 정본**을 알려 준다.
|
|
710
709
|
*
|
|
711
|
-
*
|
|
710
|
+
* asidebar 도크는 주소의 id만
|
|
712
711
|
* 알았으므로 DB에 저장된 옛 판을 읽었다. 저장 전 변경을 두고 "왜 발행이 안 되나" 또는
|
|
713
712
|
* "이 부품을 줄여 달라"고 물으면 대화가 엉뚱한 판을 보게 되는 결함이었다.
|
|
714
713
|
*
|
|
@@ -720,7 +719,7 @@ let FigureModellerPage = class FigureModellerPage extends FigureModellerPageBase
|
|
|
720
719
|
if (changed.has('figure') && changed.get('figure')?.id !== this.figure?.id) {
|
|
721
720
|
this.proposalFeedback = [];
|
|
722
721
|
}
|
|
723
|
-
if (changed.has('
|
|
722
|
+
if (changed.has('draft') || changed.has('parts') || changed.has('figure')) {
|
|
724
723
|
window.dispatchEvent(new CustomEvent('figure-ai-context', {
|
|
725
724
|
detail: { figureId: this.figure?.id, source: this.folded }
|
|
726
725
|
}));
|
|
@@ -729,15 +728,15 @@ let FigureModellerPage = class FigureModellerPage extends FigureModellerPageBase
|
|
|
729
728
|
/**
|
|
730
729
|
* A candidate from the dock opens the review lane. It does not become the draft.
|
|
731
730
|
*
|
|
732
|
-
* This used to write `
|
|
731
|
+
* This used to write `draft` and `parts` straight onto the working draft and then set
|
|
733
732
|
* `proposalSession = undefined` — the dock's candidate overwrote what the author had open and
|
|
734
733
|
* erased the lane built to review it. There was no moment where the person said yes, and a
|
|
735
734
|
* draft has no version history to go back to, so the previous work was simply gone.
|
|
736
735
|
*
|
|
737
736
|
* `ai-client-base`'s analysis contract states this as a literal type: `approvalRequired: true`,
|
|
738
737
|
* and of `proposal`, "It is never an instruction to mutate canonical state." The in-page
|
|
739
|
-
*
|
|
740
|
-
* the same door. Applying is what the take button does, from the lane, per change.
|
|
738
|
+
* The in-page entrance honoured this through `openAiProposal` before it was removed, and the dock
|
|
739
|
+
* entrance is now the same door. Applying is what the take button does, from the lane, per change.
|
|
741
740
|
*
|
|
742
741
|
* ## Why the overwrite was there — so it does not come back
|
|
743
742
|
*
|
|
@@ -847,13 +846,13 @@ let FigureModellerPage = class FigureModellerPage extends FigureModellerPageBase
|
|
|
847
846
|
@toggle-part-hidden=${(e) => this.toggleHidden(e.detail.index)}
|
|
848
847
|
@set-all-parts-hidden=${(e) => this.setAllHidden(e.detail.hidden)}
|
|
849
848
|
@change-detail-level=${(e) => this.changeDetailLevel(e.detail.level)}
|
|
850
|
-
@update-
|
|
849
|
+
@update-draft=${(e) => this.updateDraft(e.detail.draft)}
|
|
851
850
|
@part-tool=${(e) => this.runTool(e.detail.index, e.detail.tool, e.detail.axis)}
|
|
852
851
|
@pick-part=${(e) => this.pickPart(e.detail.name)}
|
|
853
852
|
>
|
|
854
853
|
<figure-parts
|
|
855
854
|
.parts=${this.parts}
|
|
856
|
-
.level=${(this.
|
|
855
|
+
.level=${(this.draft?.detailLevel ?? 'M')}
|
|
857
856
|
.selected=${this.selected}
|
|
858
857
|
></figure-parts>
|
|
859
858
|
|
|
@@ -867,7 +866,7 @@ let FigureModellerPage = class FigureModellerPage extends FigureModellerPageBase
|
|
|
867
866
|
<h4>${i18next.t('figure.label.now')}</h4>
|
|
868
867
|
<figure-canvas
|
|
869
868
|
.figureId=${this.figure?.id || this.figure?.type}
|
|
870
|
-
.
|
|
869
|
+
.draft=${this.draft}
|
|
871
870
|
.parts=${this.parts}
|
|
872
871
|
.picked=${this.pickedName}
|
|
873
872
|
.view=${this.view}
|
|
@@ -890,10 +889,10 @@ let FigureModellerPage = class FigureModellerPage extends FigureModellerPageBase
|
|
|
890
889
|
</div>
|
|
891
890
|
`
|
|
892
891
|
: this.mode === 'preview'
|
|
893
|
-
? html `<figure-preview .source=${source}></figure-preview>`
|
|
892
|
+
? html `<figure-preview .source=${source} .view=${this.view}></figure-preview>`
|
|
894
893
|
: html `<figure-canvas
|
|
895
894
|
.figureId=${this.figure?.id || this.figure?.type}
|
|
896
|
-
.
|
|
895
|
+
.draft=${this.draft}
|
|
897
896
|
.parts=${this.parts}
|
|
898
897
|
.picked=${this.pickedName}
|
|
899
898
|
.view=${this.view}
|
|
@@ -909,7 +908,7 @@ let FigureModellerPage = class FigureModellerPage extends FigureModellerPageBase
|
|
|
909
908
|
.figureState=${this.figure?.state}
|
|
910
909
|
.figureVersion=${this.figure?.version ?? 0}
|
|
911
910
|
.dirty=${this.dirty}
|
|
912
|
-
.
|
|
911
|
+
.draft=${this.draft}
|
|
913
912
|
.parts=${this.parts}
|
|
914
913
|
.source=${source}
|
|
915
914
|
.selected=${this.selected}
|
|
@@ -1027,7 +1026,7 @@ let FigureModellerPage = class FigureModellerPage extends FigureModellerPageBase
|
|
|
1027
1026
|
renderProposed() {
|
|
1028
1027
|
if (!this.proposalSession)
|
|
1029
1028
|
return '';
|
|
1030
|
-
return html `<figure-preview .source=${this.proposalSession.source}></figure-preview>`;
|
|
1029
|
+
return html `<figure-preview .source=${this.proposalSession.source} .view=${this.view}></figure-preview>`;
|
|
1031
1030
|
}
|
|
1032
1031
|
/**
|
|
1033
1032
|
* 무엇을 받을지 고른다.
|
|
@@ -1108,14 +1107,22 @@ let FigureModellerPage = class FigureModellerPage extends FigureModellerPageBase
|
|
|
1108
1107
|
}
|
|
1109
1108
|
/** 변경 하나. 무엇을 하겠다는 것인지 부호로 먼저 말한다. */
|
|
1110
1109
|
renderChange(change) {
|
|
1110
|
+
/*
|
|
1111
|
+
Every ChangeKind needs a row here. A kind the map does not answer draws an empty icon and a
|
|
1112
|
+
key with no name beside it, which reads as a broken row rather than a missing case — the
|
|
1113
|
+
`satisfies` makes the compiler say so instead.
|
|
1114
|
+
*/
|
|
1111
1115
|
const icon = {
|
|
1112
1116
|
added: 'add',
|
|
1113
1117
|
changed: 'edit',
|
|
1114
1118
|
removed: 'remove',
|
|
1115
1119
|
base: 'aspect_ratio',
|
|
1120
|
+
placement: 'vertical_align_bottom',
|
|
1116
1121
|
detail: 'tune',
|
|
1117
|
-
|
|
1118
|
-
|
|
1122
|
+
styleKit: 'palette',
|
|
1123
|
+
animations: 'animation',
|
|
1124
|
+
parameters: 'tune',
|
|
1125
|
+
capabilities: 'hub'
|
|
1119
1126
|
}[change.kind];
|
|
1120
1127
|
const on = this.proposalSession?.picked.has(change.key);
|
|
1121
1128
|
return html `
|
|
@@ -1147,7 +1154,7 @@ let FigureModellerPage = class FigureModellerPage extends FigureModellerPageBase
|
|
|
1147
1154
|
/**
|
|
1148
1155
|
* 발행 게이트의 구조화된 수정안 하나를 현재 작업 사본에만 겹쳐 본다. 서버가 준 값은
|
|
1149
1156
|
* `part.anchor.axis = to`라는 데이터이지 사람이 읽을 문장을 다시 해석한 결과가 아니다.
|
|
1150
|
-
* 원본 `
|
|
1157
|
+
* 원본 `draft`/`parts`는 여기서 전혀 바꾸지 않고, 아래의 `take()`만 바꾼 사본을 적용한다.
|
|
1151
1158
|
*/
|
|
1152
1159
|
previewSizingFix(fix) {
|
|
1153
1160
|
if (!this.folded)
|
|
@@ -1180,8 +1187,8 @@ let FigureModellerPage = class FigureModellerPage extends FigureModellerPageBase
|
|
|
1180
1187
|
return;
|
|
1181
1188
|
this.recordHistory();
|
|
1182
1189
|
const taken = proposals.applyProposal(this.folded, this.proposalSession.source, this.proposalSession.picked);
|
|
1183
|
-
const {
|
|
1184
|
-
this.
|
|
1190
|
+
const { draft, parts } = fromFigureSource(taken);
|
|
1191
|
+
this.draft = draft;
|
|
1185
1192
|
this.parts = parts;
|
|
1186
1193
|
this.selected = parts.length ? 0 : -1;
|
|
1187
1194
|
this.dirty = true;
|
|
@@ -1318,7 +1325,7 @@ let FigureModellerPage = class FigureModellerPage extends FigureModellerPageBase
|
|
|
1318
1325
|
// 서버가 준 것을 그대로 쓴다. 읽지 못하면 오류보고없이 빈 상태로 바꾸지 않는다.
|
|
1319
1326
|
// 그러면 사용자가 저장을 선택해 원본을 덮어쓴다.
|
|
1320
1327
|
const model = figure.source ? fromFigureSource(JSON.parse(figure.source)) : undefined;
|
|
1321
|
-
this.
|
|
1328
|
+
this.draft = model?.draft;
|
|
1322
1329
|
this.parts = model?.parts ?? [];
|
|
1323
1330
|
/*
|
|
1324
1331
|
**아무것도 고르지 않은 채로 연다.**
|
|
@@ -1346,9 +1353,9 @@ let FigureModellerPage = class FigureModellerPage extends FigureModellerPageBase
|
|
|
1346
1353
|
this.mode = 'edit';
|
|
1347
1354
|
// 타입 이름을 사람이 정하기 전까지는 임시 이름을 쓴다. 저장할 때 확정한다.
|
|
1348
1355
|
const draftType = `FIGURE_${Date.now().toString(36).toUpperCase()}`;
|
|
1349
|
-
const {
|
|
1356
|
+
const { draft, parts } = startingModel(draftType);
|
|
1350
1357
|
this.figure = { id: '', type: draftType, name: '' };
|
|
1351
|
-
this.
|
|
1358
|
+
this.draft = draft;
|
|
1352
1359
|
this.parts = parts;
|
|
1353
1360
|
/* 고른 것이 없다 — 부품이 없으니 속성 패널도 고를 것을 기다린다. */
|
|
1354
1361
|
this.selected = -1;
|
|
@@ -1368,10 +1375,10 @@ let FigureModellerPage = class FigureModellerPage extends FigureModellerPageBase
|
|
|
1368
1375
|
if (!type || this.figure?.id)
|
|
1369
1376
|
return;
|
|
1370
1377
|
const sanitized = type.replace(/[^A-Za-z0-9_]/g, '_').toUpperCase();
|
|
1371
|
-
if (this.
|
|
1372
|
-
this.
|
|
1378
|
+
if (this.draft)
|
|
1379
|
+
this.draft.figureType = sanitized;
|
|
1373
1380
|
this.figure = { ...this.figure, type: sanitized };
|
|
1374
|
-
this.folded = this.
|
|
1381
|
+
this.folded = this.draft ? toFigureSource(this.draft, this.parts) : undefined;
|
|
1375
1382
|
this.dirty = true;
|
|
1376
1383
|
}
|
|
1377
1384
|
/**
|
|
@@ -1388,7 +1395,7 @@ let FigureModellerPage = class FigureModellerPage extends FigureModellerPageBase
|
|
|
1388
1395
|
}
|
|
1389
1396
|
snapshotState() {
|
|
1390
1397
|
return {
|
|
1391
|
-
|
|
1398
|
+
draft: this.draft ? structuredClone(this.draft) : undefined,
|
|
1392
1399
|
parts: structuredClone(this.parts),
|
|
1393
1400
|
selected: this.selected
|
|
1394
1401
|
};
|
|
@@ -1410,7 +1417,7 @@ let FigureModellerPage = class FigureModellerPage extends FigureModellerPageBase
|
|
|
1410
1417
|
const prev = this.undoStack[this.undoStack.length - 1];
|
|
1411
1418
|
this.undoStack = this.undoStack.slice(0, -1);
|
|
1412
1419
|
this.redoStack = [this.snapshotState(), ...this.redoStack.slice(0, 49)];
|
|
1413
|
-
this.
|
|
1420
|
+
this.draft = prev.draft ? structuredClone(prev.draft) : undefined;
|
|
1414
1421
|
this.parts = structuredClone(prev.parts);
|
|
1415
1422
|
this.selected = this.parts.length ? Math.max(-1, Math.min(prev.selected, this.parts.length - 1)) : -1;
|
|
1416
1423
|
this.dirty = true;
|
|
@@ -1422,7 +1429,7 @@ let FigureModellerPage = class FigureModellerPage extends FigureModellerPageBase
|
|
|
1422
1429
|
const next = this.redoStack[0];
|
|
1423
1430
|
this.redoStack = this.redoStack.slice(1);
|
|
1424
1431
|
this.undoStack = [...this.undoStack.slice(-49), this.snapshotState()];
|
|
1425
|
-
this.
|
|
1432
|
+
this.draft = next.draft ? structuredClone(next.draft) : undefined;
|
|
1426
1433
|
this.parts = structuredClone(next.parts);
|
|
1427
1434
|
this.selected = this.parts.length ? Math.max(-1, Math.min(next.selected, this.parts.length - 1)) : -1;
|
|
1428
1435
|
this.dirty = true;
|
|
@@ -1441,10 +1448,10 @@ let FigureModellerPage = class FigureModellerPage extends FigureModellerPageBase
|
|
|
1441
1448
|
this.dirty = true;
|
|
1442
1449
|
}
|
|
1443
1450
|
addPart(primitive) {
|
|
1444
|
-
if (!this.
|
|
1451
|
+
if (!this.draft)
|
|
1445
1452
|
return;
|
|
1446
1453
|
// 추가한 것을 바로 수정할 수 있게 선택 상태로 둔다.
|
|
1447
|
-
this.put(edits.addPart(this.
|
|
1454
|
+
this.put(edits.addPart(this.draft, this.parts, primitive), this.parts.length);
|
|
1448
1455
|
}
|
|
1449
1456
|
removePart(index) {
|
|
1450
1457
|
this.put(edits.removePart(this.parts, index), Math.max(0, index - 1));
|
|
@@ -1464,26 +1471,26 @@ let FigureModellerPage = class FigureModellerPage extends FigureModellerPageBase
|
|
|
1464
1471
|
* 부품 목록은 건드리지 않는다. `put` 은 부품을 함께 받으므로 여기서 쓰면 능력 하나를
|
|
1465
1472
|
* 고칠 때마다 부품 목록이 새 배열이 되고, 그리는 쪽이 전부 다시 그린다.
|
|
1466
1473
|
*/
|
|
1467
|
-
|
|
1468
|
-
this.recordHistory('
|
|
1469
|
-
this.
|
|
1474
|
+
updateDraft(draft) {
|
|
1475
|
+
this.recordHistory('draft');
|
|
1476
|
+
this.draft = draft;
|
|
1470
1477
|
this.dirty = true;
|
|
1471
1478
|
}
|
|
1472
1479
|
/**
|
|
1473
1480
|
* 디테일 등급을 바꾼다.
|
|
1474
1481
|
*
|
|
1475
1482
|
* 이 값은 부품 수 한도를 정하고 성숙도의 한 축이 된다. 부품보다 위에 있는 값이라
|
|
1476
|
-
*
|
|
1483
|
+
* 초안에 담는다.
|
|
1477
1484
|
*
|
|
1478
1485
|
* 한도를 내려서 이미 넣은 부품 수보다 작아질 수 있다. 그때 부품을 지우지 않는다.
|
|
1479
1486
|
* 검증이 위반으로 알리고, 성숙도가 등급에 안 맞는다고 말한다. 저작자가 무엇을 뺄지
|
|
1480
1487
|
* 정할 일이지 도구가 정할 일이 아니다.
|
|
1481
1488
|
*/
|
|
1482
1489
|
changeDetailLevel(level) {
|
|
1483
|
-
if (!this.
|
|
1490
|
+
if (!this.draft)
|
|
1484
1491
|
return;
|
|
1485
1492
|
this.recordHistory('detailLevel');
|
|
1486
|
-
this.
|
|
1493
|
+
this.draft = { ...this.draft, detailLevel: level };
|
|
1487
1494
|
this.dirty = true;
|
|
1488
1495
|
}
|
|
1489
1496
|
/**
|
|
@@ -1527,18 +1534,18 @@ let FigureModellerPage = class FigureModellerPage extends FigureModellerPageBase
|
|
|
1527
1534
|
* 규칙은 `part-edits` 가 갖는다. 여기서는 어느 것을 부를지만 정한다.
|
|
1528
1535
|
*/
|
|
1529
1536
|
runTool(index, tool, axis) {
|
|
1530
|
-
const
|
|
1531
|
-
if (!
|
|
1537
|
+
const draft = this.draft;
|
|
1538
|
+
if (!draft)
|
|
1532
1539
|
return;
|
|
1533
1540
|
if (tool === 'center')
|
|
1534
|
-
this.put(edits.centerPart(
|
|
1541
|
+
this.put(edits.centerPart(draft, this.parts, index, axis));
|
|
1535
1542
|
else if (tool === 'floor')
|
|
1536
1543
|
this.put(edits.alignPartToStart(this.parts, index, axis));
|
|
1537
1544
|
else if (tool === 'snap')
|
|
1538
|
-
this.put(edits.snapPart(
|
|
1545
|
+
this.put(edits.snapPart(draft, this.parts, index));
|
|
1539
1546
|
// 대칭 복제는 부품이 하나 늘어난다 — 새로 생긴 것을 선택 상태로 둔다
|
|
1540
1547
|
else if (tool === 'mirror')
|
|
1541
|
-
this.put(edits.mirrorPart(
|
|
1548
|
+
this.put(edits.mirrorPart(draft, this.parts, index, axis), index + 1);
|
|
1542
1549
|
}
|
|
1543
1550
|
/**
|
|
1544
1551
|
* 캔버스에서 부품을 선택했다.
|
|
@@ -1588,7 +1595,7 @@ let FigureModellerPage = class FigureModellerPage extends FigureModellerPageBase
|
|
|
1588
1595
|
}
|
|
1589
1596
|
async fillThumbnail(id) {
|
|
1590
1597
|
await this.updateComplete;
|
|
1591
|
-
const thumbnail = await captureThumbnail(this.
|
|
1598
|
+
const thumbnail = await captureThumbnail(this.draft, this.parts);
|
|
1592
1599
|
if (!thumbnail || this.figure?.id !== id) {
|
|
1593
1600
|
return;
|
|
1594
1601
|
}
|
|
@@ -1608,7 +1615,7 @@ let FigureModellerPage = class FigureModellerPage extends FigureModellerPageBase
|
|
|
1608
1615
|
}
|
|
1609
1616
|
if (!this.figure.id) {
|
|
1610
1617
|
// 신규 저장: 타입 코드와 표시 이름을 명확히 팝업으로 확인/입력받음
|
|
1611
|
-
let defaultType = this.
|
|
1618
|
+
let defaultType = this.draft?.figureType || this.figure.type || '';
|
|
1612
1619
|
if (!defaultType || defaultType.startsWith('FIGURE_')) {
|
|
1613
1620
|
defaultType = 'FIGURE';
|
|
1614
1621
|
}
|
|
@@ -1628,7 +1635,7 @@ let FigureModellerPage = class FigureModellerPage extends FigureModellerPageBase
|
|
|
1628
1635
|
this.saveModalError = '';
|
|
1629
1636
|
try {
|
|
1630
1637
|
if (!this.figure.id) {
|
|
1631
|
-
const typeToSave = (this.saveModalType || this.
|
|
1638
|
+
const typeToSave = (this.saveModalType || this.draft?.figureType || this.figure.type || 'FIGURE').trim().toUpperCase();
|
|
1632
1639
|
const nameToSave = (this.saveModalName || this.figure.name || typeToSave).trim();
|
|
1633
1640
|
if (!typeToSave) {
|
|
1634
1641
|
throw new Error('타입 이름을 입력하세요.');
|
|
@@ -1637,12 +1644,12 @@ let FigureModellerPage = class FigureModellerPage extends FigureModellerPageBase
|
|
|
1637
1644
|
if (taken.includes(typeToSave)) {
|
|
1638
1645
|
throw new Error(i18next.t('figure.text.type-name-already-taken', { type: typeToSave }));
|
|
1639
1646
|
}
|
|
1640
|
-
if (this.
|
|
1641
|
-
this.
|
|
1647
|
+
if (this.draft)
|
|
1648
|
+
this.draft.figureType = typeToSave;
|
|
1642
1649
|
this.figure = { ...this.figure, type: typeToSave, name: nameToSave };
|
|
1643
1650
|
this.folded = { ...this.folded, type: typeToSave };
|
|
1644
1651
|
const sourceJson = JSON.stringify(this.folded);
|
|
1645
|
-
const thumbnail = await captureThumbnail(this.
|
|
1652
|
+
const thumbnail = await captureThumbnail(this.draft, this.parts);
|
|
1646
1653
|
const result = await createFigure({
|
|
1647
1654
|
type: typeToSave,
|
|
1648
1655
|
name: nameToSave,
|
|
@@ -1661,11 +1668,11 @@ let FigureModellerPage = class FigureModellerPage extends FigureModellerPageBase
|
|
|
1661
1668
|
// 기존 모델 업데이트: folded.type이 figure.type과 일치하도록 보장
|
|
1662
1669
|
if (this.figure.type && this.folded.type !== this.figure.type) {
|
|
1663
1670
|
this.folded = { ...this.folded, type: this.figure.type };
|
|
1664
|
-
if (this.
|
|
1665
|
-
this.
|
|
1671
|
+
if (this.draft)
|
|
1672
|
+
this.draft.figureType = this.figure.type;
|
|
1666
1673
|
}
|
|
1667
1674
|
const sourceJson = JSON.stringify(this.folded);
|
|
1668
|
-
const thumbnail = await captureThumbnail(this.
|
|
1675
|
+
const thumbnail = await captureThumbnail(this.draft, this.parts);
|
|
1669
1676
|
const result = await updateFigure(this.figure.id, {
|
|
1670
1677
|
name: this.figure.name,
|
|
1671
1678
|
category: this.figure.category,
|
|
@@ -1736,7 +1743,7 @@ __decorate([
|
|
|
1736
1743
|
__decorate([
|
|
1737
1744
|
state(),
|
|
1738
1745
|
__metadata("design:type", Object)
|
|
1739
|
-
], FigureModellerPage.prototype, "
|
|
1746
|
+
], FigureModellerPage.prototype, "draft", void 0);
|
|
1740
1747
|
__decorate([
|
|
1741
1748
|
state(),
|
|
1742
1749
|
__metadata("design:type", Array)
|