@things-factory/figure-ui 10.1.66 → 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 +18 -19
- 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-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 +16 -16
- 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-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/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-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 +0 -143
- package/translations/ja.json +0 -143
- package/translations/ko.json +0 -143
- package/translations/ms.json +0 -143
- package/translations/zh.json +0 -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/client/graphql/index.ts
CHANGED
|
@@ -57,7 +57,6 @@ const FIGURE_LIST_FIELDS = `
|
|
|
57
57
|
score
|
|
58
58
|
triangles
|
|
59
59
|
groups
|
|
60
|
-
format
|
|
61
60
|
thumbnailUpdatedAt
|
|
62
61
|
updatedAt
|
|
63
62
|
updater { id name }
|
|
@@ -244,28 +243,6 @@ export async function inspectFigure(id: string): Promise<FigureInspection> {
|
|
|
244
243
|
why
|
|
245
244
|
how
|
|
246
245
|
at
|
|
247
|
-
fixes {
|
|
248
|
-
findingWay
|
|
249
|
-
part
|
|
250
|
-
axis
|
|
251
|
-
from
|
|
252
|
-
to
|
|
253
|
-
resolved
|
|
254
|
-
safe
|
|
255
|
-
}
|
|
256
|
-
fixPlan {
|
|
257
|
-
resolved
|
|
258
|
-
safe
|
|
259
|
-
fixes {
|
|
260
|
-
findingWay
|
|
261
|
-
part
|
|
262
|
-
axis
|
|
263
|
-
from
|
|
264
|
-
to
|
|
265
|
-
resolved
|
|
266
|
-
safe
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
246
|
blocking
|
|
270
247
|
}
|
|
271
248
|
}
|
|
@@ -297,28 +274,6 @@ export async function inspectFigureDraft(source: string, id?: string): Promise<F
|
|
|
297
274
|
why
|
|
298
275
|
how
|
|
299
276
|
at
|
|
300
|
-
fixes {
|
|
301
|
-
findingWay
|
|
302
|
-
part
|
|
303
|
-
axis
|
|
304
|
-
from
|
|
305
|
-
to
|
|
306
|
-
resolved
|
|
307
|
-
safe
|
|
308
|
-
}
|
|
309
|
-
fixPlan {
|
|
310
|
-
resolved
|
|
311
|
-
safe
|
|
312
|
-
fixes {
|
|
313
|
-
findingWay
|
|
314
|
-
part
|
|
315
|
-
axis
|
|
316
|
-
from
|
|
317
|
-
to
|
|
318
|
-
resolved
|
|
319
|
-
safe
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
277
|
blocking
|
|
323
278
|
}
|
|
324
279
|
}
|
|
@@ -8,7 +8,7 @@ import { i18next, localize } from '@operato/i18n'
|
|
|
8
8
|
import { ScrollbarStyles } from '@operato/styles'
|
|
9
9
|
|
|
10
10
|
import { fetchFigureVersions, inspectFigure, releaseFigure, revertFigureVersion } from '../graphql/index.js'
|
|
11
|
-
import type { FigureGateFinding,
|
|
11
|
+
import type { FigureGateFinding, FigureInspection, FigureVersion } from '../types.js'
|
|
12
12
|
import { OxPrompt } from '@operato/popup'
|
|
13
13
|
|
|
14
14
|
/**
|
|
@@ -195,55 +195,6 @@ export class FigureHistoryPanel extends localize(i18next)(LitElement) {
|
|
|
195
195
|
「이 중 어느 것이 발행을 막았나」를 사람이 다시 세어야 한다.
|
|
196
196
|
*/
|
|
197
197
|
|
|
198
|
-
/* 설명으로 끝내지 않는다. 이 단추는 원본을 바꾸지 않고 모델러에 후보만 연다. */
|
|
199
|
-
li[finding] button[preview-fix] {
|
|
200
|
-
margin-top: 3px;
|
|
201
|
-
padding: 4px 7px;
|
|
202
|
-
font-weight: 700;
|
|
203
|
-
color: var(--md-sys-color-on-primary-container, var(--md-sys-color-on-surface));
|
|
204
|
-
background-color: var(--md-sys-color-primary-container, transparent);
|
|
205
|
-
border: 0;
|
|
206
|
-
border-radius: 5px;
|
|
207
|
-
cursor: pointer;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
li[finding] button[preview-fix]:hover {
|
|
211
|
-
filter: brightness(1.08);
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
li[finding] button[apply-fix] {
|
|
215
|
-
margin-top: 3px;
|
|
216
|
-
padding: 4px 7px;
|
|
217
|
-
font-weight: 700;
|
|
218
|
-
color: var(--ui-on-accent, #fff);
|
|
219
|
-
background-color: var(--md-sys-color-primary);
|
|
220
|
-
border: 0;
|
|
221
|
-
border-radius: 5px;
|
|
222
|
-
cursor: pointer;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
div[ratio-choice] {
|
|
226
|
-
display: flex;
|
|
227
|
-
flex-wrap: wrap;
|
|
228
|
-
gap: 6px;
|
|
229
|
-
margin-top: 4px;
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
div[ratio-choice] button:not([apply-fix]) {
|
|
233
|
-
padding: 4px 7px;
|
|
234
|
-
color: var(--md-sys-color-on-surface);
|
|
235
|
-
background: transparent;
|
|
236
|
-
border: 1px solid var(--md-sys-color-outline-variant);
|
|
237
|
-
border-radius: 5px;
|
|
238
|
-
cursor: pointer;
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
div[ratio-choice] button[selected] {
|
|
242
|
-
color: var(--md-sys-color-on-primary-container);
|
|
243
|
-
background: var(--md-sys-color-primary-container);
|
|
244
|
-
border-color: transparent;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
198
|
p[quiet] {
|
|
248
199
|
margin: 0;
|
|
249
200
|
line-height: 1.6;
|
|
@@ -258,25 +209,16 @@ export class FigureHistoryPanel extends localize(i18next)(LitElement) {
|
|
|
258
209
|
@property({ type: Number }) figureVersion = 0
|
|
259
210
|
/** 저장하지 않은 것이 있나 — 있으면 발행을 막는다. */
|
|
260
211
|
@property({ type: Boolean }) dirty = false
|
|
261
|
-
/**
|
|
262
|
-
* 열린 도형의 형식. 발행 · 판본 · 복원은 figure id 로만 서버를 묻고 서버의 한 문이 두 형식을 다 읽으므로 두 화면이
|
|
263
|
-
* 이 패널을 함께 쓴다. 갈리는 것은 조치 단추 하나다 — 부품을 옮기는 두 조치는 형식마다 다른 편집이라, 받는
|
|
264
|
-
* 화면이 없는 단추를 그리면 눌러도 아무 일이 없다.
|
|
265
|
-
*/
|
|
266
|
-
@property({ type: String }) format: 'v2' | 'v3' = 'v2'
|
|
267
212
|
/**
|
|
268
213
|
* 행의 타입. 판정 하나(`type-is-placeholder`)가 이것을 본다 — V3 자산은 타입을 원본에 적지 않아서, 타입을 바꾸면
|
|
269
214
|
* 원본도 dirty 도 그대로다. 그래서 이 값이 바뀌면 판정을 다시 묻는다. 안 그러면 타입을 정한 뒤에도 「임시 타입」
|
|
270
215
|
* 판정이 남아 발행 단추가 잠긴 채다.
|
|
271
216
|
*/
|
|
272
217
|
@property({ type: String }) figureType?: string
|
|
273
|
-
/** 직전 발행판의 기준 상자. 외형 변화 안내에서 X·Z 복원 선택지에만 쓴다. */
|
|
274
|
-
@property({ attribute: false }) releasedBase?: { x: number; y: number; z: number }
|
|
275
218
|
|
|
276
219
|
@state() private versions: FigureVersion[] = []
|
|
277
220
|
@state() private busy = false
|
|
278
221
|
@state() private failure = ''
|
|
279
|
-
@state() private keepChangedAppearance = false
|
|
280
222
|
/**
|
|
281
223
|
* 발행 판정. **저장된 정본에 대한 것**이라 저장할 때마다 다시 묻는다(`figureVersion` 이 아니라
|
|
282
224
|
* `dirty` 가 풀리는 순간이 그때다).
|
|
@@ -298,7 +240,6 @@ export class FigureHistoryPanel extends localize(i18next)(LitElement) {
|
|
|
298
240
|
}
|
|
299
241
|
|
|
300
242
|
private async inspect() {
|
|
301
|
-
this.keepChangedAppearance = false
|
|
302
243
|
if (!this.figureId || this.dirty) {
|
|
303
244
|
this.inspection = undefined
|
|
304
245
|
return
|
|
@@ -354,7 +295,6 @@ export class FigureHistoryPanel extends localize(i18next)(LitElement) {
|
|
|
354
295
|
*/
|
|
355
296
|
const blocking = (this.inspection?.findings ?? []).filter(finding => finding.blocking)
|
|
356
297
|
const advisory = (this.inspection?.findings ?? []).filter(finding => !finding.blocking)
|
|
357
|
-
const appearanceChoiceNeeded = advisory.some(finding => finding.code === 'base-ratio-changed') && !this.keepChangedAppearance
|
|
358
298
|
|
|
359
299
|
/*
|
|
360
300
|
── 「발행되나」에 **한 번만** 답한다 ─────────────────────────────────────
|
|
@@ -369,8 +309,6 @@ export class FigureHistoryPanel extends localize(i18next)(LitElement) {
|
|
|
369
309
|
? i18next.t('figure.text.release-needs-a-save-first')
|
|
370
310
|
: released
|
|
371
311
|
? i18next.t('figure.text.already-released-edit-to-release-again')
|
|
372
|
-
: appearanceChoiceNeeded
|
|
373
|
-
? i18next.t('figure.text.choose-appearance-change')
|
|
374
312
|
: blocking.length
|
|
375
313
|
? i18next.t('figure.text.cannot-release-now')
|
|
376
314
|
: ''
|
|
@@ -418,61 +356,9 @@ export class FigureHistoryPanel extends localize(i18next)(LitElement) {
|
|
|
418
356
|
${i18next.t('figure.button.fit-base-to-parts')}
|
|
419
357
|
</button>`
|
|
420
358
|
: nothing}
|
|
421
|
-
${finding.code === 'parts-off-placement-face' && this.format === 'v2'
|
|
422
|
-
? html`<button fit-base @click=${() => this.settleOnFloor()}>
|
|
423
|
-
${i18next.t('figure.button.settle-on-floor')}
|
|
424
|
-
</button>`
|
|
425
|
-
: nothing}
|
|
426
|
-
${finding.code === 'base-ratio-changed' && this.releasedBase
|
|
427
|
-
? html`<div ratio-choice>
|
|
428
|
-
<button apply-fix @click=${() => this.restoreReleasedFootprint()}>
|
|
429
|
-
${i18next.t('figure.button.restore-released-base')}
|
|
430
|
-
</button>
|
|
431
|
-
<button ?selected=${this.keepChangedAppearance} @click=${() => this.keepChangedFootprint()}>
|
|
432
|
-
${i18next.t('figure.button.keep-changed-appearance')}
|
|
433
|
-
</button>
|
|
434
|
-
</div>
|
|
435
|
-
<span how-line><md-icon>info</md-icon>${i18next.t('figure.text.appearance-choice-explained')}</span>`
|
|
436
|
-
: nothing}
|
|
437
|
-
${(finding.fixes ?? []).map(fix => html`
|
|
438
|
-
${fix.safe ? html`
|
|
439
|
-
<button apply-fix @click=${() => this.applyFix(fix)}>
|
|
440
|
-
${i18next.t('figure.button.apply-fix', { part: fix.part, axis: fix.axis.toUpperCase(), from: fix.from ?? 'auto', to: fix.to })}
|
|
441
|
-
</button>
|
|
442
|
-
` : nothing}
|
|
443
|
-
<button preview-fix @click=${() => this.previewFix(fix)}>
|
|
444
|
-
${i18next.t('figure.button.preview-fix', { part: fix.part, axis: fix.axis.toUpperCase(), from: fix.from ?? 'auto', to: fix.to })}
|
|
445
|
-
</button>
|
|
446
|
-
`)}
|
|
447
|
-
${finding.fixPlan?.safe ? html`
|
|
448
|
-
<span how-line><md-icon>auto_fix_high</md-icon>${i18next.t('figure.text.recommended-fix-explained', { n: finding.fixPlan.fixes.length })}</span>
|
|
449
|
-
<button apply-fix @click=${() => this.applyFixPlan(finding.fixPlan!)}>
|
|
450
|
-
${i18next.t('figure.button.apply-recommended-fix')}
|
|
451
|
-
</button>
|
|
452
|
-
` : nothing}
|
|
453
359
|
`)
|
|
454
360
|
}
|
|
455
361
|
|
|
456
|
-
/**
|
|
457
|
-
* 게이트는 수정을 저장하지 않는다. 부모 모델러가 현재 정본과 이 한 수정안을 나란히 렌더하고,
|
|
458
|
-
* 저작자가 '변경 받기'를 눌렀을 때에만 자기 작업 사본에 적용한다.
|
|
459
|
-
*/
|
|
460
|
-
private previewFix(fix: FigureGateFix) {
|
|
461
|
-
this.dispatchEvent(new CustomEvent('preview-sizing-fix', { detail: fix, bubbles: true, composed: true }))
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
/** 서버가 전수 재검사해 모든 차단 split이 사라진 후보만 작업 사본에 원클릭 적용한다. 저장은 하지 않는다. */
|
|
465
|
-
private applyFix(fix: FigureGateFix) {
|
|
466
|
-
if (!fix.safe) return
|
|
467
|
-
this.dispatchEvent(new CustomEvent('apply-sizing-fix', { detail: fix, bubbles: true, composed: true }))
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
/** Apply the server-remeasured coordinated repair to the draft only; save remains explicit. */
|
|
471
|
-
private applyFixPlan(plan: FigureGateFixPlan) {
|
|
472
|
-
if (!plan.safe || plan.fixes.length === 0) return
|
|
473
|
-
this.dispatchEvent(new CustomEvent('apply-sizing-fix-plan', { detail: plan, bubbles: true, composed: true }))
|
|
474
|
-
}
|
|
475
|
-
|
|
476
362
|
/**
|
|
477
363
|
* 넘친 것을 담는 길 하나를 여기서도 내민다 — **같은 동작이 속성 패널에도 있다**(「부품에 맞추기」).
|
|
478
364
|
*
|
|
@@ -482,44 +368,19 @@ export class FigureHistoryPanel extends localize(i18next)(LitElement) {
|
|
|
482
368
|
* 여전히 저작자가 따로 한다.
|
|
483
369
|
*/
|
|
484
370
|
/**
|
|
485
|
-
* 「부품에 맞추기」를 내미는
|
|
486
|
-
*
|
|
487
|
-
*
|
|
488
|
-
*
|
|
489
|
-
* V3 의 장착면이 떠 있는 것은 여기 없다. 부품 하나를 평면에 붙이면 그 부품에 붙지 않은 것은 따라오지 않아
|
|
490
|
-
* V2 의 「바닥에 앉히기」와 뜻이 다르다. 판정의 「어떻게」가 할 일을 말한다.
|
|
371
|
+
* 「부품에 맞추기」를 내미는 판정: 공간을 부품에서 다시 선언한다(`declare-occupancy`) — 부품은 그대로 두고 선언만
|
|
372
|
+
* 바꾼다. 공간을 아직 선언하지 않은 도형도 같은 단추로 선언한다: 새로 만든 도형은 전부 그 판정으로 막히고, 화면에
|
|
373
|
+
* 다른 길이 없다. 장착면이 떠 있는 것은 여기 없다 — 부품 하나를 평면에 붙여도 거기 붙지 않은 것은 따라오지 않는다.
|
|
374
|
+
* 판정의 「어떻게」가 할 일을 말한다.
|
|
491
375
|
*/
|
|
492
376
|
private offersFit(code: string): boolean {
|
|
493
|
-
return
|
|
494
|
-
? code === 'part-outside-occupancy' || code === 'occupancy-undeclared'
|
|
495
|
-
: code === 'part-outside-base'
|
|
377
|
+
return code === 'part-outside-occupancy' || code === 'occupancy-undeclared'
|
|
496
378
|
}
|
|
497
379
|
|
|
498
380
|
private fitBase() {
|
|
499
381
|
this.dispatchEvent(new CustomEvent('fit-base-to-parts', { bubbles: true, composed: true }))
|
|
500
382
|
}
|
|
501
383
|
|
|
502
|
-
/**
|
|
503
|
-
* 떠 있는 것을 앉힌다. 부품 하나를 고르고 「바닥에」를 누르는 길은 전부터 있었으나, 그 길은
|
|
504
|
-
* 고른 것 하나만 옮기고 **여기서는 닿지 않는다.** 막혔다는 말을 읽은 자리에서 조치가 되게 한다.
|
|
505
|
-
*/
|
|
506
|
-
private settleOnFloor() {
|
|
507
|
-
this.dispatchEvent(new CustomEvent('settle-parts-on-floor', { bubbles: true, composed: true }))
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
/** 기준 상자의 X·Z만 직전 발행값으로 되돌린다. Y와 부품 편집은 보존한다. */
|
|
511
|
-
private restoreReleasedFootprint() {
|
|
512
|
-
if (!this.releasedBase) return
|
|
513
|
-
this.dispatchEvent(new CustomEvent('restore-released-footprint', {
|
|
514
|
-
detail: { x: this.releasedBase.x, z: this.releasedBase.z }, bubbles: true, composed: true
|
|
515
|
-
}))
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
/** 현재 외형으로 발행하겠다는 명시적 선택이다. 저장·발행은 이어서 따로 한다. */
|
|
519
|
-
private keepChangedFootprint() {
|
|
520
|
-
this.keepChangedAppearance = true
|
|
521
|
-
}
|
|
522
|
-
|
|
523
384
|
private renderVersion(version: FigureVersion) {
|
|
524
385
|
return html`
|
|
525
386
|
<li>
|
|
@@ -9,7 +9,7 @@ import { SidePanelStyles } from './side-panel-styles.js'
|
|
|
9
9
|
|
|
10
10
|
/*
|
|
11
11
|
One rung per set of the format's capability names. Typed as the format's names, so a misspelt rung does not pass
|
|
12
|
-
(ADR-0051
|
|
12
|
+
(ADR-0051 ④).
|
|
13
13
|
*/
|
|
14
14
|
type Rung = 'none' | 'hold' | 'flow'
|
|
15
15
|
const RUNGS: Readonly<Record<Rung, readonly FigureCapability[]>> = Object.freeze({
|
|
@@ -28,7 +28,7 @@ export function rungOf(names: readonly string[] | undefined): Rung | null {
|
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
/**
|
|
31
|
-
* 자리·능력 — what the figure does on a board
|
|
31
|
+
* 자리·능력 — what the figure does on a board: the ladder from drawing only, to
|
|
32
32
|
* holding things, to passing them on, and every place things are held, whatever part it is on. A place is not drawn,
|
|
33
33
|
* so the list is the only way to find one; choosing a row selects its part, where the place is edited.
|
|
34
34
|
*/
|
|
@@ -11,10 +11,10 @@ import { SidePanelStyles } from './side-panel-styles.js'
|
|
|
11
11
|
import { HelpToggles } from './v3-help.js'
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
|
-
* 클립 —
|
|
14
|
+
* 클립 — controls played by keys over time. A clip is one clock; each track plays one
|
|
15
15
|
* control. Scrubbing a clip shows its pose at that moment (one batch of input changes, not saved as the default); a key
|
|
16
16
|
* is added at the scrubbed moment with the control's value there, so a pose is made with the controls' sliders and
|
|
17
|
-
* then kept as a key
|
|
17
|
+
* then kept as a key. Every change is one part edit.
|
|
18
18
|
*/
|
|
19
19
|
@customElement('figure-v3-clips')
|
|
20
20
|
export class FigureV3Clips extends localize(i18next)(LitElement) {
|
|
@@ -11,7 +11,7 @@ import { dialShape } from './angle-dial.js'
|
|
|
11
11
|
import { SidePanelStyles } from './side-panel-styles.js'
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
|
-
* The figure's controls
|
|
14
|
+
* The figure's controls and its pose tools: each value a board sets to pose the figure,
|
|
15
15
|
* with a slider to try it, its name, range and travel time, and a button that keeps the pose being looked at as the
|
|
16
16
|
* pose it stands in when placed.
|
|
17
17
|
*
|
|
@@ -25,7 +25,7 @@ export class FigureV3Controls extends localize(i18next)(LitElement) {
|
|
|
25
25
|
:host {
|
|
26
26
|
display: block;
|
|
27
27
|
}
|
|
28
|
-
/* One control, one line: its name, a dial for an angle, a thin slider, the value
|
|
28
|
+
/* One control, one line: its name, a dial for an angle, a thin slider, the value. */
|
|
29
29
|
div[control] {
|
|
30
30
|
display: grid;
|
|
31
31
|
grid-template-columns: minmax(0, 1fr) 18px minmax(64px, 1.2fr) 58px 22px;
|
|
@@ -10,7 +10,7 @@ import '@material/web/button/text-button.js'
|
|
|
10
10
|
import { firstSaveRefusalOf, releasableType, typeOf, type FirstSave } from './v3-first-save.js'
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
|
-
* The first save of a new figure: its type and its name, asked once
|
|
13
|
+
* The first save of a new figure: its type and its name, asked once, in the suite's popup look.
|
|
14
14
|
* Closes with the answer, or with nothing when cancelled -- then nothing is saved.
|
|
15
15
|
*/
|
|
16
16
|
@customElement('figure-v3-first-save')
|
|
@@ -60,14 +60,14 @@ const freshRow = () => ({ axis: '' as Axis | '', pitch: 200, fills: true, count:
|
|
|
60
60
|
const freshPlace = () => ({ role: 'grip' as 'seat' | 'grip', face: 'top' as V3Face, label: '', accepts: '', capacity: 1 })
|
|
61
61
|
|
|
62
62
|
/**
|
|
63
|
-
* What a part is tied to — its size response, what it is fastened to, how it moves
|
|
63
|
+
* What a part is tied to — its size response, what it is fastened to, how it moves.
|
|
64
64
|
*
|
|
65
65
|
* 「Build Once, Fit Anywhere」 lives here: a dimension that follows the instance size or another part is what lets
|
|
66
66
|
* a figure be placed at any size, and a part fastened to the face it rests on is what keeps it there when that
|
|
67
67
|
* happens. The release gate refuses a figure that falls apart when resized, and tells the author to fasten the
|
|
68
|
-
* parts that come away — this is where they do it. Motion is
|
|
68
|
+
* parts that come away — this is where they do it. Motion is a joint: a slide or a turn driven by a control.
|
|
69
69
|
*
|
|
70
|
-
* The
|
|
70
|
+
* The sections are dimensions, placement and joint, in that order. Every
|
|
71
71
|
* change is one figure-model authoring command, sent as `v3-command` and run by the editor through the session — one
|
|
72
72
|
* step of the undo history. Choices the command would refuse (a round body fastened, a size following an instance
|
|
73
73
|
* size the figure does not declare) are not offered, so the author is not sent into a refusal.
|
|
@@ -158,7 +158,7 @@ export class FigureV3Links extends localize(i18next)(LitElement) {
|
|
|
158
158
|
`
|
|
159
159
|
}
|
|
160
160
|
|
|
161
|
-
/** Where things are held on this part: a seat things rest on, or a grip things are held in
|
|
161
|
+
/** Where things are held on this part: a seat things rest on, or a grip things are held in. */
|
|
162
162
|
private renderPlaces(asset: V3Asset) {
|
|
163
163
|
const faces = placeFacesOf(asset, this.partId)
|
|
164
164
|
const p = this.place
|
|
@@ -294,7 +294,7 @@ export class FigureV3Links extends localize(i18next)(LitElement) {
|
|
|
294
294
|
}
|
|
295
295
|
const [of, a, b] = choice.split(':')
|
|
296
296
|
if (of === 'share') {
|
|
297
|
-
/*
|
|
297
|
+
/* A proportional rule: this measure is the share of the instance size it is now, so it grows with the figure. */
|
|
298
298
|
const size = asset.designInputs[`size.${a}`]
|
|
299
299
|
if (!size) return
|
|
300
300
|
const times = Math.round((current / size) * 1e6) / 1e6
|
|
@@ -306,7 +306,7 @@ export class FigureV3Links extends localize(i18next)(LitElement) {
|
|
|
306
306
|
}
|
|
307
307
|
|
|
308
308
|
/**
|
|
309
|
-
* Positions worked out from other values
|
|
309
|
+
* Positions worked out from other values, each with the way to
|
|
310
310
|
* keep it where it is. This is the way out the release gate names when a resize leaves a part in the air.
|
|
311
311
|
*/
|
|
312
312
|
private renderPositions(asset: V3Asset) {
|
|
@@ -7,7 +7,7 @@ import { activePalette } from '@hatiolab/things-scene'
|
|
|
7
7
|
import type { V3AssetGeometry, V3Material, V3PartEdit } from '@hatiolab/figure-model'
|
|
8
8
|
import { SidePanelStyles } from './side-panel-styles.js'
|
|
9
9
|
|
|
10
|
-
/** The purpose each palette role is for, by its token
|
|
10
|
+
/** The purpose each palette role is for, by its token. */
|
|
11
11
|
const PURPOSE: Record<string, string> = {
|
|
12
12
|
'palette.primary': 'primary',
|
|
13
13
|
'palette.accent': 'accent',
|
|
@@ -27,15 +27,15 @@ const ROUND = new Set(['cylinder', 'ellipticCylinder', 'sphere', 'frustum'])
|
|
|
27
27
|
const DEFAULT_SEGMENTS = 12
|
|
28
28
|
|
|
29
29
|
/**
|
|
30
|
-
* 재질 — a V3 part's material
|
|
30
|
+
* 재질 — a V3 part's material.
|
|
31
31
|
*
|
|
32
|
-
*
|
|
32
|
+
* An earlier editor showed the colour role as a raw token (`palette.dark`) in a select and nothing else. The V3 material
|
|
33
33
|
* holds the colour role, a preset, transparency and a glow; a round body also has how finely its rim is drawn. This
|
|
34
|
-
* shows those
|
|
34
|
+
* shows those: painted colours and lit colours as two groups of swatches, each named for what it
|
|
35
35
|
* is for.
|
|
36
36
|
*
|
|
37
|
-
* Not here, because a V3 material has no place for them: flat shading and casting
|
|
38
|
-
*
|
|
37
|
+
* Not here, because a V3 material has no place for them: flat shading and casting
|
|
38
|
+
* shadows. The glow's colour comes from the lit colours.
|
|
39
39
|
*
|
|
40
40
|
* Every change leaves as one `v3-part-edit`; the editor runs it through the session, one step of the undo history.
|
|
41
41
|
*/
|
|
@@ -75,7 +75,7 @@ export class FigureV3Material extends localize(i18next)(LitElement) {
|
|
|
75
75
|
font: inherit;
|
|
76
76
|
min-width: 0;
|
|
77
77
|
}
|
|
78
|
-
/*
|
|
78
|
+
/* The segment picker: the four common counts as their silhouettes with their triangle cost, the rest folded. */
|
|
79
79
|
div[segments] {
|
|
80
80
|
display: grid;
|
|
81
81
|
grid-template-columns: repeat(4, 1fr);
|
|
@@ -102,7 +102,7 @@ export class FigureV3Material extends localize(i18next)(LitElement) {
|
|
|
102
102
|
background-color: var(--md-sys-color-primary-container);
|
|
103
103
|
border-color: transparent;
|
|
104
104
|
}
|
|
105
|
-
/* Small, and 12 and 16 both read as circles: large enough for the corners to show
|
|
105
|
+
/* Small, and 12 and 16 both read as circles: large enough for the corners to show. */
|
|
106
106
|
button[seg] svg {
|
|
107
107
|
display: block;
|
|
108
108
|
width: 32px;
|
|
@@ -166,7 +166,7 @@ export class FigureV3Material extends localize(i18next)(LitElement) {
|
|
|
166
166
|
if (!part) return nothing
|
|
167
167
|
const material = part.material
|
|
168
168
|
/*
|
|
169
|
-
The roles offered are the app's palette,
|
|
169
|
+
The roles offered are the app's palette, with any the asset carries beyond it. A new asset carries
|
|
170
170
|
only its primary colour; a role it lacks is sent with its colour and added in the same edit (`put`).
|
|
171
171
|
*/
|
|
172
172
|
const entries = Object.entries(this.offered())
|
|
@@ -282,7 +282,7 @@ export class FigureV3Material extends localize(i18next)(LitElement) {
|
|
|
282
282
|
return { ...(activePalette() as Record<string, string>), ...this.palette }
|
|
283
283
|
}
|
|
284
284
|
|
|
285
|
-
/** Intensity 0 is no glow at all
|
|
285
|
+
/** Intensity 0 is no glow at all; a new glow takes the part's own colour until another is picked. */
|
|
286
286
|
private glow(intensity: number, live = false) {
|
|
287
287
|
const material = this.body!.material
|
|
288
288
|
this.glowing = live ? intensity : undefined
|
|
@@ -310,7 +310,7 @@ export class FigureV3Material extends localize(i18next)(LitElement) {
|
|
|
310
310
|
}
|
|
311
311
|
}
|
|
312
312
|
|
|
313
|
-
/** A regular polygon of this many sides -- how round a body with this rim count looks from its end
|
|
313
|
+
/** A regular polygon of this many sides -- how round a body with this rim count looks from its end. */
|
|
314
314
|
function silhouette(segments: number) {
|
|
315
315
|
const points: string[] = []
|
|
316
316
|
for (let i = 0; i < segments; i++) {
|
|
@@ -11,14 +11,12 @@ import { partLabelOf } from './v3-fields.js'
|
|
|
11
11
|
/**
|
|
12
12
|
* 도형 팔레트와 부품 목록 — V3 자산의 것.
|
|
13
13
|
*
|
|
14
|
-
*
|
|
15
|
-
* 가야 한다: 팔레트는 목록 위에, 눈 단추는 늘 자리를 차지하고, 조작은 고른 줄에서만 보인다.
|
|
14
|
+
* 팔레트는 목록 위에, 눈 단추는 늘 자리를 차지하고, 조작은 고른 줄에서만 보인다.
|
|
16
15
|
*
|
|
17
|
-
*
|
|
18
|
-
* 읽는다. 「숨김」은 여기서도 **작업대의 것**이다 — 저장되지 않고, 자산의 `visibility`(상태에 따라
|
|
16
|
+
* 부품의 도형은 V3 평가가 준 `provider` 로 읽는다. 「숨김」은 여기서도 **작업대의 것**이다 — 저장되지 않고, 자산의 `visibility`(상태에 따라
|
|
19
17
|
* 보이고 안 보이는 것)와는 다른 것이다. 그것은 속성 패널의 몫이다.
|
|
20
18
|
*
|
|
21
|
-
* 이 컴포넌트는 정본을 만지지 않는다. 무엇을 하겠다는 것만
|
|
19
|
+
* 이 컴포넌트는 정본을 만지지 않는다. 무엇을 하겠다는 것만 알린다.
|
|
22
20
|
*/
|
|
23
21
|
|
|
24
22
|
/** 한 줄 — V3 평가에서 이 패널이 읽는 것만. */
|
|
@@ -50,8 +48,7 @@ const PROVIDER_ICON: Record<string, string> = {
|
|
|
50
48
|
|
|
51
49
|
/** 팔레트 — 저작 API 가 만들 수 있는 것만 보인다. */
|
|
52
50
|
/*
|
|
53
|
-
The palette
|
|
54
|
-
they are starting sizes, not kinds of their own.
|
|
51
|
+
The palette. A plate and a wall are boxes of a shape a person reaches for, so they are starting sizes, not kinds of their own.
|
|
55
52
|
*/
|
|
56
53
|
export type V3PaletteKind = V3PrimitiveCreation['kind'] | 'plate' | 'wall'
|
|
57
54
|
const RECIPES: Array<{ kind: V3PaletteKind; icon: string; label: string }> = [
|
|
@@ -359,11 +356,11 @@ export class FigureV3Parts extends localize(i18next)(LitElement) {
|
|
|
359
356
|
@property({ type: Boolean }) locked = false
|
|
360
357
|
/**
|
|
361
358
|
* 이 도형이 치르는 값 — 삼각형 · 묶음 · 한 화면에 몇 대 · 등급. 부품을 더하는 바로 그 자리에서 보여야 로우폴리의
|
|
362
|
-
* 기준이 저작을
|
|
359
|
+
* 기준이 저작을 이끈다. 등급이 D 면 무엇이 넘쳤는지를 적는다. 누르면 성숙도 탭이 열린다.
|
|
363
360
|
*/
|
|
364
361
|
@property({ attribute: false }) budget?: V3BudgetLine
|
|
365
362
|
/**
|
|
366
|
-
* 디테일
|
|
363
|
+
* 디테일 등급(S/M/L)의 부품 한도(사용자 2026-09-24). 부품을 넣기 **전에** 몇 개 남았는지 보이고, 다 차면 팔레트가
|
|
367
364
|
* 잠긴다. 되풀이는 한 부품으로 센다. 등급을 안 정했으면 한도는 없다.
|
|
368
365
|
*/
|
|
369
366
|
@property({ attribute: false }) partBudget?: { level: 'S' | 'M' | 'L' | null; used: number; limit: number | null }
|
|
@@ -411,7 +408,7 @@ export class FigureV3Parts extends localize(i18next)(LitElement) {
|
|
|
411
408
|
`
|
|
412
409
|
}
|
|
413
410
|
|
|
414
|
-
/** 디테일 등급 — 고르면 한도가 바뀐다.
|
|
411
|
+
/** 디테일 등급 — 고르면 한도가 바뀐다. 목록 머리 아래. */
|
|
415
412
|
private renderLevel() {
|
|
416
413
|
const b = this.partBudget
|
|
417
414
|
if (!b) return nothing
|
|
@@ -11,15 +11,15 @@ import { dialShape } from './angle-dial.js'
|
|
|
11
11
|
import { authoredSizeOf, PREVIEW_FACTOR, PREVIEW_WAYS, previewClampsOf, previewInstances } from './v3-preview-model.js'
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
|
-
* The figure placed on a board
|
|
14
|
+
* The figure placed on a board.
|
|
15
15
|
*
|
|
16
16
|
* The editing canvas shows the figure at the size it was made. Half of what a figure is lies in how it answers a
|
|
17
17
|
* different size, so here the figure being authored is registered as a board registers it and placed as
|
|
18
18
|
* `FigureInstance`s: the size it was made, and each of the seven ways of growing one, two or three axes twice as
|
|
19
|
-
* large, side by side at one scale, four to a row
|
|
19
|
+
* large, side by side at one scale, four to a row. The board draws them as it will on a real board --
|
|
20
20
|
* placement, lights, environment, the same V3 renderer.
|
|
21
21
|
*
|
|
22
|
-
* The controls
|
|
22
|
+
* The controls: each value that poses the figure with a slider (and a dial for an angle), each clip's
|
|
23
23
|
* speed, and 「이 자세를 기본으로」 to keep the pose as the one it stands in. Nothing here is edited; the canvas edits.
|
|
24
24
|
*/
|
|
25
25
|
|
|
@@ -17,11 +17,10 @@ const PLACEMENTS: Placement[] = ['floor', 'ceiling', 'center', 'wall']
|
|
|
17
17
|
const FACES = Object.keys(V3_FACES) as V3Face[]
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
|
-
* 속성 — the
|
|
20
|
+
* 속성 — the modeller's figure properties.
|
|
21
21
|
*
|
|
22
|
-
* The
|
|
23
|
-
*
|
|
24
|
-
* inspector draws them.
|
|
22
|
+
* The tab opens with what the figure is: its name, the face it is placed by, the room it takes up, where the
|
|
23
|
+
* catalogue files it.
|
|
25
24
|
*
|
|
26
25
|
* Two kinds of change leave this tab, and it does neither itself:
|
|
27
26
|
* - `v3-command` carries an authoring command (rename, declare the room, the mounting face). The page runs it
|
|
@@ -30,7 +29,7 @@ const FACES = Object.keys(V3_FACES) as V3Face[]
|
|
|
30
29
|
* to the saved row at once, so they need a saved figure.
|
|
31
30
|
*
|
|
32
31
|
* Not here yet, because V3 has no place for them: editing the declared room by hand (V3 declares it from the
|
|
33
|
-
* parts, as graph expressions), and the detail level
|
|
32
|
+
* parts, as graph expressions), and the detail level. Both wait on a V3 ruling.
|
|
34
33
|
*/
|
|
35
34
|
@customElement('figure-v3-properties')
|
|
36
35
|
export class FigureV3Properties extends localize(i18next)(LitElement) {
|
|
@@ -81,7 +80,7 @@ export class FigureV3Properties extends localize(i18next)(LitElement) {
|
|
|
81
80
|
render() {
|
|
82
81
|
const facts = this.facts()
|
|
83
82
|
if (!facts) return nothing
|
|
84
|
-
/* The figure's type is the page's (it lives on the row); it is slotted into the first section
|
|
83
|
+
/* The figure's type is the page's (it lives on the row); it is slotted into the first section. */
|
|
85
84
|
return html`<section>
|
|
86
85
|
<h3>${i18next.t('figure.label.group-figure')}</h3>
|
|
87
86
|
<slot name="type"></slot>
|
|
@@ -19,12 +19,12 @@ import type { V3BudgetUse, V3MaturityAxis, V3Report } from './v3-maturity.js'
|
|
|
19
19
|
export const VERDICT_SETTLE_MS = 400
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
|
-
* 성숙도 — the
|
|
22
|
+
* 성숙도 — the modeller's verdict while editing.
|
|
23
23
|
*
|
|
24
|
-
*
|
|
24
|
+
* It shows, as the author edits: how many fit on one screen with the grade beside it and the budget that
|
|
25
25
|
* decided the grade, the grade scale, six maturity axes as a radar and a list, the budget bars, the drawing cost,
|
|
26
|
-
* the reuse trend, and the findings.
|
|
27
|
-
* 「분석부분도 많이 부족하고, 왜 이렇게 너프되었는지」).
|
|
26
|
+
* the reuse trend, and the findings. An earlier tab kept only the count and the findings (user, 2026-09-24:
|
|
27
|
+
* 「분석부분도 많이 부족하고, 왜 이렇게 너프되었는지」).
|
|
28
28
|
*
|
|
29
29
|
* ## What is computed where
|
|
30
30
|
*
|
|
@@ -34,15 +34,14 @@ export const VERDICT_SETTLE_MS = 400
|
|
|
34
34
|
*
|
|
35
35
|
* The findings do not come from here: they come from the server's release door (`inspectFigureDraft`), the same
|
|
36
36
|
* door and the same sentences as the release panel. A second judgement on the screen would say something different
|
|
37
|
-
* the first time either changed.
|
|
38
|
-
* server's, so that section is the server's answer.
|
|
37
|
+
* the first time either changed. The release judgement is the server's, so that section is the server's answer.
|
|
39
38
|
*
|
|
40
39
|
* ## The grade
|
|
41
40
|
*
|
|
42
41
|
* figure-model's `v3ScoreOf`, which the catalogue uses too: headroom against placing `LIMITS.screenInstances` of the
|
|
43
42
|
* figure on one screen (chief architect, 2026-09-24) -- the screen's measured groups and its triangle target shared
|
|
44
|
-
* per instance -- and
|
|
45
|
-
* tightest
|
|
43
|
+
* per instance -- and the rule limits for independently moved parts and transparent materials, decided by the
|
|
44
|
+
* tightest. The two budgets V3 has no field for are left out and the tab says so.
|
|
46
45
|
*/
|
|
47
46
|
/** A per-instance share of the screen is not a whole number; what an instance may draw is the whole part of it. */
|
|
48
47
|
const limitOf = (use: V3BudgetUse) => Math.floor(use.limit).toLocaleString()
|
|
@@ -566,7 +565,7 @@ export class FigureV3Verdict extends localize(i18next)(LitElement) {
|
|
|
566
565
|
`
|
|
567
566
|
}
|
|
568
567
|
|
|
569
|
-
/**
|
|
568
|
+
/** The radar: rings at a third, two thirds and full, short names so the left edge is not cut. */
|
|
570
569
|
private renderRadar(axes: V3MaturityAxis[]) {
|
|
571
570
|
const cx = 60
|
|
572
571
|
const cy = 46
|
|
@@ -671,7 +670,7 @@ export class FigureV3Verdict extends localize(i18next)(LitElement) {
|
|
|
671
670
|
}
|
|
672
671
|
|
|
673
672
|
/**
|
|
674
|
-
* The trend at its own size
|
|
673
|
+
* The trend at its own size: both axes logarithmic, the growing lines against the flat ones, and a
|
|
675
674
|
* legend with each line's value at the last count.
|
|
676
675
|
*/
|
|
677
676
|
private renderSheet(report: V3Report) {
|
|
@@ -4,9 +4,8 @@
|
|
|
4
4
|
* ## 저장되지 않는다
|
|
5
5
|
*
|
|
6
6
|
* 이것은 자산이 아니라 **작업대**다. 조명을 밝게 하고 바닥을 켠 것은 그 사람이 지금
|
|
7
|
-
* 보기 편한 상태일 뿐, 그 자산의 성질이 아니다. 그래서
|
|
8
|
-
*
|
|
9
|
-
* 버린다.
|
|
7
|
+
* 보기 편한 상태일 뿐, 그 자산의 성질이 아니다. 그래서 자산에 안 들어가고, 보는 사람의
|
|
8
|
+
* 브라우저에 남는다.
|
|
10
9
|
*
|
|
11
10
|
* 다른 사람이 같은 자산을 열면 자기 설정으로 본다. 그것이 맞다.
|
|
12
11
|
*
|