@things-factory/figure-ui 10.1.210 → 10.1.212
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 +1 -1
- package/client/modeller/angle-dial.ts +1 -1
- package/client/modeller/canvas.ts +1 -1
- package/client/modeller/editor.ts +24 -32
- package/client/modeller/figure-history-panel.ts +1 -1
- package/client/modeller/figure-links.ts +61 -37
- package/client/modeller/figure-parts.ts +3 -3
- package/client/modeller/figure-settings.ts +1 -1
- package/client/modeller/figure-size-editor.ts +41 -4
- package/client/modeller/links.ts +63 -24
- package/client/modeller/live.ts +33 -0
- package/client/modeller/scene-budget.ts +3 -3
- package/client/modeller/thumbnail.ts +1 -1
- package/client/pages/figure-list-page.ts +2 -2
- package/client/pages/figure-modeller-page.ts +4 -4
- package/client/types.ts +2 -2
- package/client/viewparts/figure-thumb.ts +1 -1
- package/dist-client/graphql/index.d.ts +1 -1
- package/dist-client/graphql/index.js +1 -1
- package/dist-client/graphql/index.js.map +1 -1
- package/dist-client/modeller/angle-dial.d.ts +1 -1
- package/dist-client/modeller/angle-dial.js.map +1 -1
- package/dist-client/modeller/canvas.js +1 -1
- package/dist-client/modeller/canvas.js.map +1 -1
- package/dist-client/modeller/editor.d.ts +5 -0
- package/dist-client/modeller/editor.js +24 -32
- package/dist-client/modeller/editor.js.map +1 -1
- package/dist-client/modeller/figure-history-panel.d.ts +1 -1
- package/dist-client/modeller/figure-history-panel.js.map +1 -1
- package/dist-client/modeller/figure-links.d.ts +2 -0
- package/dist-client/modeller/figure-links.js +66 -39
- package/dist-client/modeller/figure-links.js.map +1 -1
- package/dist-client/modeller/figure-parts.d.ts +3 -3
- package/dist-client/modeller/figure-parts.js.map +1 -1
- package/dist-client/modeller/figure-settings.js +1 -1
- package/dist-client/modeller/figure-settings.js.map +1 -1
- package/dist-client/modeller/figure-size-editor.d.ts +3 -1
- package/dist-client/modeller/figure-size-editor.js +45 -4
- package/dist-client/modeller/figure-size-editor.js.map +1 -1
- package/dist-client/modeller/links.d.ts +15 -6
- package/dist-client/modeller/links.js +63 -25
- package/dist-client/modeller/links.js.map +1 -1
- package/dist-client/modeller/live.d.ts +14 -0
- package/dist-client/modeller/live.js +31 -0
- package/dist-client/modeller/live.js.map +1 -1
- package/dist-client/modeller/scene-budget.d.ts +3 -3
- package/dist-client/modeller/scene-budget.js +3 -3
- package/dist-client/modeller/scene-budget.js.map +1 -1
- package/dist-client/modeller/thumbnail.js +1 -1
- package/dist-client/modeller/thumbnail.js.map +1 -1
- package/dist-client/pages/figure-list-page.d.ts +1 -1
- package/dist-client/pages/figure-list-page.js +2 -2
- package/dist-client/pages/figure-list-page.js.map +1 -1
- package/dist-client/pages/figure-modeller-page.d.ts +3 -3
- package/dist-client/pages/figure-modeller-page.js +4 -4
- 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-client/types.d.ts +2 -2
- package/dist-client/types.js +1 -1
- package/dist-client/types.js.map +1 -1
- package/dist-client/viewparts/figure-thumb.js +1 -1
- package/dist-client/viewparts/figure-thumb.js.map +1 -1
- package/docs/multipart-response-review-2026-10-24.md +1 -1
- package/docs/response-authoring-2026-10-24.md +4 -4
- package/package.json +6 -6
- package/test/ai-proposal.test.ts +1 -1
- package/test/align.test.ts +1 -1
- package/test/browser/editing.check.mjs +38 -0
- package/test/browser/modeller.check.mjs +55 -0
- package/test/command-preview.test.ts +3 -3
- package/test/fields.test.ts +2 -2
- package/test/first-minute.test.ts +5 -5
- package/test/first-save.test.ts +3 -3
- package/test/gizmo.test.ts +3 -3
- package/test/keys.test.ts +2 -2
- package/test/layout.test.ts +1 -1
- package/test/links.test.ts +53 -14
- package/test/live.test.ts +4 -4
- package/test/material.test.ts +1 -1
- package/test/properties.test.ts +1 -1
- package/test/proposal-record.test.ts +1 -1
- package/test/refusals.test.ts +1 -1
- package/test/resize-with-placement.test.ts +1 -1
- package/test/scene-budget.test.ts +4 -4
- package/test/verdict.test.ts +1 -1
- package/translations/en.json +3 -0
- package/translations/es.json +3 -0
- package/translations/ja.json +3 -0
- package/translations/ko.json +109 -106
- package/translations/ms.json +3 -0
- package/translations/zh.json +3 -0
package/test/links.test.ts
CHANGED
|
@@ -96,7 +96,7 @@ test('세 칸의 말은 다섯 말 모두에 있다', () => {
|
|
|
96
96
|
}
|
|
97
97
|
})
|
|
98
98
|
|
|
99
|
-
test('
|
|
99
|
+
test('피규어 크기를 따라 움직이는 자리를 가려 읽고, 여기에 고정하면 사라진다 — 드라이룸 램프의 길', () => {
|
|
100
100
|
let asset = pair()
|
|
101
101
|
asset = addFigureBox(asset, { id: 'lamp', size: { x: 40, y: 20, z: 40 }, position: { x: 0, y: 10, z: 0 } })
|
|
102
102
|
const model = asset.document.model
|
|
@@ -125,7 +125,7 @@ test('자리 — 부품의 면에 둔 집는 자리·놓는 자리를 그 부품
|
|
|
125
125
|
assert.deepEqual(placesOn(asset, 'plate'), [], '다른 부품의 자리는 안 섞인다')
|
|
126
126
|
})
|
|
127
127
|
|
|
128
|
-
test('담는 능력이 없는
|
|
128
|
+
test('담는 능력이 없는 피규어는 자리가 있어도 보드가 아무것도 넘기지 않는다 — 화면이 그것을 말한다', () => {
|
|
129
129
|
const asset = pair()
|
|
130
130
|
assert.equal(holdsThings(asset), false)
|
|
131
131
|
asset.document.capabilities.names = ['Capacity', 'Holdable']
|
|
@@ -221,7 +221,7 @@ const openSides = () => {
|
|
|
221
221
|
}
|
|
222
222
|
|
|
223
223
|
test('도면에서의 크기 — 좁히지 않은 끝은 부품에서 계산하고, 좁힌 끝은 작성자의 값이다', () => {
|
|
224
|
-
assert.equal(instanceRangeOf(createFigureAsset('Probe')), undefined, '크기를 선언하지 않은
|
|
224
|
+
assert.equal(instanceRangeOf(createFigureAsset('Probe')), undefined, '크기를 선언하지 않은 피규어에는 범위가 없다')
|
|
225
225
|
const asset = openSides()
|
|
226
226
|
const y = asset.document.model.inputs.find(i => i.id === 'size.y')!
|
|
227
227
|
y.min = 90
|
|
@@ -245,7 +245,7 @@ test('도면에서의 크기 — 숫자를 치면 그 끝을 좁히고, 칸을
|
|
|
245
245
|
)
|
|
246
246
|
})
|
|
247
247
|
|
|
248
|
-
test('한 비율로 커지는
|
|
248
|
+
test('한 비율로 커지는 피규어 — 자기 숫자인 길이를 세고, 한 번에 따라가게 하며, 무엇이 남는지 이름을 댄다(아키텍트 판정 09-25)', () => {
|
|
249
249
|
let asset = createFigureAsset('Probe')
|
|
250
250
|
asset = addFigureBox(asset, { id: 'base', size: { x: 400, y: 100, z: 400 }, position: { x: 0, y: 0, z: 0 } })
|
|
251
251
|
asset = addFigureBox(asset, { id: 'lamp', size: { x: 60, y: 60, z: 60 }, position: { x: 0, y: 0, z: 0 } })
|
|
@@ -262,7 +262,7 @@ test('한 비율로 커지는 도형 — 자기 숫자인 길이를 세고, 한
|
|
|
262
262
|
assert.equal(Math.round(valueNow(revisionOf(asset), 'lamp.dimension.x.value')! * 1e6) / 1e6, 60, '따르게 해도 지금 크기는 그대로')
|
|
263
263
|
})
|
|
264
264
|
|
|
265
|
-
test('관절이 있는
|
|
265
|
+
test('관절이 있는 피규어에는 한 비율로 키우기를 권하고, 선언하면 규칙으로 보인다(수석 아키텍트 판정 09-24)', () => {
|
|
266
266
|
let asset = sizedPair()
|
|
267
267
|
assert.equal(turnsAboutAJoint(asset), false)
|
|
268
268
|
asset = moving(asset, 'flange', { kind: 'turn', axis: 'y', id: 'flange.turn', min: 0, max: 90 })
|
|
@@ -372,7 +372,7 @@ test('따라 움직이는 관절 — 같은 방식으로 움직이고 제 조작
|
|
|
372
372
|
assert.deepEqual(motionOf(asset, 'right')?.follows, { sum: [{ joint: 'left', multiplier: -1 }], offset: 0 }, '화면은 무엇을 따르는지 읽는다')
|
|
373
373
|
})
|
|
374
374
|
|
|
375
|
-
test('면은
|
|
375
|
+
test('면은 피규어가 정한다 — 문틀(portal)은 바깥 여섯에 개구부 셋, 공은 없고 곡면, 원뿔대는 위아래뿐, 원기둥 옆은 면이 아님 (2026-09-25, ADR-0140 3.9)', async () => {
|
|
376
376
|
const { facesOf, faceAxisOf, canFasten, alignAxesOf, surfaceOf } = await import('../client/modeller/links.ts')
|
|
377
377
|
let asset = createFigureAsset('Doorway')
|
|
378
378
|
asset = addFigurePrimitive(asset, {
|
|
@@ -431,20 +431,20 @@ test('돌려 놓인 부품에도 모서리 맞춤을 내놓는다 — 지금 자
|
|
|
431
431
|
void compileFigureAsset
|
|
432
432
|
})
|
|
433
433
|
|
|
434
|
-
test('모델러에서 만든
|
|
434
|
+
test('모델러에서 만든 피규어는 부품에서 재어 피규어 크기를 선언한다 — 그 뒤에야 부품이 피규어 크기를 따를 수 있다 (사용자 09-25)', async () => {
|
|
435
435
|
const { instanceSizeToDeclare, instanceRangeOf, hasInstanceSize } = await import('../client/modeller/links.ts')
|
|
436
436
|
const { compileFigureAsset } = await import('@hatiolab/figure-model')
|
|
437
437
|
let asset = createFigureAsset('Conveyor')
|
|
438
438
|
assert.equal(instanceSizeToDeclare(asset), undefined, '부품이 없으면 잴 것이 없다')
|
|
439
439
|
asset = addFigureBox(asset, { id: 'frame', size: { x: 2000, y: 100, z: 600 }, position: { x: 0, y: 0, z: 0 } })
|
|
440
440
|
asset = applyFigureAuthoring(asset, { kind: 'attach', part: 'frame', to: { plane: 'mounting-plane' } })
|
|
441
|
-
assert.equal(hasInstanceSize(asset, 'x'), false, '새
|
|
441
|
+
assert.equal(hasInstanceSize(asset, 'x'), false, '새 피규어에는 피규어 크기가 없다')
|
|
442
442
|
const toDeclare = instanceSizeToDeclare(asset)!
|
|
443
443
|
assert.deepEqual(toDeclare.at, { x: 2000, y: 100, z: 600 }, '지금 부품의 크기가 선언할 크기')
|
|
444
444
|
asset = applyFigureAuthoring(asset, { kind: 'declare-instance-size', at: toDeclare.at })
|
|
445
445
|
assert.ok(instanceRangeOf(asset), '선언 뒤에는 도면에서의 크기가 보인다')
|
|
446
446
|
assert.equal(instanceSizeToDeclare(asset), undefined, '이미 있으면 다시 권하지 않는다')
|
|
447
|
-
assert.equal(hasInstanceSize(asset, 'x'), true, '부품이
|
|
447
|
+
assert.equal(hasInstanceSize(asset, 'x'), true, '부품이 피규어 크기를 따르는 선택이 열린다')
|
|
448
448
|
asset = applyFigureAuthoring(asset, { kind: 'link-dimension', part: 'frame', axis: 'x', source: { of: 'instance', axis: 'x' } } as never)
|
|
449
449
|
const at = (size: number) => (compileFigureAsset({ ...asset, designInputs: { ...asset.designInputs, 'size.x': size } }).evaluate().geometry.find(g => g.id === 'frame')!.shape.dimensions as Record<string, number>)['size.x']
|
|
450
450
|
assert.equal(at(3000), 3000, '보드가 3000 으로 놓으면 틀도 3000')
|
|
@@ -490,7 +490,7 @@ test('미끄러짐의 이동 거리가 부품 길이를 따른다 — 레일이
|
|
|
490
490
|
assert.equal(end(4500), 0, '레일이 길어져도 끝까지')
|
|
491
491
|
})
|
|
492
492
|
|
|
493
|
-
test('면 위 거리를
|
|
493
|
+
test('면 위 거리를 피규어 크기 비율로 — 피규어가 커지면 그 자리도 비율로 옮긴다 (사이징, 2026-09-25)', async () => {
|
|
494
494
|
const { alignOf } = await import('../client/modeller/links.ts')
|
|
495
495
|
const { compileFigureAsset } = await import('@hatiolab/figure-model')
|
|
496
496
|
let asset = createFigureAsset('Panel')
|
|
@@ -498,7 +498,7 @@ test('면 위 거리를 도형 크기 비율로 — 도형이 커지면 그 자
|
|
|
498
498
|
asset = addFigureBox(asset, { id: 'lamp', size: { x: 60, y: 60, z: 30 }, position: { x: 0, y: 0, z: 0 } })
|
|
499
499
|
asset = applyFigureAuthoring(asset, { kind: 'attach', part: 'panel', to: { plane: 'mounting-plane' } })
|
|
500
500
|
const front = { part: 'panel', face: 'front' }
|
|
501
|
-
assert.deepEqual(alignOf(asset, front, { x: 'share' }, { x: 300 }), undefined, '
|
|
501
|
+
assert.deepEqual(alignOf(asset, front, { x: 'share' }, { x: 300 }), undefined, '피규어 크기가 없으면 비율을 보낼 수 없다')
|
|
502
502
|
asset = applyFigureAuthoring(asset, { kind: 'declare-instance-size', range: { x: { min: 200, max: 5000 }, y: { min: 200, max: 5000 }, z: { min: 10, max: 500 } }, at: { x: 1000, y: 800, z: 40 } })
|
|
503
503
|
asset = applyFigureAuthoring(asset, { kind: 'link-dimension', part: 'panel', axis: 'x', source: { of: 'instance', axis: 'x' } })
|
|
504
504
|
const align = alignOf(asset, front, { x: 'share' }, { x: 300 })!
|
|
@@ -506,7 +506,7 @@ test('면 위 거리를 도형 크기 비율로 — 도형이 커지면 그 자
|
|
|
506
506
|
asset = applyFigureAuthoring(asset, { kind: 'attach', part: 'lamp', to: front, align })
|
|
507
507
|
const x = (size: number) => Math.round(compileFigureAsset({ ...asset, designInputs: { ...asset.designInputs, 'size.x': size } }).evaluate().geometry.find(g => g.id === 'lamp')!.pose.t[0]!)
|
|
508
508
|
assert.equal(x(1000), 300)
|
|
509
|
-
assert.equal(x(2000), 600, '
|
|
509
|
+
assert.equal(x(2000), 600, '피규어가 두 배면 거리도 두 배')
|
|
510
510
|
})
|
|
511
511
|
|
|
512
512
|
test('선언할 크기는 부품이 쉬고 있을 때의 크기 — 문짝이 도는 자리까지 재지 않는다 (2026-09-25)', async () => {
|
|
@@ -521,7 +521,7 @@ test('선언할 크기는 부품이 쉬고 있을 때의 크기 — 문짝이
|
|
|
521
521
|
assert.deepEqual(instanceSizeToDeclare(asset)!.at, { x: 995, y: 2100, z: 150 })
|
|
522
522
|
})
|
|
523
523
|
|
|
524
|
-
test('바닥에 선 부품도
|
|
524
|
+
test('바닥에 선 부품도 피규어 크기를 선언한 피규어면 피규어의 옆면에 맞출 수 있다 (2026-09-25)', async () => {
|
|
525
525
|
const { alignAxesOf, alignOf } = await import('../client/modeller/links.ts')
|
|
526
526
|
let asset = addFigureBox(createFigureAsset('Gate'), { id: 'post', size: { x: 100, y: 2000, z: 150 }, position: { x: 0, y: 0, z: 0 } })
|
|
527
527
|
assert.deepEqual(alignAxesOf(asset, 'plane'), [{ axis: 'x', edges: false }, { axis: 'z', edges: false }], '크기가 없으면 옆면도 없다')
|
|
@@ -616,7 +616,7 @@ test('팔레트의 문틀은 문 크기로 서고, 세 축 모두 크기를 따
|
|
|
616
616
|
})
|
|
617
617
|
|
|
618
618
|
/* 크기를 따라감 한 번 — 치수 칸의 단추 하나, 크기를 대신 정했으면 한 줄로 말한다 (ADR 판정 Q1, 09-26). */
|
|
619
|
-
test('치수 칸 —
|
|
619
|
+
test('치수 칸 — 「피규어 크기를 따라감」 단추는 follow-size 한 번, 다 따르면 사라진다; 크기를 대신 정하면 한 줄', () => {
|
|
620
620
|
const ko = wordsOf('ko')
|
|
621
621
|
assert.match(ko['figure.text.size-declared-to-follow'], /\{x\} × \{y\} × \{z\} mm/)
|
|
622
622
|
})
|
|
@@ -703,3 +703,42 @@ test('a follower of several leaders and a stroke that is a sum of lengths are wr
|
|
|
703
703
|
assert.equal(slide.travel, '')
|
|
704
704
|
assert.deepEqual(motionJoint(reach, slide, 'wrist').motion![0]!.travel, reach.motion[0]!.travel, 'saving keeps the summed stroke')
|
|
705
705
|
})
|
|
706
|
+
|
|
707
|
+
test('어깨는 축 둘 — 축 추가는 쓰지 않은 축으로 시작하고, 고쳐도 다른 축은 그대로, 같은 관절의 다른 축을 따를 수 있고, 축을 빼도 남은 축의 조작값 이름은 그대로 (ADR-0159)', async () => {
|
|
708
|
+
const { leadersFor, motionJoint, motionFormOf, motionOf, withoutAxis, controlIdFor } = await import('../client/modeller/links.ts')
|
|
709
|
+
const { compileFigureAsset, motionIdOf } = await import('@hatiolab/figure-model')
|
|
710
|
+
let asset = createFigureAsset('Shoulder')
|
|
711
|
+
asset = addFigureBox(asset, { id: 'body', size: { x: 300, y: 400, z: 200 }, position: { x: 0, y: 200, z: 0 } })
|
|
712
|
+
asset = addFigureBox(asset, { id: 'arm', size: { x: 60, y: 300, z: 60 }, position: { x: 0, y: 550, z: 0 } })
|
|
713
|
+
asset = applyFigureAuthoring(asset, { kind: 'attach', part: 'body', to: { plane: 'mounting-plane' } })
|
|
714
|
+
asset = applyFigureAuthoring(asset, { kind: 'attach', part: 'arm', to: { part: 'body', face: 'top' } })
|
|
715
|
+
const jointOf = () => asset.joints!.find(j => j.body1.part === 'arm')!
|
|
716
|
+
asset = applyFigureAuthoring(asset, { kind: 'set-joint', joint: motionJoint(jointOf(), { ...motionFormOf(jointOf()), kind: 'turn', axis: 'x', id: 'pitch', min: -60, max: 180 }, 'arm') })
|
|
717
|
+
|
|
718
|
+
const fresh = motionFormOf(jointOf(), 1)
|
|
719
|
+
assert.deepEqual([fresh.kind, fresh.axis, fresh.id, fresh.min, fresh.max], ['turn', 'y', '', -90, 90], '새 축은 쓰지 않은 축의 돎')
|
|
720
|
+
asset = applyFigureAuthoring(asset, { kind: 'set-joint', joint: motionJoint(jointOf(), fresh, 'arm', 1) })
|
|
721
|
+
assert.equal(jointOf().motion!.length, 2)
|
|
722
|
+
assert.equal(controlIdFor('arm', 'turn', 1), 'arm-turn-2')
|
|
723
|
+
assert.deepEqual(motionOf(asset, 'arm', 1), { kind: 'turn', axis: 'y', control: { id: 'arm-turn-2', unit: 'deg', min: -90, max: 90 } }, '둘째 축은 기록대로 읽는다')
|
|
724
|
+
assert.equal(motionOf(asset, 'arm')?.control?.id, 'pitch', '첫 축은 그대로')
|
|
725
|
+
|
|
726
|
+
asset = applyFigureAuthoring(asset, { kind: 'set-joint', joint: motionJoint(jointOf(), { ...motionFormOf(jointOf(), 1), min: -30, max: 30 }, 'arm', 1) })
|
|
727
|
+
assert.deepEqual([jointOf().motion![0]!.lowerLimit, jointOf().motion![0]!.upperLimit, jointOf().motion![1]!.lowerLimit], [-60, 180, -30], '둘째 축만 바뀐다')
|
|
728
|
+
|
|
729
|
+
/* The second axis turns the arm about Y, on top of the first. */
|
|
730
|
+
const turned = (state: Record<string, number>) => compileFigureAsset(asset).evaluate(state).geometry.find(g => g.id === 'arm')!.pose.r
|
|
731
|
+
assert.notDeepEqual(turned({ 'arm-turn-2': 30 }), turned({}))
|
|
732
|
+
|
|
733
|
+
assert.deepEqual(leadersFor(asset, 'arm', 'turn', motionIdOf(jointOf(), 1)).map(a => a.id), ['arm'], '같은 관절의 첫 축은 따를 수 있다')
|
|
734
|
+
assert.deepEqual(leadersFor(asset, 'arm', 'turn', motionIdOf(jointOf(), 0)).map(a => a.id), ['arm.2'], '제 축은 고르지 않는다')
|
|
735
|
+
|
|
736
|
+
asset = applyFigureAuthoring(asset, { kind: 'set-joint', joint: motionJoint(jointOf(), { ...motionFormOf(jointOf(), 2), id: 'roll' }, 'arm', 2) })
|
|
737
|
+
asset = applyFigureAuthoring(asset, { kind: 'set-joint', joint: withoutAxis(jointOf(), 0) })
|
|
738
|
+
assert.deepEqual(
|
|
739
|
+
jointOf().motion!.map(a => [a.id, a.state?.id]),
|
|
740
|
+
[['arm.2', 'arm-turn-2'], ['arm.3', 'roll']],
|
|
741
|
+
'앞 축을 빼도 뒤 축은 제 이름과 조작값을 지킨다'
|
|
742
|
+
)
|
|
743
|
+
assert.notDeepEqual(turned({ 'arm-turn-2': 30 }), turned({}), '남은 축은 같은 조작값으로 움직인다')
|
|
744
|
+
})
|
package/test/live.test.ts
CHANGED
|
@@ -17,7 +17,7 @@ const slider = () => {
|
|
|
17
17
|
return moving(asset, 'block', { kind: 'slide', axis: 'x', id: 'shift', min: 0, max: 60, start: 0 })
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
test('끄는 값으로 그 자세를 바로 그린다 —
|
|
20
|
+
test('끄는 값으로 그 자세를 바로 그린다 — 피규어는 그대로', () => {
|
|
21
21
|
const asset = slider()
|
|
22
22
|
const before = JSON.stringify(asset)
|
|
23
23
|
const parts = livePartsOf(asset, { values: { shift: 45 } })!
|
|
@@ -26,7 +26,7 @@ test('끄는 값으로 그 자세를 바로 그린다 — 도형은 그대로',
|
|
|
26
26
|
assert.equal(livePartsOf(asset, NOTHING_LIVE), null, '끄는 것이 없으면 평소대로')
|
|
27
27
|
})
|
|
28
28
|
|
|
29
|
-
test('속성창의 설계 값도 치는 동안 그린다 — 크기가 따라 변하고
|
|
29
|
+
test('속성창의 설계 값도 치는 동안 그린다 — 크기가 따라 변하고 피규어는 그대로', () => {
|
|
30
30
|
const asset = slider()
|
|
31
31
|
const before = JSON.stringify(asset)
|
|
32
32
|
const size = (parts: { id: string; shape?: unknown }[]) => JSON.stringify((parts.find(p => p.id === 'block') as { shape: unknown }).shape)
|
|
@@ -40,7 +40,7 @@ test('설계 값과 자세를 가른다 — 모르는 이름은 버린다', () =
|
|
|
40
40
|
assert.deepEqual(liveOverridesOf(slider(), { shift: 10, 'block.size.x': 5, nothing: 1 }), { design: { 'block.size.x': 5 }, state: { shift: 10 } })
|
|
41
41
|
})
|
|
42
42
|
|
|
43
|
-
test('치는 도중
|
|
43
|
+
test('치는 도중 피규어가 못 받는 값이면 지금 모습을 그린다 — 지어낸 피규어를 보이지 않는다', () => {
|
|
44
44
|
assert.equal(livePartsOf(slider(), { values: { 'block.size.x': -5 } }), null)
|
|
45
45
|
})
|
|
46
46
|
|
|
@@ -51,7 +51,7 @@ test('재질의 끄는 값(발광)도 그린다 — 편집 하나를 기록 없
|
|
|
51
51
|
edit: { kind: 'set-material', target: 'block', material: { token: 'palette.primary', emissive: { token: 'palette.primary', intensity: 0.5, on: true } } }
|
|
52
52
|
})!
|
|
53
53
|
assert.equal(glowing.find(p => p.id === 'block')!.material.emissive?.intensity, 0.5)
|
|
54
|
-
assert.equal(asset.appearance[0]!.material.emissive, undefined, '
|
|
54
|
+
assert.equal(asset.appearance[0]!.material.emissive, undefined, '피규어는 그대로')
|
|
55
55
|
})
|
|
56
56
|
|
|
57
57
|
test('이름표를 끌면 값이 크기에 맞는 걸음으로 움직인다 — 각도 1°, 길이는 자릿수에 따라, Shift 는 열 배 곱게', () => {
|
package/test/material.test.ts
CHANGED
|
@@ -57,7 +57,7 @@ test('곡면 분할은 둥근 몸체에만 내고, 고르면 삼각형 수가
|
|
|
57
57
|
assert.ok(fine > coarse, `48 분할이 8 분할보다 삼각형이 많다 (${coarse} → ${fine})`)
|
|
58
58
|
})
|
|
59
59
|
|
|
60
|
-
test('자산에 없는 색 역할은 그 색을 함께 보낸다 — 새
|
|
60
|
+
test('자산에 없는 색 역할은 그 색을 함께 보낸다 — 새 피규어의 팔레트는 기본색 하나다', () => {
|
|
61
61
|
const asset = probe()
|
|
62
62
|
const offered = offeredPaletteOf({ 'palette.primary': '#000000', 'palette.accent': '#f28c28', 'palette.dark': '#2b2b2b' }, asset.palette)
|
|
63
63
|
assert.equal(offered['palette.primary'], asset.palette['palette.primary'], '자산의 색이 앱의 색 위에 선다')
|
package/test/properties.test.ts
CHANGED
|
@@ -115,7 +115,7 @@ test('the dock checks the result from the server: saved is accepted and named, n
|
|
|
115
115
|
const { proposalOutcomeFrom } = await import('../client/modeller/ai-proposal.js')
|
|
116
116
|
const words = JSON.parse(read('../translations/ko.json'))
|
|
117
117
|
const sayKo = (key: string, params: Record<string, string> = {}) => words[key].replace(/\{(\w+)\}/g, (_: string, k: string) => params[k] ?? '')
|
|
118
|
-
assert.deepEqual(proposalOutcomeFrom([{ figureId: 'x', type: 'LIDDED', name: '뚜껑 상자' }], sayKo), { verdict: 'accepted', note: '저장된
|
|
118
|
+
assert.deepEqual(proposalOutcomeFrom([{ figureId: 'x', type: 'LIDDED', name: '뚜껑 상자' }], sayKo), { verdict: 'accepted', note: '저장된 피규어에 들어 있습니다: 뚜껑 상자' })
|
|
119
119
|
assert.equal(proposalOutcomeFrom([], sayKo), undefined, 'not saved is not known, never refused')
|
|
120
120
|
for (const lang of ['en', 'ja', 'ko', 'ms', 'zh', 'es']) assert.ok(JSON.parse(read(`../translations/${lang}.json`))['figure.text.proposal-saved-into'], lang)
|
|
121
121
|
})
|
package/test/refusals.test.ts
CHANGED
|
@@ -271,7 +271,7 @@ test('단면 · 속 공간 — 모서리, 벽, 막힌 끝, 붙은 면을 거절
|
|
|
271
271
|
assert.match(editRefusalOf(refusalOf(() => act(wedge, { kind: 'set-section', part: 'wedge', points: crossed })), keyed), /^figure\.text\.edit-refused .*"code":"SECTION_INVALID"/)
|
|
272
272
|
})
|
|
273
273
|
|
|
274
|
-
test('
|
|
274
|
+
test('피규어의 한도 — 노드 수, 저장 크기, 중첩 깊이를 숫자로 말한다 (「노드 한도」로 잘못 말하던 결함)', () => {
|
|
275
275
|
const doc = structuredClone(box().document) as { model: { nodes: unknown[] } }
|
|
276
276
|
for (let i = 0; i <= fm.FIGURE_DOCUMENT_NODE_LIMIT; i++) doc.model.nodes.push({ id: `k${i}`, op: 'const@1', args: [], outputs: {} })
|
|
277
277
|
const nodes = editRefusalOf(refusalOf(() => fm.compileFigureDocument(doc as never)), say)
|
|
@@ -94,7 +94,7 @@ test('fresh, width only, and all set back to fixed are three different answers',
|
|
|
94
94
|
assert.deepEqual(resizeAxesOf(following, 'box'), { axes: ['y'], basis: 'chosen' })
|
|
95
95
|
assert.deepEqual(resizeAxesOf(following, 'box', ['x']), { axes: ['x', 'y'], basis: 'chosen' })
|
|
96
96
|
const ko = JSON.parse(readFileSync(new URL('../translations/ko.json', import.meta.url), 'utf-8'))
|
|
97
|
-
assert.equal(ko['figure.button.follow-size'], '
|
|
97
|
+
assert.equal(ko['figure.button.follow-size'], '피규어 크기에 맞추기')
|
|
98
98
|
})
|
|
99
99
|
|
|
100
100
|
test('a part off the floor is not moved by choosing its size response', () => {
|
|
@@ -45,9 +45,9 @@ describe('한 화면이 감당하는 양', () => {
|
|
|
45
45
|
})
|
|
46
46
|
|
|
47
47
|
/*
|
|
48
|
-
실측한 두
|
|
48
|
+
실측한 두 피규어가 이 분모로 되돌아오는지 본다. 분모를 누가 고치면 이 둘이 먼저 어긋난다.
|
|
49
49
|
*/
|
|
50
|
-
it('잰 두
|
|
50
|
+
it('잰 두 피규어가 잰 수와 맞다', () => {
|
|
51
51
|
/* 묶음 9 짜리 6 축 로봇: 600 대에서 59.5fps, 700 대에서 56.7fps 였다. */
|
|
52
52
|
assert.ok(capacityFrom(9, 200)!.instances <= 600, '잰 값보다 많이 놓으라고 하면 안 된다')
|
|
53
53
|
/* 묶음 2 짜리 컨베이어: 1,600 대에서 59.3fps, 2,500 대에서 36.8fps 였다. */
|
|
@@ -60,8 +60,8 @@ describe('한 화면이 감당하는 양', () => {
|
|
|
60
60
|
* 놓는 개수로 값을 말하지 않는다 — ADR-0051 ③.
|
|
61
61
|
*
|
|
62
62
|
* 보고서에 「100개 기준 draw call」 · 「1만개 기준」이 오래 남아 있었다. 놓는 개수는 값을 치르지
|
|
63
|
-
* 않는다(가만히 선
|
|
64
|
-
* 그
|
|
63
|
+
* 않는다(가만히 선 피규어는 프레임 비용 0, 카메라 밖은 컬링). 치르는 것은 한 화면에 보이는 개수 ×
|
|
64
|
+
* 그 피규어의 묶음 수이고, 그 답은 위의 실측 분모가 한다.
|
|
65
65
|
*/
|
|
66
66
|
describe('놓는 개수 기준 문구가 화면에 없다', () => {
|
|
67
67
|
const HERE = fileURLToPath(new URL('.', import.meta.url))
|
package/test/verdict.test.ts
CHANGED
|
@@ -36,7 +36,7 @@ test('개수는 목록 카드와 같은 셈이다 — 원가를 같은 capacityF
|
|
|
36
36
|
assert.deepEqual(measured.report, figureReportOf(asset), '탭은 그 셈을 부르고 보여 줄 뿐이다')
|
|
37
37
|
assert.equal(measured.told.instances, capacityFrom(cost.groups, cost.triangles)!.instances, '탭 이름표의 개수도 같은 셈에서 온다')
|
|
38
38
|
assert.deepEqual(measured.told.budget, budgetOf(figureReportOf(asset)), '부품 목록 머리의 줄도 같은 보고서에서 온다')
|
|
39
|
-
assert.deepEqual(verdictMeasureOf(undefined), { report: undefined, told: { instances: undefined, budget: undefined } }, '연
|
|
39
|
+
assert.deepEqual(verdictMeasureOf(undefined), { report: undefined, told: { instances: undefined, budget: undefined } }, '연 피규어가 없으면 잴 것도 알릴 개수도 없다')
|
|
40
40
|
})
|
|
41
41
|
|
|
42
42
|
test('판정은 발행 패널과 같은 서버 문에서 온다 — 화면이 따로 판정하지 않는다', () => {
|
package/translations/en.json
CHANGED
|
@@ -594,6 +594,9 @@
|
|
|
594
594
|
"figure.label.control-start": "start",
|
|
595
595
|
"figure.label.travel-follows": "travel follows",
|
|
596
596
|
"figure.button.add-motion": "Add motion",
|
|
597
|
+
"figure.button.add-axis": "Add axis",
|
|
598
|
+
"figure.button.remove-axis": "Remove axis",
|
|
599
|
+
"figure.label.motion-axis-n": "Axis {n}",
|
|
597
600
|
"figure.button.remove-motion": "Remove motion",
|
|
598
601
|
"figure.label.room": "Room it takes up",
|
|
599
602
|
"figure.text.room-explained": "Bounds computed from the parts are a proposal. Nothing is declared until you confirm, and a declaration never widens on its own.",
|
package/translations/es.json
CHANGED
|
@@ -594,6 +594,9 @@
|
|
|
594
594
|
"figure.label.control-start": "inicio",
|
|
595
595
|
"figure.label.travel-follows": "el recorrido sigue a",
|
|
596
596
|
"figure.button.add-motion": "Añadir movimiento",
|
|
597
|
+
"figure.button.add-axis": "Añadir eje",
|
|
598
|
+
"figure.button.remove-axis": "Quitar eje",
|
|
599
|
+
"figure.label.motion-axis-n": "Eje {n}",
|
|
597
600
|
"figure.button.remove-motion": "Quitar movimiento",
|
|
598
601
|
"figure.label.room": "Espacio que ocupa",
|
|
599
602
|
"figure.text.room-explained": "Los límites calculados a partir de las piezas son una propuesta. No se declara nada hasta que lo confirme, y una declaración nunca se amplía por sí sola.",
|
package/translations/ja.json
CHANGED
|
@@ -594,6 +594,9 @@
|
|
|
594
594
|
"figure.label.control-start": "start",
|
|
595
595
|
"figure.label.travel-follows": "travel follows",
|
|
596
596
|
"figure.button.add-motion": "Add motion",
|
|
597
|
+
"figure.button.add-axis": "軸を追加",
|
|
598
|
+
"figure.button.remove-axis": "軸を削除",
|
|
599
|
+
"figure.label.motion-axis-n": "軸 {n}",
|
|
597
600
|
"figure.button.remove-motion": "Remove motion",
|
|
598
601
|
"figure.label.room": "Room it takes up",
|
|
599
602
|
"figure.text.room-explained": "Bounds computed from the parts are a proposal. Nothing is declared until you confirm, and a declaration never widens on its own.",
|