@things-factory/figure-ui 10.1.82 → 10.1.84
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/command-preview.ts +4 -2
- package/client/modeller/drawn-shapes.ts +29 -0
- package/client/modeller/editor.ts +11 -29
- package/client/modeller/figure-links.ts +47 -101
- package/client/modeller/figure-material-panel.ts +2 -3
- package/client/modeller/figure-parts.ts +9 -11
- package/client/modeller/figure-section-panel.ts +175 -0
- package/client/modeller/gizmo.ts +26 -16
- package/client/modeller/joint-fan.ts +4 -3
- package/client/modeller/links.ts +24 -24
- package/client/modeller/maturity.ts +12 -6
- package/client/modeller/motion-ends.ts +2 -1
- package/client/modeller/refusals.ts +20 -0
- package/client/modeller/renderer.ts +3 -2
- package/client/modeller/section-controls.ts +34 -0
- package/client/modeller/starting-shape.ts +34 -0
- package/dist-client/modeller/clips.d.ts +1 -1
- package/dist-client/modeller/command-preview.js +4 -2
- package/dist-client/modeller/command-preview.js.map +1 -1
- package/dist-client/modeller/drawn-shapes.d.ts +44 -0
- package/dist-client/modeller/drawn-shapes.js +12 -0
- package/dist-client/modeller/drawn-shapes.js.map +1 -0
- package/dist-client/modeller/editor.d.ts +1 -6
- package/dist-client/modeller/editor.js +10 -29
- package/dist-client/modeller/editor.js.map +1 -1
- package/dist-client/modeller/figure-links.d.ts +2 -2
- package/dist-client/modeller/figure-links.js +45 -96
- package/dist-client/modeller/figure-links.js.map +1 -1
- package/dist-client/modeller/figure-material-panel.js +2 -3
- package/dist-client/modeller/figure-material-panel.js.map +1 -1
- package/dist-client/modeller/figure-parts.d.ts +3 -2
- package/dist-client/modeller/figure-parts.js +6 -9
- package/dist-client/modeller/figure-parts.js.map +1 -1
- package/dist-client/modeller/figure-section-panel.d.ts +28 -0
- package/dist-client/modeller/figure-section-panel.js +172 -0
- package/dist-client/modeller/figure-section-panel.js.map +1 -0
- package/dist-client/modeller/gizmo.d.ts +3 -3
- package/dist-client/modeller/gizmo.js +24 -11
- package/dist-client/modeller/gizmo.js.map +1 -1
- package/dist-client/modeller/joint-fan.js +4 -3
- package/dist-client/modeller/joint-fan.js.map +1 -1
- package/dist-client/modeller/links.d.ts +4 -1
- package/dist-client/modeller/links.js +23 -25
- package/dist-client/modeller/links.js.map +1 -1
- package/dist-client/modeller/maturity.d.ts +3 -2
- package/dist-client/modeller/maturity.js +9 -6
- package/dist-client/modeller/maturity.js.map +1 -1
- package/dist-client/modeller/motion-ends.js +2 -1
- package/dist-client/modeller/motion-ends.js.map +1 -1
- package/dist-client/modeller/refusals.d.ts +0 -5
- package/dist-client/modeller/refusals.js +25 -0
- package/dist-client/modeller/refusals.js.map +1 -1
- package/dist-client/modeller/renderer.d.ts +3 -4
- package/dist-client/modeller/renderer.js +3 -2
- package/dist-client/modeller/renderer.js.map +1 -1
- package/dist-client/modeller/section-controls.d.ts +11 -0
- package/dist-client/modeller/section-controls.js +27 -0
- package/dist-client/modeller/section-controls.js.map +1 -0
- package/dist-client/modeller/starting-shape.d.ts +32 -0
- package/dist-client/modeller/starting-shape.js +37 -0
- package/dist-client/modeller/starting-shape.js.map +1 -0
- 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/browser/acceptance-page.js +8 -0
- package/test/command-preview.test.ts +3 -2
- package/test/fixtures/joint-column.json +110 -15
- package/test/fixtures/joint-roller.json +66 -9
- package/test/fixtures/robot-arm-6dof.json +203 -27
- package/test/joint-fan.test.ts +10 -7
- package/test/links.test.ts +6 -5
- package/test/material.test.ts +7 -2
- package/test/renderer.test.ts +2 -1
- package/test/resize-with-placement.test.ts +15 -14
- package/test/scene-canvas.test.ts +2 -1
- package/test/section-panel.test.ts +93 -0
- package/translations/en.json +21 -2
- package/translations/ja.json +20 -1
- package/translations/ko.json +22 -3
- package/translations/ms.json +20 -1
- package/translations/zh.json +20 -1
- package/dist-client/tsconfig.localkernel.tsbuildinfo +0 -1
|
@@ -45,8 +45,8 @@ for (const mode of ['floor', 'ceiling', 'wall', 'center'] as const) {
|
|
|
45
45
|
/* At twice the height the kept face is where it was. */
|
|
46
46
|
const asset = parseFigureAsset(session.source())
|
|
47
47
|
asset.designInputs['size.y'] = asset.designInputs['size.y']! * 2
|
|
48
|
-
const g = compileFigureAsset(asset).evaluate().geometry.find(g => g.id === 'box')! as unknown as { pose: { t: number[] }; shape: { dimensions:
|
|
49
|
-
const y = g.pose.t[1]!, h = g.shape.dimensions.
|
|
48
|
+
const g = compileFigureAsset(asset).evaluate().geometry.find(g => g.id === 'box')! as unknown as { pose: { t: number[] }; shape: { dimensions: Record<string, number> } }
|
|
49
|
+
const y = g.pose.t[1]!, h = g.shape.dimensions.length!
|
|
50
50
|
if (mode === 'floor') assert.equal(y - h / 2, 0)
|
|
51
51
|
if (mode === 'ceiling') assert.equal(y + h / 2, 0)
|
|
52
52
|
if (mode === 'center') assert.equal(y, 50)
|
|
@@ -81,7 +81,7 @@ test('fresh, width only, and all set back to fixed are three different answers',
|
|
|
81
81
|
const resized = applyFigureProposal(a, planFigureResize(a, { part: 'box', axes: only.axes }).steps)
|
|
82
82
|
for (const axis of ['y', 'z'] as const) assert.equal(figureFollowOf(resized, 'box', axis).of, 'own', `${axis} stays fixed`)
|
|
83
83
|
const g = compileFigureAsset({ ...resized, designInputs: { ...resized.designInputs, 'size.x': 200, 'size.y': 400, 'size.z': 400 } }).evaluate().geometry.find(g => g.id === 'box') as unknown as { shape: { dimensions: Record<string, number> }; pose: { t: number[] } }
|
|
84
|
-
assert.deepEqual(g.shape.dimensions,
|
|
84
|
+
assert.deepEqual([g.shape.dimensions['size.x'], g.shape.dimensions.length, g.shape.dimensions['size.z']], [200, 100, 100], 'width 200; height and depth kept')
|
|
85
85
|
assert.equal(g.pose.t[1]! - 50, 0, 'and it stands on the floor')
|
|
86
86
|
/* All set back to fixed: nothing is taken for "all". */
|
|
87
87
|
let fixed = applyFigureAuthoring(a, { kind: 'follow-size', part: 'box', axes: ['x'] })
|
|
@@ -91,23 +91,23 @@ test('fresh, width only, and all set back to fixed are three different answers',
|
|
|
91
91
|
const following = applyFigureAuthoring(a, { kind: 'follow-size', part: 'box', axes: ['y'] })
|
|
92
92
|
assert.deepEqual(resizeAxesOf(following, 'box'), { axes: ['y'], basis: 'chosen' })
|
|
93
93
|
assert.deepEqual(resizeAxesOf(following, 'box', ['x']), { axes: ['x', 'y'], basis: 'chosen' })
|
|
94
|
-
/* The screen:
|
|
94
|
+
/* The screen: size response is no longer a disguised placement command. */
|
|
95
95
|
const links = readFileSync(new URL('../client/modeller/figure-links.ts', import.meta.url), 'utf-8')
|
|
96
|
-
|
|
97
|
-
assert.ok(
|
|
98
|
-
assert.ok(
|
|
99
|
-
assert.ok(links.includes('
|
|
96
|
+
const dimensions = links.slice(links.indexOf(' private renderDimensions('), links.indexOf(' /** The same source'))
|
|
97
|
+
assert.ok(dimensions.includes("this.command({ kind: 'follow-size', part: this.partId })"))
|
|
98
|
+
assert.ok(!dimensions.includes('resize-with-placement'), 'size response does not attach the part')
|
|
99
|
+
assert.ok(!links.includes('figure.label.stands-on-plane'), 'the attachment form does not present a model-placement toggle')
|
|
100
100
|
const ko = JSON.parse(readFileSync(new URL('../translations/ko.json', import.meta.url), 'utf-8'))
|
|
101
|
-
assert.equal(ko['figure.
|
|
101
|
+
assert.equal(ko['figure.button.follow-size'], '모델 크기에 맞추기')
|
|
102
102
|
})
|
|
103
103
|
|
|
104
|
-
test('a part off the floor is
|
|
104
|
+
test('a part off the floor is not moved by choosing its size response', () => {
|
|
105
105
|
let a = addFigureBox(createFigureAsset('UX'), { id: 'shelf', size: { x: 400, y: 40, z: 300 }, position: { x: 0, y: 520, z: 0 } })
|
|
106
106
|
a = applyFigureAuthoring(a, { kind: 'declare-occupancy', proposal: proposeFigureOccupancy(a), placement: 'floor' })
|
|
107
107
|
const asked = planFigureResize(a, { part: 'shelf', axes: resizeAxesOf(a, 'shelf').axes })
|
|
108
108
|
assert.deepEqual([asked.refusal?.code, asked.refusal?.mm], ['GAP_CHOICE', 500])
|
|
109
109
|
const links = readFileSync(new URL('../client/modeller/figure-links.ts', import.meta.url), 'utf-8')
|
|
110
|
-
assert.ok(links.includes("@click=${() => ask('keep')}")
|
|
110
|
+
assert.ok(!links.includes("@click=${() => ask('keep')}"), 'the UI does not offer a size command that also moves the part')
|
|
111
111
|
})
|
|
112
112
|
|
|
113
113
|
test('a field only the room reads is taken out of the part\'s position row and shown apart', () => {
|
|
@@ -164,10 +164,11 @@ test('a fastened part keeps its position and turn rows, with the numbers the rul
|
|
|
164
164
|
assert.ok(!editor.includes('value="—" disabled'), 'not a blank')
|
|
165
165
|
})
|
|
166
166
|
|
|
167
|
-
test('
|
|
167
|
+
test('size response and attachment are separate screen paths', () => {
|
|
168
168
|
const links = readFileSync(new URL('../client/modeller/figure-links.ts', import.meta.url), 'utf-8')
|
|
169
|
-
assert.ok(links.includes('
|
|
170
|
-
assert.ok(
|
|
169
|
+
assert.ok(links.includes('figure.button.fasten-start'))
|
|
170
|
+
assert.ok(links.includes('figure.label.target-part-placeholder'))
|
|
171
|
+
assert.ok(!links.includes('? this.renderHeld(asset)'))
|
|
171
172
|
const ko = JSON.parse(readFileSync(new URL('../translations/ko.json', import.meta.url), 'utf-8'))
|
|
172
173
|
assert.equal(ko['figure.text.held-on-plane'].replace('{face}', '아랫면').replace('{place}', '바닥').replace('{gap}', '0'), '아랫면을 바닥에 유지 중 (간격 0 mm)')
|
|
173
174
|
})
|
|
@@ -12,6 +12,7 @@ import { fileURLToPath } from 'node:url'
|
|
|
12
12
|
|
|
13
13
|
import { changedKeys, componentOf, gizmoResultOf } from '../client/modeller/stage-model.ts'
|
|
14
14
|
import type { FigureRenderPart } from '../client/modeller/renderer.ts'
|
|
15
|
+
import { boxShape } from '../client/modeller/drawn-shapes.ts'
|
|
15
16
|
|
|
16
17
|
const read = (path: string) => readFileSync(fileURLToPath(new URL(path, import.meta.url)), 'utf8')
|
|
17
18
|
const canvas = read('../client/modeller/canvas.ts')
|
|
@@ -27,7 +28,7 @@ const turned = (deg: number) => {
|
|
|
27
28
|
}
|
|
28
29
|
const box = (t: number[], r = turned(0)): FigureRenderPart => ({
|
|
29
30
|
id: 'block',
|
|
30
|
-
shape:
|
|
31
|
+
shape: boxShape(200, 100, 60),
|
|
31
32
|
pose: { r, t },
|
|
32
33
|
material: { token: 'palette.primary' }
|
|
33
34
|
})
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* **단면 칸 — 모서리와 속 공간** (ADR-0100 1단계, 2026-09-29).
|
|
3
|
+
*
|
|
4
|
+
* 칸이 보내는 명령이 figure-model 에서 정말로 받아들여져 그려지는 몸체를 바꾸는지, 받아들여지지 않을 때 화면이 그 까닭을
|
|
5
|
+
* 사람의 말로 하는지를 잰다.
|
|
6
|
+
*/
|
|
7
|
+
import { test } from 'node:test'
|
|
8
|
+
import assert from 'node:assert/strict'
|
|
9
|
+
import { readFileSync } from 'node:fs'
|
|
10
|
+
import { fileURLToPath } from 'node:url'
|
|
11
|
+
|
|
12
|
+
import { addFigureBox, applyFigureAuthoring, compileFigureAsset, createFigureAsset } from '@hatiolab/figure-model'
|
|
13
|
+
import type { FigureAsset, FigureEvaluatedShape } from '@hatiolab/figure-model'
|
|
14
|
+
|
|
15
|
+
import { cavityRequestOf, defaultWallOf } from '../client/modeller/section-controls.ts'
|
|
16
|
+
import { editRefusalOf } from '../client/modeller/refusals.ts'
|
|
17
|
+
|
|
18
|
+
const read = (path: string) => readFileSync(fileURLToPath(new URL(path, import.meta.url)), 'utf8')
|
|
19
|
+
const panel = read('../client/modeller/figure-section-panel.ts')
|
|
20
|
+
const editor = read('../client/modeller/editor.ts')
|
|
21
|
+
const ko = JSON.parse(read('../translations/ko.json')) as Record<string, string>
|
|
22
|
+
|
|
23
|
+
const probe = () => addFigureBox(createFigureAsset('Probe'), { id: 'body', size: { x: 400, y: 200, z: 300 }, position: { x: 0, y: 100, z: 0 } })
|
|
24
|
+
const shapeOf = (asset: FigureAsset, id = 'body') =>
|
|
25
|
+
(compileFigureAsset(asset).evaluate().geometry.find(g => (g as { id: string }).id === id) as unknown as { shape: FigureEvaluatedShape }).shape
|
|
26
|
+
const say = (key: string, params: Record<string, string>) => Object.entries(params).reduce((s, [k, v]) => s.replace(`{${k}}`, v), ko[key] ?? key)
|
|
27
|
+
const refusal = (run: () => unknown) => {
|
|
28
|
+
try {
|
|
29
|
+
run()
|
|
30
|
+
} catch (error) {
|
|
31
|
+
return editRefusalOf(error, say)
|
|
32
|
+
}
|
|
33
|
+
assert.fail('the command was taken')
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
test('모서리 반지름은 네 모서리를 한 값으로 둥글게 하고, 0 은 둥글림을 없앤다', () => {
|
|
37
|
+
const round = applyFigureAuthoring(probe(), { kind: 'set-section-corner', part: 'body', corner: 40 })
|
|
38
|
+
const shape = shapeOf(round)
|
|
39
|
+
assert.deepEqual(shape.extrusion!.section, { kind: 'rectangle', size: { x: 400, z: 300 }, corner: { x: 40, z: 40 } })
|
|
40
|
+
const sharp = applyFigureAuthoring(round, { kind: 'set-section-corner', part: 'body', corner: null })
|
|
41
|
+
assert.equal(shapeOf(sharp).extrusion!.section.kind, 'rectangle')
|
|
42
|
+
assert.equal('corner' in shapeOf(sharp).extrusion!.section, false)
|
|
43
|
+
assert.match(panel, /corner: value > 0 \? value : null/, 'the field sends 0 as no rounding')
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
test('속을 비우면 기본 벽·막힌 바닥·열린 윗면의 쟁반이 되고, 끝과 벽을 하나씩 바꾼다', () => {
|
|
47
|
+
const before = shapeOf(probe())
|
|
48
|
+
assert.equal(defaultWallOf(before), 30, 'a tenth of the narrower side (300)')
|
|
49
|
+
const tray = applyFigureAuthoring(probe(), { kind: 'set-cavity', part: 'body', cavity: cavityRequestOf(before) })
|
|
50
|
+
const shape = shapeOf(tray)
|
|
51
|
+
assert.deepEqual(shape.cavity!.start, { closed: 30 })
|
|
52
|
+
assert.equal(shape.cavity!.end, 'open')
|
|
53
|
+
assert.deepEqual(Object.values(shape.cavity!.wall), [30, 30, 30, 30])
|
|
54
|
+
const thin = applyFigureAuthoring(tray, { kind: 'set-cavity', part: 'body', cavity: cavityRequestOf(shape, { wall: 5 }) })
|
|
55
|
+
assert.deepEqual(Object.values(shapeOf(thin).cavity!.wall), [5, 5, 5, 5])
|
|
56
|
+
assert.deepEqual(shapeOf(thin).cavity!.start, { closed: 30 }, 'the ends stay as they were')
|
|
57
|
+
const lidded = applyFigureAuthoring(thin, { kind: 'set-cavity', part: 'body', cavity: cavityRequestOf(shapeOf(thin), { end: { closed: 8 } }) })
|
|
58
|
+
assert.deepEqual(shapeOf(lidded).cavity!.end, { closed: 8 })
|
|
59
|
+
const solid = applyFigureAuthoring(lidded, { kind: 'set-cavity', part: 'body', cavity: null })
|
|
60
|
+
assert.equal(shapeOf(solid).cavity, undefined)
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
test('벽이 단면을 다 채우거나 모서리가 변의 절반을 넘으면, 그 까닭을 말로 한다', () => {
|
|
64
|
+
const tray = applyFigureAuthoring(probe(), { kind: 'set-cavity', part: 'body', cavity: cavityRequestOf(shapeOf(probe())) })
|
|
65
|
+
assert.equal(
|
|
66
|
+
refusal(() => applyFigureAuthoring(tray, { kind: 'set-cavity', part: 'body', cavity: cavityRequestOf(shapeOf(tray), { wall: 150 }) })),
|
|
67
|
+
ko['figure.text.section-wall-too-thick']
|
|
68
|
+
)
|
|
69
|
+
assert.equal(
|
|
70
|
+
refusal(() => applyFigureAuthoring(tray, { kind: 'set-cavity', part: 'body', cavity: cavityRequestOf(shapeOf(tray), { start: { closed: 120 }, end: { closed: 90 } }) })),
|
|
71
|
+
ko['figure.text.section-ends-too-thick']
|
|
72
|
+
)
|
|
73
|
+
assert.equal(refusal(() => applyFigureAuthoring(probe(), { kind: 'set-section-corner', part: 'body', corner: 160 })), ko['figure.text.section-corner-too-large'])
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
test('편집기는 단면 칸의 명령을 세션의 이력 하나로 돌리고, 칸은 둥글린 사각·타원 단면에만 선다', () => {
|
|
77
|
+
assert.match(editor, /<figure-section-panel[\s\S]*?@command=\$\{\(e: CustomEvent\) => this\.linkCommand\(e\.detail\.action\)\}/)
|
|
78
|
+
assert.match(panel, /if \(kind !== 'rectangle' && kind !== 'ellipse'\) return nothing/)
|
|
79
|
+
for (const lang of ['ko', 'en', 'ja', 'zh', 'ms']) {
|
|
80
|
+
const words = JSON.parse(read(`../translations/${lang}.json`)) as Record<string, string>
|
|
81
|
+
const used = [...new Set([...panel.matchAll(/'(figure\.(?:label|text)\.section-[\w-]+|figure\.label\.group-section)'/g)].map(m => m[1]!))]
|
|
82
|
+
assert.ok(used.length >= 8)
|
|
83
|
+
for (const key of used) assert.ok(words[key], `${lang} has ${key}`)
|
|
84
|
+
}
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
test('붙어 있는 것이 기대는 면을 없애는 편집은 거절되고, 그 면을 사람의 말로 부른다', () => {
|
|
88
|
+
let asset = applyFigureAuthoring(probe(), { kind: 'set-cavity', part: 'body', cavity: { wall: 10, start: { closed: 15 }, end: 'open' } })
|
|
89
|
+
asset = addFigureBox(asset, { id: 'divider', size: { x: 10, y: 100, z: 200 }, position: { x: 0, y: 0, z: 0 } })
|
|
90
|
+
asset = applyFigureAuthoring(asset, { kind: 'attach', part: 'divider', face: 'bottom', to: { part: 'body', face: 'inside-bottom' as never } })
|
|
91
|
+
const said = refusal(() => applyFigureAuthoring(asset, { kind: 'set-cavity', part: 'body', cavity: { wall: 10, start: 'open', end: 'open' } }))
|
|
92
|
+
assert.equal(said, say('figure.text.section-face-in-use', { faces: ko['figure.label.face-inside-bottom']! }))
|
|
93
|
+
})
|
package/translations/en.json
CHANGED
|
@@ -188,6 +188,19 @@
|
|
|
188
188
|
"figure.label.palette-token": "palette token",
|
|
189
189
|
"figure.label.part": "part",
|
|
190
190
|
"figure.label.part-material": "material",
|
|
191
|
+
"figure.label.group-section": "section",
|
|
192
|
+
"figure.label.section-corner": "corner radius",
|
|
193
|
+
"figure.text.section-corner-differs": "differs by axis",
|
|
194
|
+
"figure.label.section-cavity": "hollow",
|
|
195
|
+
"figure.label.section-wall": "wall thickness",
|
|
196
|
+
"figure.text.section-wall-differs": "differs by side",
|
|
197
|
+
"figure.label.section-end-closed": "closed",
|
|
198
|
+
"figure.label.section-end-open": "open",
|
|
199
|
+
"figure.text.section-face-in-use": "Not changed: something is attached to {faces}. Detach it first.",
|
|
200
|
+
"figure.text.section-dimension-linked": "This dimension follows another value. Unlink it before changing it.",
|
|
201
|
+
"figure.text.section-corner-too-large": "The corner radius is more than half the side.",
|
|
202
|
+
"figure.text.section-wall-too-thick": "The walls are too thick to leave an inside.",
|
|
203
|
+
"figure.text.section-ends-too-thick": "The closed ends are too thick to leave an inside.",
|
|
191
204
|
"figure.label.part-position": "position (centre)",
|
|
192
205
|
"figure.label.part-size": "size",
|
|
193
206
|
"figure.label.parts": "parts",
|
|
@@ -200,7 +213,7 @@
|
|
|
200
213
|
"figure.label.shown-always": "always",
|
|
201
214
|
"figure.label.shown-while": "while {control} is at least",
|
|
202
215
|
"figure.label.shown-at-least": "at least",
|
|
203
|
-
"figure.button.follow-size": "
|
|
216
|
+
"figure.button.follow-size": "Match model size",
|
|
204
217
|
"figure.text.size-declared-to-follow": "the figure size to follow was set from its parts: {x} × {y} × {z} mm.",
|
|
205
218
|
"figure.label.recipes": "recipes",
|
|
206
219
|
"figure.text.recipe-needs-a-part": "choose the part to put it on first.",
|
|
@@ -731,7 +744,8 @@
|
|
|
731
744
|
"figure.label.resize-z": "Depth (Z)",
|
|
732
745
|
"figure.label.resize-custom": "Linked to another rule",
|
|
733
746
|
"figure.label.resize-following": "Follows equipment size",
|
|
734
|
-
"figure.label.resize-advanced": "
|
|
747
|
+
"figure.label.resize-advanced": "Choose size response",
|
|
748
|
+
"figure.text.resize-all-following": "This part changes with the model size.",
|
|
735
749
|
"figure.text.resize-uniform-warning": "This equipment uses uniform scaling, which takes precedence over individual axis changes. Switching this mode is not yet available.",
|
|
736
750
|
"figure.text.preview-setup": "Not resizing as expected? Choose a part to set which dimensions follow and where it stays attached. Preview controls do not change the saved model.",
|
|
737
751
|
"figure.label.resize-part": "Part to configure",
|
|
@@ -829,6 +843,11 @@
|
|
|
829
843
|
"figure.label.model-settings": "Model settings",
|
|
830
844
|
"figure.text.fasten-editing": "Editing the current attachment: its {face} on {target}",
|
|
831
845
|
"figure.text.fasten-new": "Attach anew",
|
|
846
|
+
"figure.text.fasten-start": "Attach this part to a face on another part so they keep their relationship when either changes.",
|
|
847
|
+
"figure.button.fasten-start": "Attach to another part",
|
|
848
|
+
"figure.label.target-part-placeholder": "Choose a part",
|
|
849
|
+
"figure.text.fasten-target-first": "Choose the part to attach to first.",
|
|
850
|
+
"figure.text.fasten-edit-on-plane": "This part is connected to the model's placement reference. Detach it before attaching it to another part.",
|
|
832
851
|
"figure.button.fasten-update": "Update this attachment",
|
|
833
852
|
"figure.button.align-to-floor": "Align to the floor",
|
|
834
853
|
"figure.button.align-to-ceiling": "Align to the ceiling",
|
package/translations/ja.json
CHANGED
|
@@ -188,6 +188,19 @@
|
|
|
188
188
|
"figure.label.palette-token": "palette token",
|
|
189
189
|
"figure.label.part": "part",
|
|
190
190
|
"figure.label.part-material": "material",
|
|
191
|
+
"figure.label.group-section": "断面",
|
|
192
|
+
"figure.label.section-corner": "角の半径",
|
|
193
|
+
"figure.text.section-corner-differs": "軸ごとに異なる",
|
|
194
|
+
"figure.label.section-cavity": "中空",
|
|
195
|
+
"figure.label.section-wall": "壁の厚さ",
|
|
196
|
+
"figure.text.section-wall-differs": "面ごとに異なる",
|
|
197
|
+
"figure.label.section-end-closed": "閉じる",
|
|
198
|
+
"figure.label.section-end-open": "開く",
|
|
199
|
+
"figure.text.section-face-in-use": "変更しませんでした: {faces} に取り付けられたものがあります。先に外してください。",
|
|
200
|
+
"figure.text.section-dimension-linked": "この寸法は他の値に従います。連動を解除してから変更してください。",
|
|
201
|
+
"figure.text.section-corner-too-large": "角の半径が辺の半分より大きいです。",
|
|
202
|
+
"figure.text.section-wall-too-thick": "壁が厚く、内部の空間が残りません。",
|
|
203
|
+
"figure.text.section-ends-too-thick": "閉じた端が厚く、内部の空間が残りません。",
|
|
191
204
|
"figure.label.part-position": "position (centre)",
|
|
192
205
|
"figure.label.part-size": "size",
|
|
193
206
|
"figure.label.parts": "parts",
|
|
@@ -731,7 +744,8 @@
|
|
|
731
744
|
"figure.label.resize-z": "奥行き (Z)",
|
|
732
745
|
"figure.label.resize-custom": "別の規則に連結",
|
|
733
746
|
"figure.label.resize-following": "図形と一緒に変わる",
|
|
734
|
-
"figure.label.resize-advanced": "
|
|
747
|
+
"figure.label.resize-advanced": "サイズの反応を設定",
|
|
748
|
+
"figure.text.resize-all-following": "この部品のサイズはモデルのサイズに合わせて変わります。",
|
|
735
749
|
"figure.text.resize-uniform-warning": "この図形は全体を一つの比率で拡大します。方向ごとの変更より全体の比率が優先されます。この方式の切り替えはまだ提供されていません。",
|
|
736
750
|
"figure.text.preview-setup": "思った通りにサイズが変わりませんか? 部品を選んで、伸びる方向と付いている場所を設定してください。この画面の操作値は保存されたモデルを変えません。",
|
|
737
751
|
"figure.label.resize-part": "サイズ追従を設定する部品",
|
|
@@ -829,6 +843,11 @@
|
|
|
829
843
|
"figure.label.model-settings": "モデル設定",
|
|
830
844
|
"figure.text.fasten-editing": "現在の取り付けを編集: {face}を{target}に",
|
|
831
845
|
"figure.text.fasten-new": "新しく取り付ける",
|
|
846
|
+
"figure.text.fasten-start": "別の部品の面に取り付けると、相手の部品が変わっても関係を保ちます。",
|
|
847
|
+
"figure.button.fasten-start": "別の部品に取り付ける",
|
|
848
|
+
"figure.label.target-part-placeholder": "取り付ける部品を選択",
|
|
849
|
+
"figure.text.fasten-target-first": "先に取り付ける部品を選んでください。",
|
|
850
|
+
"figure.text.fasten-edit-on-plane": "この部品はモデルの設置基準に接続されています。別の部品に取り付ける前に外してください。",
|
|
832
851
|
"figure.button.fasten-update": "この取り付けを更新",
|
|
833
852
|
"figure.button.align-to-floor": "床に合わせる",
|
|
834
853
|
"figure.button.align-to-ceiling": "天井に合わせる",
|
package/translations/ko.json
CHANGED
|
@@ -188,6 +188,19 @@
|
|
|
188
188
|
"figure.label.palette-token": "팔레트 토큰",
|
|
189
189
|
"figure.label.part": "부품",
|
|
190
190
|
"figure.label.part-material": "재질",
|
|
191
|
+
"figure.label.group-section": "단면",
|
|
192
|
+
"figure.label.section-corner": "모서리 반지름",
|
|
193
|
+
"figure.text.section-corner-differs": "축마다 다름",
|
|
194
|
+
"figure.label.section-cavity": "속을 비움",
|
|
195
|
+
"figure.label.section-wall": "벽 두께",
|
|
196
|
+
"figure.text.section-wall-differs": "면마다 다름",
|
|
197
|
+
"figure.label.section-end-closed": "막힘",
|
|
198
|
+
"figure.label.section-end-open": "열림",
|
|
199
|
+
"figure.text.section-face-in-use": "이 면에 붙어 있는 것이 있어 바꾸지 않았습니다: {faces}. 먼저 떼어 냅니다.",
|
|
200
|
+
"figure.text.section-dimension-linked": "이 치수는 다른 값을 따릅니다. 따르기를 풀고 고칩니다.",
|
|
201
|
+
"figure.text.section-corner-too-large": "모서리 반지름이 변 길이의 절반보다 큽니다.",
|
|
202
|
+
"figure.text.section-wall-too-thick": "벽이 두꺼워 속 공간이 남지 않습니다.",
|
|
203
|
+
"figure.text.section-ends-too-thick": "막힌 끝이 두꺼워 속 공간이 남지 않습니다.",
|
|
191
204
|
"figure.label.part-position": "위치 (중심)",
|
|
192
205
|
"figure.label.part-size": "크기",
|
|
193
206
|
"figure.label.parts": "부품",
|
|
@@ -200,7 +213,7 @@
|
|
|
200
213
|
"figure.label.shown-always": "늘 보임",
|
|
201
214
|
"figure.label.shown-while": "{control} 값에 따라",
|
|
202
215
|
"figure.label.shown-at-least": "이 값 이상에서 보임",
|
|
203
|
-
"figure.button.follow-size": "
|
|
216
|
+
"figure.button.follow-size": "모델 크기에 맞추기",
|
|
204
217
|
"figure.text.size-declared-to-follow": "따라갈 도형 크기를 부품에 맞춰 {x} × {y} × {z} mm 로 정했습니다.",
|
|
205
218
|
"figure.label.recipes": "조각",
|
|
206
219
|
"figure.text.recipe-needs-a-part": "붙일 부품을 먼저 고르세요.",
|
|
@@ -724,14 +737,15 @@
|
|
|
724
737
|
"figure.text.placement-intent-wall": "벽 배치: 뒷면을 벽(Z=0)에서 지금 간격 그대로 유지하며 크기를 따라갑니다. 벽 위의 위치(X·Y)는 그대로입니다.",
|
|
725
738
|
"figure.text.placement-intent-center": "중심 배치: 지금 중심 위치를 그대로 두고 크기만 따라갑니다. 바닥·천장·벽에 붙이지 않습니다.",
|
|
726
739
|
"figure.label.resize-intent": "이 부품은 크기가 바뀔 때",
|
|
727
|
-
"figure.text.resize-intent": "
|
|
740
|
+
"figure.text.resize-intent": "지금은 고정 크기입니다. 모델 크기가 바뀔 때 이 부품도 함께 바꿀지 정할 수 있습니다.",
|
|
728
741
|
"figure.label.resize-diameter": "지름 (X·Z 함께)",
|
|
729
742
|
"figure.label.resize-x": "너비 (X)",
|
|
730
743
|
"figure.label.resize-y": "높이 (Y)",
|
|
731
744
|
"figure.label.resize-z": "깊이 (Z)",
|
|
732
745
|
"figure.label.resize-custom": "다른 규칙에 연결됨",
|
|
733
746
|
"figure.label.resize-following": "도형과 함께 변경",
|
|
734
|
-
"figure.label.resize-advanced": "
|
|
747
|
+
"figure.label.resize-advanced": "크기 반응 정하기",
|
|
748
|
+
"figure.text.resize-all-following": "이 부품의 크기는 모델 크기를 따라 바뀝니다.",
|
|
735
749
|
"figure.text.resize-uniform-warning": "이 도형은 전체 비율 유지 방식입니다. 방향별 변경보다 전체 비율 규칙이 우선합니다. 이 방식의 전환 기능은 아직 제공되지 않습니다.",
|
|
736
750
|
"figure.text.preview-setup": "크기가 기대대로 바뀌지 않나요? 부품을 골라 늘어날 방향과 붙어 있을 자리를 설정하세요. 이 화면의 조작값은 저장된 모델을 바꾸지 않습니다.",
|
|
737
751
|
"figure.label.resize-part": "크기 반응을 설정할 부품",
|
|
@@ -829,6 +843,11 @@
|
|
|
829
843
|
"figure.label.model-settings": "모델 설정",
|
|
830
844
|
"figure.text.fasten-editing": "현재 관계 수정 — {face} → {target}",
|
|
831
845
|
"figure.text.fasten-new": "새로 붙이기",
|
|
846
|
+
"figure.text.fasten-start": "이 부품을 다른 부품의 면에 붙여 두면, 상대 부품의 크기나 위치가 바뀌어도 함께 움직입니다.",
|
|
847
|
+
"figure.button.fasten-start": "다른 부품에 붙이기",
|
|
848
|
+
"figure.label.target-part-placeholder": "붙일 부품 선택",
|
|
849
|
+
"figure.text.fasten-target-first": "먼저 붙일 부품을 고르세요.",
|
|
850
|
+
"figure.text.fasten-edit-on-plane": "이 부품은 현재 모델의 설치 기준면에 연결되어 있습니다. 다른 부품에 붙이려면 먼저 붙임을 푸세요.",
|
|
832
851
|
"figure.button.fasten-update": "이 붙임 수정",
|
|
833
852
|
"figure.button.align-to-floor": "바닥에 맞추기",
|
|
834
853
|
"figure.button.align-to-ceiling": "천장에 맞추기",
|
package/translations/ms.json
CHANGED
|
@@ -188,6 +188,19 @@
|
|
|
188
188
|
"figure.label.palette-token": "palette token",
|
|
189
189
|
"figure.label.part": "part",
|
|
190
190
|
"figure.label.part-material": "material",
|
|
191
|
+
"figure.label.group-section": "keratan",
|
|
192
|
+
"figure.label.section-corner": "jejari sudut",
|
|
193
|
+
"figure.text.section-corner-differs": "berbeza mengikut paksi",
|
|
194
|
+
"figure.label.section-cavity": "berongga",
|
|
195
|
+
"figure.label.section-wall": "ketebalan dinding",
|
|
196
|
+
"figure.text.section-wall-differs": "berbeza mengikut sisi",
|
|
197
|
+
"figure.label.section-end-closed": "tertutup",
|
|
198
|
+
"figure.label.section-end-open": "terbuka",
|
|
199
|
+
"figure.text.section-face-in-use": "Tidak diubah: ada sesuatu dipasang pada {faces}. Tanggalkannya dahulu.",
|
|
200
|
+
"figure.text.section-dimension-linked": "Dimensi ini mengikut nilai lain. Nyahpaut sebelum mengubahnya.",
|
|
201
|
+
"figure.text.section-corner-too-large": "Jejari sudut melebihi separuh panjang sisi.",
|
|
202
|
+
"figure.text.section-wall-too-thick": "Dinding terlalu tebal sehingga tiada ruang di dalam.",
|
|
203
|
+
"figure.text.section-ends-too-thick": "Hujung tertutup terlalu tebal sehingga tiada ruang di dalam.",
|
|
191
204
|
"figure.label.part-position": "position (centre)",
|
|
192
205
|
"figure.label.part-size": "size",
|
|
193
206
|
"figure.label.parts": "parts",
|
|
@@ -731,7 +744,8 @@
|
|
|
731
744
|
"figure.label.resize-z": "Kedalaman (Z)",
|
|
732
745
|
"figure.label.resize-custom": "Dipautkan pada peraturan lain",
|
|
733
746
|
"figure.label.resize-following": "Berubah bersama rajah",
|
|
734
|
-
"figure.label.resize-advanced": "
|
|
747
|
+
"figure.label.resize-advanced": "Tetapkan tindak balas saiz",
|
|
748
|
+
"figure.text.resize-all-following": "Saiz bahagian ini berubah bersama saiz model.",
|
|
735
749
|
"figure.text.resize-uniform-warning": "Rajah ini membesar dengan satu nisbah, yang didahulukan berbanding perubahan setiap arah. Penukaran cara ini belum tersedia.",
|
|
736
750
|
"figure.text.preview-setup": "Saiz tidak berubah seperti dijangka? Pilih bahagian untuk menetapkan arah yang mengikut dan tempat ia dilekatkan. Nilai di sini tidak mengubah model yang disimpan.",
|
|
737
751
|
"figure.label.resize-part": "Bahagian untuk ditetapkan",
|
|
@@ -829,6 +843,11 @@
|
|
|
829
843
|
"figure.label.model-settings": "Tetapan model",
|
|
830
844
|
"figure.text.fasten-editing": "Menyunting lekatan semasa: {face} pada {target}",
|
|
831
845
|
"figure.text.fasten-new": "Lekatkan baharu",
|
|
846
|
+
"figure.text.fasten-start": "Lekatkan bahagian ini pada muka bahagian lain supaya hubungannya kekal apabila salah satu berubah.",
|
|
847
|
+
"figure.button.fasten-start": "Lekatkan pada bahagian lain",
|
|
848
|
+
"figure.label.target-part-placeholder": "Pilih bahagian",
|
|
849
|
+
"figure.text.fasten-target-first": "Pilih bahagian yang hendak dilekatkan dahulu.",
|
|
850
|
+
"figure.text.fasten-edit-on-plane": "Bahagian ini disambungkan kepada rujukan peletakan model. Tanggalkan dahulu sebelum melekatkannya pada bahagian lain.",
|
|
832
851
|
"figure.button.fasten-update": "Kemas kini lekatan ini",
|
|
833
852
|
"figure.button.align-to-floor": "Jajarkan ke lantai",
|
|
834
853
|
"figure.button.align-to-ceiling": "Jajarkan ke siling",
|
package/translations/zh.json
CHANGED
|
@@ -188,6 +188,19 @@
|
|
|
188
188
|
"figure.label.palette-token": "palette token",
|
|
189
189
|
"figure.label.part": "part",
|
|
190
190
|
"figure.label.part-material": "material",
|
|
191
|
+
"figure.label.group-section": "截面",
|
|
192
|
+
"figure.label.section-corner": "圆角半径",
|
|
193
|
+
"figure.text.section-corner-differs": "各轴不同",
|
|
194
|
+
"figure.label.section-cavity": "中空",
|
|
195
|
+
"figure.label.section-wall": "壁厚",
|
|
196
|
+
"figure.text.section-wall-differs": "各面不同",
|
|
197
|
+
"figure.label.section-end-closed": "封闭",
|
|
198
|
+
"figure.label.section-end-open": "开口",
|
|
199
|
+
"figure.text.section-face-in-use": "未更改:{faces} 上附着有其他部件。请先拆下。",
|
|
200
|
+
"figure.text.section-dimension-linked": "此尺寸跟随其他值。请先解除关联再修改。",
|
|
201
|
+
"figure.text.section-corner-too-large": "圆角半径超过边长的一半。",
|
|
202
|
+
"figure.text.section-wall-too-thick": "壁太厚,内部没有空间。",
|
|
203
|
+
"figure.text.section-ends-too-thick": "封闭端太厚,内部没有空间。",
|
|
191
204
|
"figure.label.part-position": "position (centre)",
|
|
192
205
|
"figure.label.part-size": "size",
|
|
193
206
|
"figure.label.parts": "parts",
|
|
@@ -731,7 +744,8 @@
|
|
|
731
744
|
"figure.label.resize-z": "深度(Z)",
|
|
732
745
|
"figure.label.resize-custom": "已链接到其他规则",
|
|
733
746
|
"figure.label.resize-following": "随图形一起变化",
|
|
734
|
-
"figure.label.resize-advanced": "
|
|
747
|
+
"figure.label.resize-advanced": "设置尺寸响应",
|
|
748
|
+
"figure.text.resize-all-following": "此部件会随模型尺寸一起变化。",
|
|
735
749
|
"figure.text.resize-uniform-warning": "此图形按单一比例整体缩放,整体比例优先于各方向的变化。暂不提供切换此方式的功能。",
|
|
736
750
|
"figure.text.preview-setup": "尺寸没有按预期变化?请选择部件,设置跟随的方向和附着的位置。此处的操作值不会更改已保存的模型。",
|
|
737
751
|
"figure.label.resize-part": "要设置尺寸跟随的部件",
|
|
@@ -829,6 +843,11 @@
|
|
|
829
843
|
"figure.label.model-settings": "模型设置",
|
|
830
844
|
"figure.text.fasten-editing": "编辑当前附着:{face}附着在{target}上",
|
|
831
845
|
"figure.text.fasten-new": "新建附着",
|
|
846
|
+
"figure.text.fasten-start": "将此部件附着到另一部件的面上,任一部件变化时都会保持该关系。",
|
|
847
|
+
"figure.button.fasten-start": "附着到另一部件",
|
|
848
|
+
"figure.label.target-part-placeholder": "选择部件",
|
|
849
|
+
"figure.text.fasten-target-first": "请先选择要附着的部件。",
|
|
850
|
+
"figure.text.fasten-edit-on-plane": "此部件当前连接到模型的安装基准。附着到另一部件前请先解除连接。",
|
|
832
851
|
"figure.button.fasten-update": "更新此附着",
|
|
833
852
|
"figure.button.align-to-floor": "对齐地面",
|
|
834
853
|
"figure.button.align-to-ceiling": "对齐天花板",
|