Compare commits

...

249 Commits

Author SHA1 Message Date
bherbruck 9df8837d43 Release 0.26.1 2026-10-29 06:33:09 -04:00
bherbruck 90f0353724 Release 0.26.1 (#8647)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 06:33:01 -04:00
N3MI-DG 4f3ac07aec Move/Copy: changing Move Type keeps the move made so far, and picks follow the moved body (#8746) (#8747)
* claim: #8746

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Move/Copy: changing Move Type keeps the move made so far, and picks follow the moved body (#8746)

Switching the Move Type reset the values, so the move made under the
earlier type was lost. The dialog now keeps it (`chain`) and the new type
moves the bodies on from there; params() composes the two into one
solid.move (one turn about the origin and a translation, as before).
While the new type's picks are missing, the kept move alone is made.

The new type measures from where the bodies now stand (Free Move's pivot,
Rotate's ring, round-edge centres and axes on a moved body). The picker,
the edge/face highlights, the centre marker and Rotate's axis line follow
the moving body, mid-drag too; a pick on it is taken back by the current
type's own move so it doesn't move with the move it sets. While the
triad is dragged the moved bodies' highlights are hidden and rebuilt once
on release.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 09:47:26 +00:00
ABDULLAH 710a3f8f11 Arabic: re-translate outdated strings and review the Render light and frame strings (#8752) 2026-10-29 09:47:18 +00:00
github-actions[bot] 4cee4db19b Regenerate generated files and fold pending files [skip ci] 2026-10-29 09:59:37 +00:00
semmelrinde 036d4234a1 Croatian: translate the 781 messages added since the catalog came in (#7813), the Render workspace included (#8683)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 09:29:12 +00:00
PaddleStroke 7341b8f6be Browser: Show/Hide context menu on origin axis rows (#8382) (#8724)
* claim: #8382

* Browser: Show/Hide context menu on origin axis rows (#8382)

Right-clicking an origin axis row (X, Y, Z) now opens its own menu with
Show/Hide (V), through ui.originPart and browser.visibility like the
origin planes' entry. An axis takes no sketch, so Create Sketch is not
offered.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 09:20:11 +00:00
semmelrinde 0f2ad19bdb Navigation menus: a label too long for its row ends in an ellipsis (#8700) (#8745)
The Display menu's "Perspective while orbiting, ortho on faces" ran past
the menu's edge: a menu row painted its label at full length. It is now
cut before the row's detail and check, and shown whole on hover, as a
long name in a list is.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 09:20:05 +00:00
jeromehzl 1643b74111 Sketch: selected points stay marked after the pointer moves on (#1069) (#8714)
* fix(ui): keep selected sketch points highlighted

Add persistent point selection rings while retaining constraint-state markers, with regressions for pointer selection, dialog inputs, aliases and visibility. Fixes #1069.

* Move the sketch point selection tests into the viewport overlay tests (#1069)

Run them through a frame that clears its texture uploads, as the current egui
requires, next to the other overlay tests.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Victor Santos Oliveira <56417388+Vittuu@users.noreply.github.com>
Co-authored-by: Colin Faulkingham <colinfaulkingham@Colins-Mac-mini.local>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-29 08:46:34 +00:00
github-actions[bot] 815e7de7e7 Regenerate generated files and fold pending files [skip ci] 2026-10-29 09:07:06 +00:00
Nathan Dane 3cc10acafa Render lights: uniform light list, solo and mute, and the Light editor (#6281) (#7265)
* Render lights: uniform light list, solo and mute, and the Light editor

* Render lights: Lighting and Light editors to the approved design

* Render lights: the scale-test frame carries the product light list

* Restore the stable Render light mute target on the shared eye control

* fix: validate the viewport BRDF probe with current shader dependencies

* fix: compile legacy lighting controls only for tests

* fix: scope the legacy lighting preset import to tests

* fix: reuse the merged Add Light label and translations

* test: enable the implemented Add Light radial action

* fix: restrict the legacy CPU vector editor to tests

* test: reveal Output before checking Lights browser focus

* test: use the published Browser card rectangle for Output scrolling

* test: reveal Output children before exercising editor navigation
2026-10-29 08:40:51 +00:00
N3MI-DG 06dfbc4000 Sketch Create menu: family flyouts open beside their row, on hover (#8267) (#8713)
* claim: #8267

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Sketch Create menu: family flyouts open beside their row, on hover (#8267)

A family row (Line, Rectangle, Arc, ...) opened its variants as a dropdown
below the row, covering the rows under it. The flyout now opens to the
right of its row, level with it, and on the left only when the right has
no room. Hovering a row opens it, as the context menu's Appearance
flyout does; resting on another row closes it after the shared delay.

The context menu and the Create menu share the flyout timing
(SUBMENU_CLOSE_DELAY, flyout_hover, flyout_leaving) and placement
(flyout_at) in ui_kit::menu.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 08:31:36 +00:00
semmelrinde 2d56f5d599 Construction: a vertex where another body's edge runs past stays its corner (#8650) (#8722)
A vertex pick found its named edges and then picked each again by a point
on it, among the edges of every body. At a corner where another body's
edge runs past (a wall against a side wall), all three became that edge,
and the vertex its end 3 mm away. Take each named edge's ends from the
body that has it.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 08:03:31 +00:00
ABDULLAH 2f7a9a1fc0 Arabic: review of strings added since the catalog came in (#8393)
* Arabic: consistent joint type names, rim face and tanween spelling

* Arabic: review of the Render and Edit in Place strings
2026-10-29 07:58:14 +00:00
github-actions[bot] 7ad2bbd391 Regenerate generated files and fold pending files [skip ci] 2026-10-29 08:12:10 +00:00
austin62jake c10d36a0b5 Tests: Open Linked Design waits for the part as settle waits for a load (#8716)
menu_tests::linked_component_opens_its_part_in_a_tab_and_reports_a_missing_source
gave the background open of the linked part 600 frames. Headless frames
are quick, so on a loaded machine (the whole ui-egui suite at once) the
read can take longer, and the test then found the assembly still shown.
It now waits until the part is open, up to 120 s as Harness::settle and
the edit-in-place tests wait for a load.

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-29 07:37:20 +00:00
raykholo aee57875f5 Sketch Fillet: 3D sketch lines are not offered and say they can't be filleted yet (#4160) (#4177)
* claim: #4160

* Sketch Fillet: 3D sketch lines are not offered, and say they can't be filleted (#4160)

The Fillet tool offered 3D sketch lines as picks, and sketch.fillet then
refused them with "`a` must be a line". The tool no longer offers them, and
the command refuses them with "not supported yet: filleting 3D sketch lines".

* Sketch Fillet and Chamfer: refuse all spatial sketch curves (#4160)

* Sketch corner test: give the picked curve its point (#4160)

main added a point to sketch-curve hits after this branch was written.
2026-10-29 07:22:53 +00:00
Nathan Dane d2fcab8432 Render shot editor: camera and frame controls, aspect presets, guides and frame overlay (#6281) (#7232)
* Render shot editor: camera and frame controls, aspect presets, guides and the frame overlay

* Render shot: Shot editor and Scene overview to the approved design

* Distinguish Render stage variants from native window frames

* fix: restore library inspection after clearing shot selection

* test: follow the merged Output Check navigation

* test: inspect Check without requiring a preflight result

* test: cancel Shot removal through its shared dialog action

* fix: remove obsolete Inspector stage form after editor integration

* fix: preserve Appearance Advanced when clearing Wear focus

* test: expect the dedicated Check editor from Scene overview
2026-10-29 07:03:24 +00:00
github-actions[bot] c7a1cee357 Regenerate generated files and fold pending files [skip ci] 2026-10-29 07:43:09 +00:00
semmelrinde 883f8e8e90 Save: the status line says where the design was saved (#8693) (#8705)
Saving gave no sign that it worked, while an export names the file it wrote.
After Save or Save As, the status line now reads "Saved <path>".

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 06:48:35 +00:00
github-actions[bot] a6b272dec8 Regenerate generated files and fold pending files [skip ci] 2026-10-29 07:13:25 +00:00
github-actions[bot] 2a749f4294 Regenerate generated files and fold pending files [skip ci] 2026-10-29 07:06:44 +00:00
semmelrinde 5241c64aa6 Sketch solver: eliminate row by row on slices, so the dense solve vectorises (#8631)
The dense solve updated each matrix element through bounds-checked get/add;
on slow scripted drags it was most of the time. The same operations in the
same order on row slices give bit-identical solutions, about twice as fast.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 06:39:05 +00:00
raykholo c688054db0 Canvas and Decal say where to click after the image is chosen (#4359) (#4396)
* claim: #4359

* Canvas and Decal say where to click after the image is chosen (#4359)

After picking an image the placement tool started silently, so it looked
as if nothing had happened. Show the tool's placement hint as a toast while
it waits for the click (translated), and end it once the image is placed.

* Canvas: include placement hint in viewport obstacles (#4359)
2026-10-29 06:17:35 +00:00
semmelrinde d77b0434dd English (UK): UK spellings for 43 messages that still had US ones (#8696)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 06:16:27 +00:00
N3MI-DG 0818ad0ed4 Preferences: typing in a number field edits it instead of searching (#8662) (#8663)
* claim: #8662

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Preferences: typing in a number field edits it instead of searching (#8662)

Type-to-search takes printable keys unless the focused field notes the key
sink. number_field (Autosave every, the Largest file to open limits) never
did, so its digits went into the search.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 05:32:25 +00:00
github-actions[bot] 54f74a613e Regenerate generated files and fold pending files [skip ci] 2026-10-29 06:38:44 +00:00
github-actions[bot] 74791e0220 Regenerate generated files and fold pending files [skip ci] 2026-10-29 06:29:24 +00:00
raykholo afe7dcd4e1 Allow sketch Mirror to use origin axes (#4193) (#4207)
* claim: #4193

* Sketch Mirror: an origin axis can be the mirror line (#4193)

Mirror accepted only a straight curve of the sketch. It now also takes an
origin axis that lies in the sketch plane ({axis: X|Y|Z}), projected into
the sketch as a fixed linked line, so the copies stay symmetric to it and
follow the source when it moves.

* Sketch Mirror: use current sketch store (#4193)
2026-10-29 05:08:00 +00:00
semmelrinde fed7ea0c88 Malay: translate the 264 messages the catalog lacks, Render panels and point clouds included (batch 6) (#8667)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 05:03:26 +00:00
semmelrinde dfa8ae9a60 Hungarian: translate the 264 messages the catalog lacks, Render panels and point clouds included (batch 6) (#8655)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 05:03:00 +00:00
semmelrinde 53b2f73d2e Bosnian: translate the 781 messages added since the catalog came in (#7813), the Render workspace included (#8682)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 05:02:58 +00:00
austin62jake 1dce42e744 Preferences: a drop-down's Search box keeps what is typed in it (#8675)
In Preferences, letters typed in a drop-down list's own Search box (the
Font list, a 3D mouse's button assignments) went to the Preferences search
instead, which then filtered the page, usually to "No matching
preferences", and closed the list. The Preferences search takes typing only
when no text field held the keyboard on the previous frame, and the
drop-down's Search box never said it did. On the full Interface page the
number fields' focus check covered for it; once a search hid them, as when
the Font row is found by searching for "font", nothing did.

The Search box in searchable_dropdown_with now reports that it has the
keyboard, as the Preferences search box does.

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-29 05:02:44 +00:00
semmelrinde aad3d56ec2 Serbian: translate the 781 messages added since the catalog came in (#7813), the Render workspace included (#8684)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 05:02:18 +00:00
semmelrinde 8719cc7b57 Swedish: translate the 264 messages the catalog lacks, Render panels and point clouds included (batch 6) (#8660)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 05:02:06 +00:00
semmelrinde 651addda84 French: translate the 262 messages the catalog lacks, Render panels and point clouds included (batch 6) (#8654)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 05:01:47 +00:00
github-actions[bot] dd16cc9faf Regenerate generated files and fold pending files [skip ci] 2026-10-29 06:02:10 +00:00
github-actions[bot] 6747ea0dcf Regenerate generated files and fold pending files [skip ci] 2026-10-29 05:53:14 +00:00
semmelrinde 4215fb11c2 Italian: translate the 264 messages the catalog lacks, Render panels and point clouds included (batch 6) (#8656)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 05:01:40 +00:00
semmelrinde 504fe1afcb Dutch: translate the 262 messages the catalog lacks, Render panels and point clouds included (batch 6) (#8657)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 05:01:37 +00:00
semmelrinde 7367b81ffe Romanian: translate the 264 messages the catalog lacks, Render panels and point clouds included (batch 6) (#8659)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 05:01:33 +00:00
semmelrinde 183226d2b6 Turkish: translate the 264 messages the catalog lacks, Render panels and point clouds included (batch 6) (#8661)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 04:55:04 +00:00
semmelrinde 514563187b Traditional Chinese: translate the 264 messages the catalog lacks, Render panels and point clouds included (batch 6) (#8664)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 04:54:48 +00:00
semmelrinde 5286f50fd9 Ukrainian: translate the 264 messages the catalog lacks, Render panels and point clouds included (batch 6) (#8665)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 04:54:42 +00:00
semmelrinde 46487216d0 Indonesian: translate the 264 messages the catalog lacks, Render panels and point clouds included (batch 6) (#8668)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 04:54:24 +00:00
semmelrinde 39250092a3 Galician: translate the 264 messages the catalog lacks, Render panels and point clouds included (batch 6) (#8669)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 04:54:18 +00:00
semmelrinde a1fd2be2c8 Norwegian Bokmål: translate the 264 messages the catalog lacks, Render panels and point clouds included (batch 6) (#8670)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 04:54:11 +00:00
Nathan Dane bd8cb4e6d6 Render output: Effects and Check sections, Size presets panel and the Check chip (#6281) (#7233)
* Render output: Effects and Check sections, Size presets panel and the Check tool chip

* Render output: Sampling, Effects and Check editors as child rows under Output

* fix: restrict legacy Output controls to test builds

* fix: cover status controls and reveal Effects test targets

* fix: include shared quality reviews in copied check reports

* fix: remove the obsolete Effects GPU guard after Wear integration
2026-10-29 04:39:34 +00:00
Nathan Dane c1925bb219 Render appearance: click, drag and paint to assign, Pick Up, copy and paste (#6281) (#6431)
* Render appearance: click, drag and paint to assign, Pick Up, copy and paste, and Remove

* Exclude the workspace Shots strip from dialog width checks

* Exclude the collapsed Shots control from dialog width checks

* Retain assembly cache listings and measure actual dialog bounds

* fix: handle toast button rectangles in assignment status

* fix: restrict gallery note measurement helper to tests

* test: measure assignment help at the catalogue footer

* fix: share the command revision snapshot after restacking
2026-10-29 04:33:31 +00:00
mynoc 75035ac4a5 Color picker: add Hex alongside U8 and F (#7445) (#7450)
* claim: #7445

* Color picker: add shared Hex input mode (#7445)

Accept strict RGB/RGBA Hex input while preserving exact opacity,
opaque/PBR restrictions, invalid drafts and existing U8/F behavior.

Keep explicit English fallback entries for the three new Hex messages
in Arabic and Hebrew, which final integration main now requires as
complete catalogs. No Arabic or Hebrew translations are claimed.

The user authorized this feature-only commit after full cargo xtask ci
stopped at the pre-existing geometry nonminimal_bool lint. The same
failure was reproduced without this patch at the published claim and
main. No unrelated lint fix or suppression is included.

* i18n: cover complete catalogs for Hex picker (#7445)

Add the three Hex message keys to Vietnamese in the feature's pending
locale file. Keep the unchanged English source values as explicit
fallbacks; no Vietnamese translations are claimed.

Audit the complete-catalog set (ar, he, ja, vi, zh) rather than only
the first catalog reported by CI. Preserve the existing completeness
test and all picker/Appearance code.

The completeness regression changes from red to green. Full local CI
and wasm checks remain blocked by failures independently reproduced
in clean upstream main; no unrelated fixes or suppressions are added.

* Appearance: use the shared opacity-aware color picker in Render (#7445)

Route the merged Render Appearance editor through the UI-kit picker,
passing exact opacity only for non-PBR looks. Keep a non-editable mixed
label and treat explicitly accepting the first color as a mixed edit.

Remove the external Hex field and duplicate parser, replace its gallery
entry with the shared mixed-aware picker, and update the control contract.

Preserve existing regression assertions and add actual Render UI tests
for alpha edits, precision, invalid drafts, PBR rejection and mixed edits.

Full local CI and wasm were run before this commit and remain blocked
by the separately reproduced unchanged upstream geometry lints and
prefs.bytes wasm error. No unrelated fixes or suppressions are included.

---------

Co-authored-by: mynoc <298906611+mynoc-96@users.noreply.github.com>
2026-10-29 04:33:10 +00:00
github-actions[bot] ae47ed342b Regenerate generated files and fold pending files [skip ci] 2026-10-29 05:24:00 +00:00
Mike111177 03cf8f3e90 Configuration table: a filter in the Add Column menu (#8086) (#8088)
* claim: #8086

* Configuration table: a filter in the Add Column menu (#8086)

The + menu listed every parameter, feature suppression and body
material/appearance with no way to narrow it. A filter field now sits at
the top, takes focus when the menu opens, narrows the entries and the Face
Appearance submenu as typed, picks a lone match on Enter and clears when
the menu closes. A click into the field keeps the menu open (plus_header
closes on outside clicks; entries close it themselves), and the list keeps
its full height after the filter has emptied it once.

New kit element ui_kit::menu_filter (glyph, frameless editor, rule) so the
field does not read as an entry; gallery, i18n guard and docs/ui-kit.md
updated. Regression test in manage_dialogs_tests.
2026-10-29 04:20:42 +00:00
MarkusRe 0baf49b25f Windows: never load a dxcompiler.dll found on PATH; FXC unless DXC ships beside the app (#6756) (#7923)
* claim: #6756

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Windows: never load a dxcompiler.dll found on PATH; FXC unless DXC ships beside the app (#6756)

wgpu's Dx12Compiler::Auto loads dxcompiler.dll by name, so Windows takes the
first one on PATH. SolidCraft ships none, and DXC 1.8.2505 from other programs'
folders (Obsidian, NVIDIA SDK Manager) crashed every start with
EXCEPTION_ILLEGAL_INSTRUCTION during the viewport shader compile.

solidcraft_gpu::dx12_compiler() now chooses: WGPU_DX12_COMPILER as wgpu reads
it when it names a compiler; otherwise DXC from the dxcompiler.dll beside the
program, by its full path, else FXC. The window, the headless/CLI instance and
the test helpers start with it, and dx12_compiles_with_fxc follows it.
WGPU_DX12_COMPILER=dxc keeps the old lookup.

Fixes #6756

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 04:14:57 +00:00
github-actions[bot] 9bcda52408 Regenerate generated files and fold pending files [skip ci] 2026-10-29 04:45:23 +00:00
semmelrinde f4e52c4d3e Sketch: points tied only through a removed curve's end stay tied (#8640)
* Sketch: points tied only through a removed curve's end stay tied

Removing a curve removed its orphaned end points with their constraints, so
two points made coincident with such an end lost their tie although they
still met: two rectangles' corners on one arc end came apart when the arc
was trimmed. They are now tied to each other before the point goes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Sketch: keep the tie test with the other trim tests

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 04:14:22 +00:00
semmelrinde 2da969cf5c Czech: translate the 264 messages the catalog lacks, Render panels and point clouds included (batch 6) (#8653)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 04:14:04 +00:00
NOWN-DEV dd8308e835 Naming: a face swept from one of many sketch curves is named without measuring every curve (#8643)
Naming a face swept from a sketch flattened every curve of the sketch to
a polyline and measured its distance to each, for every face. On a sketch
with thousands of curves (a sheet with many cut-outs) that grew with
curves times faces. The curves are now flattened once per feature, each
with its box, and a curve whose box is farther than the best distance so
far is not measured.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 04:12:56 +00:00
Colin Faulkingham 6f9788ccba Browser: move a component under another by drag and drop (#5164) (#8532)
* claim: #5164

* Browser: drag a placement row onto another to move it into that component (#5164)

---------

Co-authored-by: Colin Faulkingham <colinfaulkingham@Colins-Mac-mini.local>
2026-10-29 04:01:21 +00:00
github-actions[bot] 46a6686380 Regenerate generated files and fold pending files [skip ci] 2026-10-29 04:15:14 +00:00
CaRLymx ec76068a0b Spanish (es-ES): catch up with en.json (#6899)
* Spanish (es-ES): catch up with en.json

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Navigation preferences: name the Shift key through the catalog

Spanish now translates the key name, so the page painted it in English.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: bherbruck <brennen.herbruck@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 03:42:24 +00:00
Colin Faulkingham 99664a4d35 fix: keep expression move distances on world axes (#7234) (#8508) 2026-10-29 03:39:39 +00:00
froglemonade2 e55eff7c5d Orbit about the cursor: on an edge or sketch line, turn about the point under the cursor (#7356) (#7358)
* claim: #7356

* Orbit about the cursor: on an edge or sketch line, turn about the point under the cursor (#7356)

With Orbit around: point under the cursor, a drag that starts on a body
edge turned about the edge's middle, which on a long edge is far from
the cursor, and one that starts on a sketch curve turned about the
centre of the bodies in view. Edge and sketch curve hits now carry the
point under the cursor, which the pick already measured, and
pivot_under uses it. An edge hit's `mid` is unchanged, so selections
still record the edge's middle.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 03:36:05 +00:00
austin62jake d8d22cd52a 3MF export: a component's bodies as one object with parts (#8139) (#8187)
* claim: #8139

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019FAWPuFoh9qxn2uS2j53QZ

* 3MF export: a component's bodies as one object with parts (#8139)

file.export and file.save_mesh wrote every body as its own 3MF object and
build item, so a slicer loaded a multi-body part as separate objects and
could arrange them apart on the bed. With objects: "component", each placed
component that holds two or more bodies is written as one object whose
<components> are its bodies' meshes, built once, so PrusaSlicer, OrcaSlicer,
Bambu Studio and Cura load it as one object with a part per body, each of
which can take its own filament. The design's own bodies, and a component
with a single body, stay objects of their own. The default (objects: "body")
writes the same file as before.

- io: model_xml_parts and write_3mf_parts write the parts; export_with_parts
  maps body names to them. model_xml_with and export_with_quality give the
  same output as before.
- engine: mesh_parts reads `objects` (component is refused for formats
  other than 3MF); component_parts groups the placed bodies by placement,
  each part named after its occurrence (Bracket:1, Bracket:2).
- file.save_mesh passes the parts on when it also sends the file to a slicer;
  file.send_to_slicer's own folder export is unchanged.

Fixes #8139.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019FAWPuFoh9qxn2uS2j53QZ

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-29 03:35:38 +00:00
Nathan Dane 40ff251e5f Render wear: a Wear row and editor for the aging layers (#6281) (#7459)
* Render wear: a Wear row and editor for the aging layers

* test: read Wear header text from accessibility label values

* test: restore body picks for Wear header recovery assertions
2026-10-29 03:29:10 +00:00
github-actions[bot] 081c4bca73 Regenerate generated files and fold pending files [skip ci] 2026-10-29 03:40:32 +00:00
Nathan Dane de5cee9bf1 Viewport status item: UI-kit element and row (#8544) (#8553)
* claim: #8544

* Add reusable viewport status items and fixture (#8544)
2026-10-29 03:02:43 +00:00
Nathan Dane 09bf603588 Render environment editor: rotation, intensity, backdrop colour and ground (#6281) (#7231)
* Render environment editor: rotation, intensity, backdrop colour and ground through render.environment.set

* Render environment editor: rotation ring in the view with one undo step per drag

* Render environment: Source, orientation, backdrop, ground and atmosphere sections

* Keep segmented controls inside their allocated rows

* fix: compile legacy environment controls only for tests
2026-10-29 02:49:16 +00:00
semmelrinde f071f00155 Sketch Trim: an end at a place several curves cut is tied to the one with an end there (#8612) (#8628)
Where several curves cut at one place, trim pinned the new end onto the
first of them. At the touch point of two circles that was a rectangle side
passing through, and once a later trim removed the side the arc ends were
loose: a trimmed dog bone kept two untied ends.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 02:45:35 +00:00
raykholo 8fb452b05e Report a bug: always offer a way to submit (#5463) (#5615)
* claim: #5463

* Report a bug: always offer a way to submit (#5463)

* Keep report strings pending and update the focus regression (#5463)
2026-10-29 02:43:49 +00:00
semmelrinde e4cfbbd0c3 Sketch Coincident: refuse a line's two ends, as MidPoint refuses its own end (#8611)
* Sketch Coincident: refuse a line's two ends

Making a line's two ends coincident shrinks it to a point; a Parallel or
Perpendicular on it afterwards has no direction to hold and a later solve
could throw points far away while reporting solved, as with a line's own end
as its midpoint (#8562).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Sketch Coincident: keep the own-ends test with the other Coincident tests

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 02:21:05 +00:00
Colin Faulkingham 746e1c633d Dialogs: wrap status and refusal messages at full width (#8455) (#8460)
* claim: #8455

* fix(ui): wrap dialog status and refusal messages (#8455)
2026-10-29 02:16:56 +00:00
The Nomad 674ef84b53 Add History playback to the Inspect ribbon (#3693) (#7853)
* claim: #3693

* Fix timeline playback to show each rebuilt feature

* Move History playback into the Inspect ribbon

* Refuse Play History up front when playback couldn't run

Starting Play and the per-frame check that stops it were looking at
different app state, so Play could be accepted during an apply, a delete
check or queued history work and then stop silently on the next frame.
Both now use one playback_blocked check.

The UI also reads the engine's PlaybackAction as the typed enum instead of
matching strings, so a bad reply is an error rather than a quiet toggle.

* Put Play History in the History controls

History now shows five controls in transport order: start, previous,
play, next, end. Play runs timeline.play, so it turns into Stop while
playback runs, same as the ribbon button and the shortcut.

It's on by default (#3688, #3740, #4216). Anyone who wants the old four
controls back can right-click them and pick Hide Play Button, or clear
history_play_button under Preferences > Interface. In a named vertical
History too narrow for five buttons beside its grip, Play is left to the
ribbon rather than overlapping the grip.

* Draw the History Play button as a plain play/pause glyph

The Play button in the History controls now uses the same drawn glyphs as
its neighbours: a filled triangle, and two bars while History plays. The
triangle is bigger than the step arrows so it doesn't read as Forward.
The ribbon command keeps its timeline_play and timeline_stop icons.

* Keep the playback changes clear of PRs queued ahead

Several PRs in the merge queue touch the same lines, so this moves ours
aside without changing behaviour:

- history_play_button and its reset-test row sit with the other History
  preferences, not beside view_confirm_corner (#7248 adds status_bar there).
- History keeps main's history_transport_width() for four controls (#6430
  and #7459 call it); the Play button's count uses history_controls_width.
- A new or opened document stops playback after dim_view::cancel(), clear
  of the line #7819 adds after reset_chat.
- The Play/Stop label swap moves from interactive_command_info, which #7906
  rewrites, into the ribbon's command_info.

* Stop playback after the command completes, clear of #6433

#6433 rewrites the session.execute line in execute_command, and our playback check sat right under it, so the queue couldn't merge the two. Checking the revision after command_completed does the same job a couple of lines later.

---------

Co-authored-by: cfaulkingham <colin.faulkingham@gmail.com>
2026-10-29 02:14:53 +00:00
Frank be757154d6 fix(sketch): join nearby profile endpoints (#7269)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-10-29 01:54:56 +00:00
PaddleStroke 3b983dc550 Viewport: vertex markers where edges are drawn (#7834) (#8119)
* claim: #7834

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Viewport: vertex markers where edges are drawn (#7834)

Each body's vertices (the ends of its pickable edges, once each) show as
small screen-space squares in the edge colour in the styles that draw
edges: shaded with edges, wireframe, and shaded with hidden edges, where
hidden vertices show faintly like hidden edges. Plain shaded draws none.
A marker is a lifted line from the vertex to itself in the body's block,
so it is instanced with the edges, cached with them, and depth-tested
like a highlight band. The existing vertex hover ring stays on top.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Viewport tests: count edge segments apart from vertex markers (#7834)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Vertex markers: an option, off by default (#7834)

Adds the Vertex markers preference (Preferences > Graphics, off by default) and draws the dots only when it is on.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: bherbruck <brennen.herbruck@gmail.com>
2026-10-29 01:53:01 +00:00
github-actions[bot] b5217b1e86 Regenerate generated files and fold pending files [skip ci] 2026-10-29 03:07:55 +00:00
github-actions[bot] 5dccc3d978 Regenerate generated files and fold pending files [skip ci] 2026-10-29 03:00:55 +00:00
semmelrinde 800b6b4486 Saved model: read text records up to 16 MiB, so a long warning keeps fast opening (#8541) (#8607)
Open refused a saved model whose text records (a feature's warning, a body or
sketch name) held more than 65,536 bytes, although Save writes them, so such a
design was evaluated again on every open.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 01:52:21 +00:00
semmelrinde 11f208f665 Viewport: cut dashed lines to the view, so a huge distance can't fill the memory (#8540)
* Viewport: cut dashed lines to the view, so a huge distance can't fill the memory

epaint makes one shape per dash and steps along a line in f32. The
viewport's dashed lines (the Extrude taper handle, Measure's legs, the
fillet radius guide, the inference and snap guides, a sketch text's
frame) were dashed over their whole projected length. With an Extrude
distance of 1e9 mm the taper line was billions of points long: the
frame never finished and filled the memory within a second.

`viewport::dashed_line` dashes a line that lies in view exactly as
before, and cuts one that reaches far off screen to the view (grown by
two dash periods) first, keeping its dashes in phase with its start.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Viewport: compute a cut dashed line's ends in f64

A line a trillion points long lost its cut ends in f32: they collapsed to one point, and the part in view drew nothing. The new test caught it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 01:27:34 +00:00
phanoob ba52632985 Tabs: Ctrl+Tab shows the next design tab, Ctrl+Shift+Tab the previous one (#8565) (#8597)
Two new commands, view.next_tab and view.previous_tab, with Ctrl+Tab and
Ctrl+Shift+Tab as their default keys: they appear on the Keyboard Shortcuts
page and can be rebound or cleared like any other. The window steps along the
tab strip and goes round at either end; one design alone stays as it is, and
a "save changes?" prompt keeps its tab shown. The engine only echoes the
step (no design edit, no undo step); engine.batch refuses them like the
other steps that go to another design.

Co-authored-by: Phanoob <phanoob@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 01:25:12 +00:00
bherbruck 4571701179 Embed a Windows version resource in solidcraft.exe (#8378)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 01:21:02 +00:00
raykholo 4c6382c0a3 PR checks: a read-only token gets a notice from the label job, not a failure (#7850) (#7851) 2026-10-29 01:00:15 +00:00
raykholo 0e01dc9bad Pattern counts: say when a parameter has a length unit, and refuse fractional counts (#5066) (#5337)
* claim: #5066

* Pattern counts: name a length-unit parameter, refuse fractional counts (#5066)

A count parameter created with a length or angle unit now gets an error
that names it and says to set its Unit to none. A count that evaluates to
a fraction is refused instead of being rounded silently.
2026-10-29 01:00:10 +00:00
bherbruck c0d84ad460 Dependencies: security updates (2026-10-28) (#8588)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 00:30:53 +00:00
yhamil04 af9772fb3c Browser: mesh bodies get their own icon and a body-kind tooltip (#6907) (#7059)
A mesh body's row (an imported STL, 3MF, OBJ, ...) now shows a new
mesh_body icon, a triangulated cube in the mesh accent, instead of the
solid body's grey cube. Hovering a body row says Mesh body, Surface body
or Solid body. Body::is_mesh() decides; nothing new is saved.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 00:26:01 +00:00
w0prup 3449f0def2 Wayland: trackpad pinch zooms the view (#7744) (#8023)
* claim: #7744

* Vendor winit 0.30.13 with Wayland touchpad pinch and rotation gestures

The 0.30 Wayland backend never binds zwp_pointer_gestures_v1, and
WindowEvent::PinchGesture / WindowEvent::RotationGesture only come from the
macOS and iOS backends, so a trackpad pinch produces no input at all on
Linux and Wayland (two-finger scroll still works, since X11/XWayland
reports it as a wheel). egui-winit already maps the events to
egui::Event::Zoom and navigation::handle already zooms the camera from
that, so the Wayland backend was the only missing piece.

Upstream the gesture support is part of winit 0.31 (rust-windowing/winit#4338),
which eframe 0.36 cannot use while it still requires winit 0.30, and the
0.30 backport rust-windowing/winit#4778 was closed unmerged. So ship the
same fix locally, upstream-style-applied and stripped of example and test
targets, with its unit tests for the gesture state machine kept under
cargo test -p winit --lib -- pointer_gesture:

- src/platform_impl/linux/wayland/seat/pointer/pointer_gesture.rs: bind
  the global (versions 1..=3), one pinch gesture object per pointer,
  destroyed before the pointer is released; begin/update/end become the
  two events for the window the gesture began over. Two fingers only;
  the protocol's scale is relative to the gesture's beginning, so the
  event carries the change since the previous update; rotation is
  negated to winit's counterclockwise degrees; a non-finite scale is
  dropped, and so are updates of a gesture whose begin we never saw.
- seat state wiring: bind the global, track and drop the gesture object.
- wayland-protocols' unstable feature, platform notes on both events,
  changelog, patch-section entry in Cargo.toml, vendor/README, and
  Linux/Wayland notes in the troubleshooting guide and the UI tour.

Retire this vendoring once an eframe release consumes winit 0.31 or
later; the cleaned branch is kept as
https://github.com/purp0w/winit/tree/wayland-pinch-gestures.

* ci: retrigger after flaky occurrence-cache test

---------

Co-authored-by: Francisco das Chagas Danta Filho <dev@dantas-filho.me>
2026-10-29 00:09:02 +00:00
github-actions[bot] 0889ef9dfc Regenerate generated files and fold pending files [skip ci] 2026-10-29 02:11:11 +00:00
semmelrinde 1937dea04b Sketch constraints: refuse one curve picked twice for a two-curve constraint (#8577)
Parallel, collinear, equal or concentric of a curve with itself was added
as a constraint that always holds; perpendicular or tangent to itself was
refused as geometry that can't move. These six now refuse one curve
picked twice, as Coincident already does for a point, and leave the
sketch as it was. Constraints already in a design are untouched.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 23:52:44 +00:00
Nathan Dane a545f32113 Render stage panels: Surfaces and references, Studios and environments, and the review dialogs (#6281) (#7999)
* Render stage panels: Surfaces and references, Studios and environments, and the review dialogs

* fix: complete stage panel translations and gallery tile fields

* fix: exercise stage catalog sizing in the floating layout

* fix: retain the Appearance library selection query
2026-10-28 23:49:39 +00:00
github-actions[bot] 937d5f0176 Regenerate generated files and fold pending files [skip ci] 2026-10-29 01:43:00 +00:00
bherbruck 409ab1ed45 Release 0.26.0 (zip 9.1.3) 2026-10-28 19:41:38 -04:00
dependabot[bot] 00df48dfe4 Bump zip from 9.0.4 to 9.0.5 (#8572)
Bumps [zip](https://github.com/zip-rs/zip2) from 9.0.4 to 9.0.5.
- [Release notes](https://github.com/zip-rs/zip2/releases)
- [Changelog](https://github.com/zip-rs/zip2/blob/master/CHANGELOG.md)
- [Commits](https://github.com/zip-rs/zip2/compare/v9.0.4...v9.0.5)

---
updated-dependencies:
- dependency-name: zip
  dependency-version: 9.0.5
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-28 19:41:29 -04:00
bherbruck 5e03fe2f4b Release 0.26.0 2026-10-28 19:32:17 -04:00
bherbruck 0656819123 Release 0.26.0: fold point-clouds into format 43 (#8579)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 19:32:15 -04:00
github-actions[bot] 926d753a40 Regenerate generated files and fold pending files [skip ci] 2026-10-28 23:29:43 +00:00
semmelrinde 05a7a4fef9 Traditional Chinese: translate the 56 messages main gained since batch 1 (batch 3) (#8365)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 23:28:02 +00:00
github-actions[bot] c03dccabb6 Regenerate generated files and fold pending files [skip ci] 2026-10-28 23:20:35 +00:00
bherbruck 776653dd7c Release 0.26.0 (#8574)
Fold the pending design format change (linked-body-properties) into format 42.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 19:17:37 -04:00
N3MI-DG 33c27106ff Pick by the body's own size, not the camera's distance (#7919) (#7920)
* claim: #7919

* Pick by the body's own size, not the camera's distance (#7919)

The occlusion test that decides whether an edge or vertex is hidden by the
face in front allowed a slack of `scene_radius(app) * 0.02`, and
`scene_radius` ends with `.max(app.cam.half_height() * 2.0)`: in an
orthographic view that is `0.016 x camera distance`. Zooming out grew the
slack without bound until a whole body fitted inside it and every edge behind
the front face counted as visible, and edges and vertices are offered before
faces, so they won the pick. Cutting the slack from the scene also gave a
small part in a large assembly a tolerance many times its own size.

`pick_slack` now takes a size and returns the mesh's own chord tolerance with
room to spare, `DisplayQuality::Coarse.chord(size) * 4.0`: a facet sits at
most a chord tolerance inside its surface, and that tolerance is already a
fraction of the body's size, so the slack no longer moves when the camera
does. Each body is tested with its own bounding box, which the loop already
holds. `view.pick` does the same, so an agent's pick still matches a click on
the same pixel. Sketch profiles and origin planes belong to no body and keep
a scene-level value, `scene_pick_slack`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-10-28 23:15:09 +00:00
semmelrinde 17807ab6dc Sketch MidPoint: refuse a line's own end as its midpoint (#8562)
A line's own end held at its middle shrinks the line to a point. The
solve accepted that, and a later angle, tangent or parallel on the line
had no direction to hold: its points went millions of millimetres away
while the sketch still reported solved. MidPoint now refuses the pick,
saying why, and leaves the sketch as it was. Constraints already in a
design are untouched (only the command refuses).

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 23:11:05 +00:00
momysnow 1445b5a4f0 Extend: pick two curves to extend both to where they meet (#4750) (#8392)
* claim: #4750

Co-Authored-By: Claude <noreply@anthropic.com>

* Extend: pick two curves to extend both to where they meet (#4750)

`sketch.extend` gains a second form: `curves: [a, b]` names two lines or
arcs, with an optional `at: [[x,y],[x,y]]` naming the end of each to grow
(default: the end nearest the meeting point). Both grow along their own
line or circle to where they cross and the two ends are joined with one
Coincident, in one undo step. `moved` is the joined end's id.

- Where two crossings are possible (line and arc, two arcs) the one with
  the least total growth is used; a tie is refused.
- A curve that already reaches the point does not grow. An end held by
  other geometry or a constraint stays and gets a new line or arc.
- Parallel or collinear lines, curves that never meet, a point behind the
  chosen end, the same curve twice, splines, ellipses, infinite lines,
  offset geometry and malformed `curves`/`at` are refused with no change.
- The single-curve form is unchanged; its code is shared through
  `grow_line` / `grow_arc`.

Canvas: in the Extend tool, Shift-click two curves. Shift goes through
the tool modifier registry as the new `extend_pair` action, and Extend
turns off Shift's midpoint snap. Escape drops a pending first pick. The
sketching guide describes the gesture.

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-28 23:10:24 +00:00
github-actions[bot] 066de1b005 Regenerate generated files and fold pending files [skip ci] 2026-10-29 01:07:21 +00:00
github-actions[bot] d6876d6e67 Regenerate generated files and fold pending files [skip ci] 2026-10-29 00:58:24 +00:00
raykholo a1e7337d3c Toasts: one stack in the view's bottom-right corner, one width, buttons as in dialogs (#7893) (#7959)
* claim: #7893

* Toasts: one stack in the view's bottom-right corner, one width, buttons as in dialogs (#7893)

* Control protocol: toast_place in the sorted ui.prefs list (#7893)

* Toasts: a sketch test clears the status notice before clicking the view's corner (#7893)

The test's line end lands in the bottom-right corner, where notices now stack
and take clicks as they did at the bottom centre; the test is about the circle.

* Toasts: the pattern scenario's circle sits clear of the view's corner (#7893)

After the refit, a circle at y 0 landed in the bottom-right corner, where the
tool's prompt now stacks and takes clicks. The circle moves 40 mm up; the
pattern it checks is the same.
2026-10-28 22:35:24 +00:00
semmelrinde 951b5eb1d3 Indonesian and Traditional Chinese: the Appearances panel's 27 Render messages (#8336)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 22:27:28 +00:00
Colin Faulkingham 5221103369 Components: a component named like the design is reachable by name (#8358) (#8423)
* claim: #8358

* Components: a component named like the design is reachable by name (#8358)

Document::find_component resolved the design's own name to the root component (id 0) before
searching the component list, so a component that shares the design's name was unreachable by
name: appearance.assign reported `no component `CurtainRailPlug`` (the same lookup serves every
command that takes a component by name).

An exact component name (or component id) match now wins over the design-name fallback; "0" and
"root" still always mean the design.

Regression test: a_component_named_like_the_design_takes_its_appearance_by_name (fails on main
with the reported error, passes with the fix).
2026-10-28 22:07:58 +00:00
JK3D 9b7a6ea04d History: feature folders get their own symbol (#8521) (#8522)
* claim: #8521

* feat: give History feature folders their own symbol

A folder of features in the History on the left drew the same folder icon
as the Browser's folders. It now draws feature_group, a pile of history
chips with the front one in blue, and so do Add to New Folder and Remove
from Folder in the History's menu. Other uses of folder keep it.
2026-10-28 22:04:12 +00:00
Lars Jansen fe265d74b1 Sketch: draw conflicting curves and points in the conflict colour (#7244) (#7249)
* claim: #7244

* feat(sketch): draw curves, points and constraints that conflict in their own colour (#7244)
2026-10-28 22:03:54 +00:00
NOWN-DEV eb29c4b2d8 Sheet metal feature commands: typed parameter contracts (#6581) (#6582)
* claim: sheet.* typed parameter schemas

* Sheet metal feature commands: typed parameter contracts

sheet.flange, sheet.perforate, sheet.hem, sheet.fold, sheet.unfold, sheet.refold and
sheet.convert read their parameters by hand, so a misspelt key or a value of the wrong
shape was ignored or failed late, and describe_command had only prose for them.

Each now has a contract in schema/sheet.rs, checked in front of the unchanged handler,
and returns FeatureResult. The values no shared type fits (sheet-edge points, an edge
flange's edges, a fold's line and fixed point, the flange type, the positions, the
relief shape and the perforation pattern) get types that call the handlers' own
readers, split out of cmd/sheet.rs, and give their messages. The rule's values
(thickness, K-factor, bend radius, reliefs) stay out of the contracts: the handlers
refuse them, and strict refuses them as unknown keys.

A test passed a nested `base` object whose `sketch` the flange never reads; it now
names the sketch at the top level.

Part of #2829 (#6581).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Sheet metal contracts: a further bend's angle stays as lenient as before

The flange handler reads a `then` bend's `angle` that is no expression
(`true`, a list) as left out and bends it 90 degrees. The rebased
contract had moved that check into the shared reader, so the handler
refused such a call even with the check off.

The reader is back to the handler's behaviour, and `ThenSteps` is the
stricter one, as the schema guide asks: warn reports such an angle and
strict refuses it. Tests cover the reader's leniency, the type's
refusal and the three check levels on one flange.

Part of #2829 (#6581).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 22:01:35 +00:00
github-actions[bot] f1ab19422b Regenerate generated files and fold pending files [skip ci] 2026-10-29 00:30:57 +00:00
github-actions[bot] 0a187f5cb1 Regenerate generated files and fold pending files [skip ci] 2026-10-29 00:21:59 +00:00
tr1pp4 7adbe00377 History in the browser: a History layout that lists each component's history in the browser (#7709) (#7710)
* Browser: the history in the browser, as a History layout (compact mode)

Settings > Interface > History gains "In browser" (view.history_layout dock: browser):
neither timeline is shown, and each component's History folder lists its sketches and
features in history order with the marker. Dragging the marker rolls the history back
through timeline.roll_to; Find in Timeline reveals the feature in the browser.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Browser history: sketches listed under their feature as in the vertical History

With Sketches: Under their feature, the history in the browser (compact mode) lists each
sketch under the first feature built from it, through the shared history_rows (#6494)
without reference rows: same rule, same fold key, so switching the History layout keeps
what is open. A drop above a row rolls back its listed sketches with it. Selecting a feature
lights the rows of its sketches, and selecting a sketch lights the features built from it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Browser: with the history in the browser, the Sketches folder starts closed

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Browser history: sketch rows have the eye of their Sketches folder row

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* History in the browser: Arabic, Hebrew and Vietnamese for the layout's name

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 21:49:21 +00:00
semmelrinde 0243afdc0b Dialogs: scroll a long refusal into view with its Create Issue (#8454) (#8506)
* Dialogs: scroll a long refusal into view with its Create Issue (#8454)

A dialog's refusal comes last in its fields. When the fields fill the
dialog, the refusal sits under the fold: an Extrude Cut that the kernel
refused showed only its first line, "boolean Cut: the operation failed: no",
and no Create Issue. The dialog now scrolls a new refusal into view once:
a refusal on OK at once, a preview's once no field is being typed in, so a
field never moves away while it is typed in.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Dialogs: decide the reveal in one function and test it

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 21:48:09 +00:00
raykholo 8e6a107f6e Lists many PRs add to: no written lengths, one file per theme (#7747) (#7898)
* Lists many PRs add to: no written lengths, one file per theme (#7747)

* xtask lists: the fixed-table allowlist in order, each with its own reason

* Lists: the wide-character blocks and the drawing scale presets as slices too (#7747)

* Lists: the drawing units test reads UNITS as a slice (#7747)
2026-10-28 21:33:34 +00:00
semmelrinde 4ad18407dc Paste: leave copied body transfers out, so the design still opens (#8478)
A copied body transfer was pasted like any feature and given the target
component as its owner. A transfer belongs to the component it moves bodies
to, so the saved design was refused on open ("body transfer owner must match
its destination"), and a pasted transfer had nothing to move anyway: the
copies go into the component they are pasted into. Paste now leaves body
transfers out and says so in its notices; a clipboard of only transfers is
refused.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 21:29:05 +00:00
semmelrinde 5695785e3e Dutch: translate the 117 messages the catalog still lacks (batch 4) (#8486)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 21:26:12 +00:00
semmelrinde c2e1dbe6e4 Italian: translate the 125 messages the catalog still lacks (batch 4) (#8491)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 21:26:00 +00:00
Logan Night bda5f69c5c Preferences: reverse trackpad orbit direction (#8410) (#8484)
* claim: #8410

* Preferences: reverse trackpad orbit direction (#8410)

Add "Reverse trackpad orbit direction" under the pan settings in
Preferences > Navigation. orbit_reverse defaults off, so older settings
files load unchanged, and turns the Shift + two-finger orbit the other
way on both axes, as natural scrolling flips both. Pan, zoom and mouse
orbiting are untouched. Labels in en, ar, de, he, ja, ko, vi and zh as
a pending locale file; orbit_reverse in the control protocol's sorted
settings list.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 21:25:24 +00:00
semmelrinde 78d05e35bb Malay: translate the 125 messages the catalog still lacks (batch 4) (#8492)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 21:25:18 +00:00
semmelrinde 70fdc27703 Czech: translate the 121 messages the catalog still lacks (batch 4) (#8485)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 21:24:15 +00:00
semmelrinde b650d7b49b French: translate the 121 messages the catalog still lacks (batch 4) (#8487)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 21:24:12 +00:00
semmelrinde 883aff8816 Traditional Chinese: translate the 125 messages the catalog still lacks (batch 4) (#8498)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 21:23:58 +00:00
semmelrinde 43cf7774aa Galician: translate the 125 messages the catalog still lacks (batch 4) (#8488)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 21:23:54 +00:00
raykholo 29749c73f3 Report missing translations for complete catalogs before review (#8542) (#8543)
* claim: #8542

* CI: report missing translations for complete catalogs before review (#8542)

`cargo xtask i18n --check` already reads the pending locale files and fails
when a complete catalog lacks an English message, but no workflow ran it, so
the gap surfaced only in the full test run after approved-for-ci. It now runs
in Format and repository checks, and CONTRIBUTING names the complete catalogs.
2026-10-28 19:51:47 -04:00
github-actions[bot] 05081e8428 Regenerate generated files and fold pending files [skip ci] 2026-10-28 23:50:48 +00:00
semmelrinde 9b8be3b8a5 Romanian: translate the 121 messages the catalog still lacks (batch 4) (#8494)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 21:23:47 +00:00
semmelrinde d755b70e25 Swedish: translate the 121 messages the catalog still lacks (batch 4) (#8497)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 21:23:33 +00:00
semmelrinde 0c4673a89d Russian: translate the 125 messages the catalog still lacks (batch 4) (#8495)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 21:23:29 +00:00
semmelrinde 1b000c92f3 Hungarian: translate the 121 messages the catalog still lacks (batch 4) (#8489)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 21:23:28 +00:00
semmelrinde eb8cfdf8cc Indonesian: translate the 125 messages the catalog still lacks (batch 4) (#8490)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 21:23:25 +00:00
semmelrinde 2da2c85f27 Norwegian Bokmål: translate the 121 messages the catalog still lacks (batch 4) (#8493)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 21:23:02 +00:00
semmelrinde 359a7253e9 Ukrainian: translate the 121 messages the catalog still lacks (batch 4) (#8500)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 21:22:18 +00:00
semmelrinde 64bbfe9ed3 Turkish: translate the 121 messages the catalog still lacks (batch 4) (#8499)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 21:22:10 +00:00
YAEemf e6dc105134 Point clouds: insert PLY, XYZ and PTS scans as a modelling reference (#5151) (#5381)
* Point clouds: insert PLY, XYZ and PTS scans as a modelling reference (#5151)

A point cloud is kept in the design as a reference, drawn as depth-tested
dots and never a body.

- io: a PLY reader (ASCII, binary little/big endian; x, y, z of any numeric
  type, optional colours, other elements skipped; counts checked against the
  file) and XYZ/PTS text, thinned evenly past max_points. PLY meshes with
  faces can also come in through file.insert_mesh.
- doc: Document.point_clouds (shared f32 points relative to an f64 origin,
  colours, units, rigid placement, size and colour), stored as a binary
  container part; format change in pending/point-clouds.rs.
- engine: pointcloud.insert / edit / delete / list; doc.open opens a cloud as
  a new design; selection.delete takes point_clouds; view bounds include them.
- gpu: an instanced point-sprite pipeline (16 bytes a point).
- ui: Browser Point Clouds folder with eyes, menu and an Edit Point Cloud
  card; drop, Open, Insert and file dialogs take .ply/.xyz/.pts; a CPU
  viewport fallback; messages in en, en-GB, ja, zh, de and ko.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Point clouds: colour by the file, one colour or height, from the UI (#5151)

The Edit Point Cloud card gets Color By (File Colors, Single Color,
Height). Height is a blue-to-red ramp over design Z, between the cloud's
own two heights or, by default, a range worked out from the points (all
but the lowest and highest 2 %, from an even sample). pointcloud.insert
and pointcloud.edit take color_by and height_range; pointcloud.list
reports them. The colour of each point is worked out in one place
(PointCloud::shade) for the GPU and CPU viewports.

Also: the card's dropdowns compare the picked index (a dropdown's
response doesn't report the pick, so File Units did not change either).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Point clouds: integrate format registration and viewport caches (#5151)

* Point clouds: satisfy current UI audits and document comparisons (#5151)

Route model RGB data through the theme conversion boundary, provide a compact ribbon label, and include point clouds in the new document comparison. Gate the Unix-only CLI-link helper and test so Windows all-target checks remain buildable after the rebase.

* Point clouds: isolate translations for current main (#5151)

Move the existing 74 messages unchanged into one pending locale file and attribute it through a pending row, following the current repository workflow. Repository checks, 50 tooling tests, final workspace Clippy, wasm and generated-catalog equality checks passed after the rebase.

* Point clouds: fit the rebased code to main's GpuTarget and Frame

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Compare point clouds when reusing placement-independent results

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Point clouds: complete command help and required translations (#5151)

* Point clouds: size the save cap from the raised limit after the rebase

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: bherbruck <brennen.herbruck@gmail.com>
2026-10-28 21:17:02 +00:00
CamWight 866029aaa2 Engine: one sketch store for the sketch commands (W38.0, #5425) (#6336)
* Engine: one sketch store for the sketch commands (W38.0, #5425, no behaviour change)

The sketch commands found and kept the sketch they work on in about forty places, each its own
way. They now go through one module, cmd::sketch_store, so a drawing session (W38a/b) can put
sheet and view sketches behind the same calls without the commands changing again.

- target: the command's `sketch` param or the sketch being edited (target_sketch, moved).
- active: the sketch being edited, if any. The thirteen commands that need one keep their own
  refusal text; unifying the three texts is a separate, visible change.
- read and write: the only calls from the sketch commands to Document::sketch and sketch_mut.
- update: change a sketch on a copy of the document and keep both, the edit the text and link
  commands made by hand (sketch.text, sketch.edit_text, the projection, intersection and
  include links, sketch.fit_curves_to_section, sketch.break_link). As before, those paths
  neither solve the sketch nor run its checks.
- checked: the checks an edited sketch passes (the periodic splines), shared by edit_solved and
  sketch.offset.break.

edit and edit_solved stay in sketch.rs and load and keep their sketch through read and write.
Imported text, snap points and the face projections keep their own shape (a text that can't be
linked is skipped, snap points copy the document only when one is needed) through read and
write. The reads and writes that are about the design's own sketches stay as they are, each on
a line marked `// design-only:` (Redefine Sketch Plane, a joint's curve, a motion trace's wire,
and the session's live drag, parameter edits and `created` diff).

A source scan, each_sketch_command_goes_through_the_store, fails when a command reads or writes
a sketch, or asks for the active one, anywhere but the store or a marked design-only line in the
files that work on the design's sketches. Every existing sketch test is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Engine: the sketch store's scan also catches the active sketch taken as a value (#5425, review of #6336)

The scan only caught `active_sketch.ok_or`, so main's `let Some(id) = s.active_sketch else …`
could have come back unseen (0xlillith's review). It now also flags the value-read forms:
`) = s.active_sketch` (let-else and if let), `=> s.active_sketch` (a match arm),
`s.active_sketch.and_then(` and `s.active_sketch.map(`. State checks (`is_some`, `is_none`,
`== Some(`), assignments and snapshot copies stay allowed.

The wider scan found five commands that hand-rolled the store's `target` rule (a `sketch` param or
the sketch being edited). They now call `sketch_store::target`: sketch.inspect, sketch.glyphs,
sketch.export_dxf, inspect.curvature_comb and inspect.minimum_radius (their `curves` form).
Their refusals become target's:
- no `sketch` and none being edited: "no sketch is being edited" (was "no such sketch (and none
  is active)", or "no such sketch" for sketch.glyphs);
- an unknown name or id: "no sketch `X`" (an unknown id used to reach "that sketch is not
  evaluated");
- a feature that is not a sketch: "`X` is not a sketch";
- a `sketch` that is neither an id nor a name (true, a list, an object): refused,
  where it used to fall back to the sketch being edited. A null `sketch` still means none given
  (the scenario harness sends one): target now reads it that way for every sketch command
  (target_reads_a_null_sketch_as_none_given).
No test, doc or schema text named the old wording; the params docs ("sketch?: id|name (default
active)") still hold.

The two remaining value reads, the default sketch for a feature (features.rs) and the sketch a
measurement prefers (measure_sel.rs), go through `sketch_store::active`, with no change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Engine: a number in `sketch` is an exact sketch id, never a name (#5425, review of #6336)

`sketch_store::target` turned a JSON number into text and looked it up with
`Document::find_feature`, which falls back to a name when no feature has that id. So
`{"sketch": 999999}` could pick a sketch named "999999" whose id is something else, and export
or inspect it. sketch.export_dxf, sketch.glyphs and the two curvature inspects read an exact id
before they moved onto the store; the other sketch commands (the old `target_sketch`) and
sketch.inspect read a number as text.

One rule now, for every command that takes `sketch`: a number is an exact id (`as_u64`, then
the feature with that id); text is an id written out or a name, as before. A number that isn't
a whole number of 0 or more (negative, fractional) is refused with "`sketch` must be an id or a
name"; an id no feature has gives "no sketch `N`", as before. Nothing in the tests, docs,
scenarios or examples names a sketch with digits, so nothing relied on the old fallback.

Test (sketch_store): a sketch named "999999" with another id. sketch.export_dxf, sketch.glyphs
(with another sketch being edited, for its enabled check), inspect.curvature_comb and
inspect.minimum_radius (with a real curve id) refuse `{"sketch": 999999}`, find the sketch as
`"999999"` and by its own id, and refuse -1 and 1.5.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Engine: MidPoint finds its sketch through the store too (#5425, after #5011)

#5011 added a caller of the old `target_sketch` (MidPoint's `line_stays`, which swaps a point
picked after its line) after this branch's base. It now reads the sketch through
`sketch_store::target` and `sketch_store::read`, as the other sketch commands do, so a number
there is an exact id too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Engine: standard parts fix their sketch's entities through the store (#5425, after #6376)

#6376 (a standard part's sketches are fully defined) reads the sketch being drawn straight from
the document's features, after this branch's base. `fix_all` now takes it from
`sketch_store::active` and `sketch_store::read`, as the store's scan requires, with the same
result.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Engine: Toggle Diameter and Delete on a profile find their sketch through the store (#5425)

Two sketch commands landed on main after the store: sketch.toggle_diameter (#7729) still
called the removed sketch::target_sketch, and Delete on a picked profile (#7107) read the
sketch straight from the document. Both now go through sketch_store (target and read), and
the store's source scan passes again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Sketch dimensioned: use the sketch store's target after the rebase

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Sketch dimensioned: read the sketch through the store

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: bherbruck <brennen.herbruck@gmail.com>
2026-10-28 20:56:05 +00:00
Nathan Dane 85a60c1af6 Render output: Output editor, size presets, Check list, Copy, progress pill and result viewer (#6281) (#6433)
* Render output: size presets, Check list, Copy, progress pill, R and Esc, and the result viewer

* Complete Output GPU help translations and format choices

* Remove Output size labels already present in catalogs

* fix: compile the legacy finishing controls only for tests
2026-10-28 20:55:55 +00:00
semmelrinde 683535a18f Evaluation: a pattern of another component's body follows its own component when that moves (#8467)
A pattern of bodies copies them about an axis in its component's frame,
so its copies of a root body depend on where that component is placed.
placement_digest never counted a pattern's bodies, so moving the
component kept the cached copies. Read each body through placed_body,
as Combine does.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 20:49:55 +00:00
Logan Night d67c8e6231 Sketch text: Arabic and Hebrew are ordered right to left and joined (#8237) (#8324)
* claim: #8237

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* Sketch text: right-to-left lines are ordered and shaped (#8237)

A line with Arabic or Hebrew letters is split into display-order runs by the
Unicode bidirectional algorithm (unicode-bidi) and each run is shaped with the
font's own rules (harfrust), so letters join and marks sit where the font puts
them. Lines without right-to-left characters keep the glyph-by-glyph layout.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* Sketch text: a line break inside a right-to-left line keeps the text after it (#8237)

The bidirectional algorithm ends a paragraph at a line break; every
paragraph is shaped now, not only the first, so measuring such a line
counts all of it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-28 20:31:02 +00:00
semmelrinde 2841210fb2 Sketch Dimension: choose horizontal or vertical from the two points' box (#7295) (#7355)
* claim: #7295

* Sketch Dimension: choose horizontal or vertical from the two points' box (#7295)

Two points or a slanted line got the aligned distance whenever the text
was between the perpendiculars through them, so straight above the middle
of nearly level points was aligned and horizontal needed a thin wedge.
Now the text position relative to the box the two span picks the type:
inside it or in its outer corners aligned, above or below horizontal,
beside it vertical. This is the rule midpoint pairs already used, so both
share auto_orientation().

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Sketch Dimension: aligned across the line, horizontal or vertical by the pull past an end

Review on #7355: the aligned length must stay the default, and the box
rule shrank its zone to a thin strip on a shallow line. Now `auto` is
the distance between the two points everywhere across from them
(between the perpendiculars through them, and a tenth of their distance
past), and only a clear pull past an end changes it: up or down from
that end gives the horizontal distance, sideways the vertical one. The
two meet on the diagonals through the end, so both zones stay wide on a
shallow or steep line. Midpoint pairs keep main's box rule.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 20:27:44 +00:00
github-actions[bot] 170f2555ce Regenerate generated files and fold pending files [skip ci] 2026-10-28 22:30:25 +00:00
raykholo 6b523d6839 Theme drops: build for the web, and import there too (#8226) (#8534)
DroppedFile::bytes exists only on native; the web build stopped at
take_theme_drops. Native keeps reading the file there. On the web, the
shell already reads every drop asynchronously before the app sees it: a
drop over Preferences' Import tile now arrives as a theme and goes to
prefs::import_theme_bytes, instead of being opened as a design.
2026-10-28 18:25:26 -04:00
github-actions[bot] 06c9479a3f Regenerate generated files and fold pending files [skip ci] 2026-10-28 22:22:05 +00:00
Frank d7ef5280c5 Ctrl+W closes the design shown, not the browser tab (#5366) (#5466)
Ctrl+W (Cmd+W) closes the active design, asking first when it is
unsaved; closing the last one shows the start page. In the web app a
capture-phase keydown listener keeps the browser from closing the tab
while a design is shown; on the start page the browser closes the tab.
Ctrl+W joins the keys the app reserves, and the tab menu's Close shows it.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 20:15:33 +00:00
froglemonade2 f595f38e1c Define a named parameter inline from any value input (#4071) (#7341)
* claim: #4071

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Define a named parameter inline from any value input (#4071)

Any value input, typed or sent as a command's expression parameter, takes
`name = expression` (or `#name = expression`): the design gets the user
parameter `name` with that expression, and the input stores `name`, in the
command's one undo step.

- doc: the lexer skips a definition's `name =`, so until the design stores
  it the text evaluates as its expression and commands read and check it
  like any value. `Document::define_inline` then turns every stored
  definition (feature inputs and placements, dimension parameters, sketch
  pattern and text values, joint and coupling values, sheet metal and
  plastic rules, canvas planes) into a user parameter, the unit following
  how the input reads a bare number. A taken, reserved or empty name, two
  different values for one name, and a definition in a parameter's own
  expression or a configuration cell are refused; all or nothing.
- engine: `Session::execute` runs it after any command whose parameters
  hold definition-shaped text; the reply has `defined` (the first name,
  as `sketch.dimension` already gives) and `definitions`. A refusal fails
  the command, which leaves the design as it was.
- `parameters.change` with `new = expression` renames the parameter it
  changes (a dimension's or feature input's own, references following)
  and sets it; when the value is just `new`, it sets `new`. `changes`
  refuses definitions. `expr.evaluate` reports `defines`.
- UI: lengths keep the name when the design unit is applied; sketch text
  sends a definition as typed and previews only its value; the box corner
  and offset Distance 2 use the value; fields whose command keeps no
  expression (sketch scale, move, chamfer) refuse a definition with the
  way to name it. The dimension editor says which parameter it named.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 20:14:36 +00:00
Colin Faulkingham a3ee8957f4 Sketch: conic curves take their own id prefix, not the constraints' k (#6173) (#8407)
* claim: #6173

* Sketch: conic curves take the id prefix n, not the constraints' k (#6173)
2026-10-28 20:12:48 +00:00
semmelrinde be2168f70d Snap Fit: the Base Height hint in the user's language (#8451)
The hint "at the face" had no catalog message, so it stayed English in
every language. Add it in English and the 26 other catalogs, and check
that every plastic dialog hint has a message.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 20:12:42 +00:00
Daniel 93066ab60c Select Other: a still hold opens the list while Orbit, Pan or Zoom is lit (#8437) (#8438)
* Select Other: a still hold opens the list while Orbit, Pan or Zoom is lit

With a mode lit in the navigation bar (or Space held), holding the left button still on overlapping geometry opened nothing, and the release then selected the top item as a click. The viewport treats such a mode as owning left drags: a plain click still selects, and every other check on the mode sits on a drag. The hold was the one place a press that had not moved counted as navigation.

The hold is now cancelled only by a navigation that has started (the drag past the click distance), so it behaves as it does with no mode lit. The hint and the user guide already describe the hold without that condition. A preset's modifier binding (Maya Alt, Alias Shift+Alt, HFSS Alt) and Ctrl+left orbit still cancel it at the press, as before: holding such a chord is a gesture to navigate.

Tests: holding still with each mode lit opens the list, picks from it and a click still selects; a drag under each mode still moves the view and opens nothing; Maya's Alt chord held still does not open the list (it fails without the preset check).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Select Other: the press that opened the list does not move the view

egui calls a press a drag once it has lasted 0.8 s. With Orbit, Pan or Zoom lit, the press that opened Select Other at 0.5 s then became an orbit, pan or zoom, and moving the pointer to a row turned the view under the open list. While the list is open, a primary press no longer takes the lit mode.

Test: a press held past 0.8 s that then moves keeps the list open and the view still, for each mode.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 20:07:33 +00:00
Colin Faulkingham 90ef106e5f Preferences: the File view entry and the search field carry the window's name (#8318) (#8432)
* claim: #8318

* Preferences: the File view entry and the search field carry the window's name (#8318)

The File view's entry that opens Preferences said "Settings", and the window's
search field said "Search settings" / "No matching settings", while the window
title, the File menu and the help texts around the app say "Preferences".  The
strings that name the window or point to it now use "Preferences"; ids unchanged.

Translations of these ids followed the English source and keep their wording
until the language teams catch up.

Tests: home::tests::the_entry_that_opens_preferences_carries_the_windows_name
and prefs_search::tests::the_search_field_names_the_window_it_searches fail on
main ("Settings" vs "Preferences") and pass here; the prefs_search:: and home::
suites pass, and the full solidcraft-ui-egui lib suite passed in `cargo xtask ci`.
2026-10-28 20:06:24 +00:00
froglemonade2 02ac56d12f Feature windows choose Join, New Body or Cut from what the material touches (#6901) (#6903)
* claim: #6901

* Feature windows choose Join, New Body or Cut from what the material touches (#6901)

Extrude, Revolve, Loft, Sweep, Coil and the Box, Cylinder, Sphere and Torus choose
their operation by running the Join on a copy of the design off the window thread
and counting the pieces: Join when the material makes one body with what it
touches, New Body when it would be a separate piece, Cut when it lies inside a
body (Revolve and the four primitives; Extrude keeps its own Cut). The choice
changes only when a check is in, a pick in the Operation row (the shown option
included) stops it for good, and OK waits for a running check. Hidden bodies take
no part: with some hidden, the shown ones become the feature's targets.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Operation row: a pick in Extrude stops its own choice at once; ja/zh strings, gallery entry

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Operation check: contact test first, mesh volumes for Cut, OK takes the evaluated Join

Material touching no body is a New Body without running the Join (the contact
test costs 0-240 ms where the Join costs seconds on a large body). Inside is told
from display-mesh volumes instead of exact ones (8 s on a 400-hole plate). The
check evaluates the Join through Session::ahead, and OK of the same commands
takes it (Session::prime) rather than computing it again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Preference: Choose the operation automatically (on by default)

Preferences > Design gets "Choose the operation automatically" (auto_operation,
on by default). Off, feature windows don't choose Join, New Body or Cut from
what their material touches: each keeps the operation it opens with (Extrude
its own Join or Cut), no check runs and OK doesn't wait for one, as before

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Arabic, Hebrew, Vietnamese and Turkish strings for the operation choice and its preference

Arabic, Hebrew and Vietnamese are complete catalogs now, and Turkish has a full
catalog, so this change's three strings get them too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Operation check: a closed window's check stops; the icon audit doesn't choose

A window's operation check kept running after the window closed, a Join on
the design for nothing, and the test harness waited for it after every step:
the icon audit, which opens every window, took ~30 min instead of ~1. The
check now runs under a Progress, and closing the window (or one that doesn't
choose) abandons it: its evaluation stops at the next feature and nothing
waits for it. The icon audit turns auto_operation off, as it only looks at
icons (75 s again).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Box placement test: the window keeps its New Body

The test #6248 added places a box that overlaps Base and expects a second body;
with #6901 the window would join or cut it. The test is about where the box
goes, so it turns auto_operation off.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Join pieces: read the target lists leniently after the rebase

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: bherbruck <brennen.herbruck@gmail.com>
2026-10-28 19:57:27 +00:00
Lars Jansen 261d00fbb2 History and browser: a sketch's icon in the colour of its state (#7245) (#7250)
* claim: #7245

* feat(ui): a sketch's icon in History and the browser takes the colour of its solve state (#7245)
2026-10-28 19:40:45 +00:00
raykholo e2935aff95 Stand-up offer: a note only when the part seems to lie on its back (#7717) (#7718)
* claim: #7717

* Stand-up offer: a note only when the part seems to lie on its back (#7717)

* Stand-up note: an unclear shape still gets the note

* Stand-up note: a Don't ask again button, as the dialog has

* Control protocol: the stand-up settings in the sorted ui.prefs list (#7717)

* Stand-up note: the control import test asks as before (#7717)

The test checks the caller's `up`, so it sets the setting to Ask and every
file from another program still gets the offer.
2026-10-28 19:40:25 +00:00
sascha2101 a95f30f186 Sketch: Center Point Arc follows the cursor clockwise or counter-clockwise (#6645) (#6664)
* claim: #6645

* Sketch: Center Point Arc follows the cursor clockwise or counter-clockwise (#6645)

The centre-point arc always ran counter-clockwise from its start; a
clockwise arc needed a typed negative sweep. The tool now tracks the
signed turn the cursor makes round the centre after the start is placed,
and its sign sets the direction of the preview, the live Sweep box and
the created arc.

sketch.arc.center_point takes `clockwise` with a clicked end: the arc is
stored counter-clockwise from the end and reversed, as a negative sweep
is, so the start keeps its radius and `<id>.start`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FN5eEMrqWWXqi65FcK8GXq

* Sketch: keep the old counter-clockwise centre-point arc behind a preference (#6645)

Preferences > Sketch gets "Center point arc follows the cursor's
direction" (center_arc_follows_cursor, on). Off, the arc runs
counter-clockwise from the start whichever way the cursor went, as it
always did. Its strings are a pending locale file (en, de).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FN5eEMrqWWXqi65FcK8GXq

* Sketch: Japanese and Chinese strings for the centre-point arc preference (#6645)

ja and zh are complete catalogs, so the new preference's label and tip
need them too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FN5eEMrqWWXqi65FcK8GXq

* Sketch: Arabic, Hebrew and Vietnamese strings for the centre-point arc preference (#6645)

Arabic, Hebrew and Vietnamese became complete catalogs on main, so the new
preference needs them too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: sascha2101 <221609842+sascha2101@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 19:32:13 +00:00
semmelrinde 429c2b44b5 Russian: translate the Render workspace's 733 messages (batch 2) (#8251)
* Russian: translate the Render workspace's 706 messages (batch 2)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Russian: the 27 Render messages main gained since (the Appearances panel)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 19:06:50 +00:00
github-actions[bot] 28b8da3126 Regenerate generated files and fold pending files [skip ci] 2026-10-28 21:55:57 +00:00
github-actions[bot] 9ddbcac775 Regenerate generated files and fold pending files [skip ci] 2026-10-28 21:46:59 +00:00
semmelrinde 9628e60ca0 Sketch: Reverse Spline Direction (#8224) (#8414)
A new command, sketch.spline.reverse, runs a spline the other way: its
point list is reversed in place, so its last point becomes its first and
the curve keeps its path (chord-length fits, uniform clamped knots and
closed fits read the same both ways). Points and constraints stay. A
projected spline and one an offset uses or makes are refused. The
sketch's right-click menu offers it for one selected spline.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 18:56:34 +00:00
Logan Night bcdee6e0bb Sketch on a face: a round's edges that end a hair apart still close (#8284) (#8386)
* claim: #8284

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* Sketch on a face: a round's edges that end a hair apart still close (#8284)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* Sketch on a face: test both ends of a rounded loft end to end (#8284)

A square lofted to a circle with its side edges rounded, as in the
report: a sketch on either end face takes the whole face. Without the
fix the circular end fails with "face projection has a branched
boundary". Also drops a redundant term from the join tolerance.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-28 18:56:20 +00:00
Colin Faulkingham c2e69ed724 Timeline: the feature menu's suppress item follows the reader's language (#8301) (#8383)
* claim: #8301

* Timeline: the feature menu's suppress item follows the reader's language (#8301)

Suppress Features / Unsuppress Features were raw literals. Menu::label()
translates a label only when a catalog entry carries it, and none did, so the
item stayed English in every language, the Japanese UI included.

The two labels are now the messages timeline.suppress_features and
timeline.unsuppress_features in a new assets/locales/pending file: the English
wording is unchanged, and the complete catalogs (ar, he, ja, vi, zh) plus de and
ko carry the translations.

cargo test --profile ci -p solidcraft-ui-egui --lib -- timeline::tests::the_feature_menu_suppress_item_follows_the_language
fails on the claim commit (the Japanese menu paints the English literal) and
passes with the change.
2026-10-28 18:55:37 +00:00
semmelrinde 94d23338fe Render: the Appearances panel and the shots strip in 15 languages (#8417)
The Appearances panel's 27 messages for Dutch, Hungarian, Galician,
Malay and Norwegian Bokmål, which their merged Render batches missed,
and the shots strip's 7 newer messages for those and ten more.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 18:54:59 +00:00
Jasper van Loenen 728100c26d UI: Fix settings autoscroll bug (#8388)
* Fix issue with settings window automatically scrolling to selected item, preventing scrolling by user

* Fix issue with settings window automatically scrolling to selected item, preventing scrolling by user
2026-10-28 18:54:23 +00:00
Daniel b470aebe80 Toolbar: Sketch Create drop-down rows share the menu's width (#8409)
In the Sketch > Create drop-down a plain row such as Point was drawn
200 pt wide, the minimum width its labels fit in, while a family row such
as Slot filled the menu. The menu was as wide as the one-line pin hint in
its footer, so the plain rows' hover background and pin stopped short of
the right edge.

The Create menu now sets its width from its rows before drawing them, as
the other panel drop-downs do, and passes that width to the plain rows
instead of recomputing it over a subset. Family rows fill the same width
and the footer hint wraps inside it. The overflow menu's plain rows take
the width of all its commands in the same way. A family's submenu still
sizes its variants to their own labels.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 18:53:32 +00:00
MarkusRe 05f62b09e0 Browser menus: V runs the open menu's Show/Hide on the row it was opened for (#8377)
Most browser menus show V beside Show/Hide, but the V key always ran
toggle_visibility, which acts on the selection. A right-click on a body or
sketch row also selects it, so the two agreed there; a right-click on the
Bodies, Sketches or Origin folder, a group, the component or an origin plane
does not, so V did nothing, or flipped a body selected earlier, and left the
menu open.

With a menu open, V now runs that menu's row whose shortcut is V, through
run_item as a click does, and closes the menu (context_menu::press_shortcut).
A disabled row takes the key and does nothing. With no menu open, or a menu
without such a row, V still acts on the selection (#4128, #4409: V stays
selection-based).

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 18:23:26 +00:00
bherbruck 5d1c33fc82 Docs: the macOS app is notarized, and the update check names tangency-labs/solidcraft (#8402)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 18:15:03 +00:00
bherbruck d26de76097 Updates: leave the update to the launcher that manages this copy (#8403)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 18:14:57 +00:00
austin62jake 65784cae2f Save As offers the open file's own name, not the name stored in the design (#8329) (#8354)
* claim: #8329

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019FAWPuFoh9qxn2uS2j53QZ

* Save As offers the open file's own name (#8329)

Save As, Save As JSON and Save a Copy proposed the design's name, the one
stored inside the file. Copies of a file under other names keep the
stored name, so "Sample Plate-bug.solidcraft" was offered
"Sample Plate.sc", the same as its sibling, and one replaced the other.

Session::save_as_name() offers the stem of the open file unless the
design was renamed since it was opened or last saved, and the design's
name otherwise (a new design, or one renamed in the Browser).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019FAWPuFoh9qxn2uS2j53QZ

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-28 18:11:06 +00:00
semmelrinde 003d388b78 Sketch: an arc slot is drawn without a redundant Equal on its caps (#8355) (#8395)
Each cap is tangent to both concentric sides, so its radius is already
half the gap between them and the two caps are equal. The Equal the arc
slot added between them was always redundant; it is no longer added.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 18:09:47 +00:00
Jasper van Loenen 562d066c0e Fix endless redraw of settings window if setting has empty row, caused by storing setting in row of previous setting (#8399) 2026-10-28 18:07:52 +00:00
github-actions[bot] eaf6ef741c Regenerate generated files and fold pending files [skip ci] 2026-10-28 21:14:05 +00:00
github-actions[bot] 3026cca31a Regenerate generated files and fold pending files [skip ci] 2026-10-28 21:06:56 +00:00
semmelrinde f0095a1ae6 Ribbon: a two-line button label stays inside the button's highlight (#8391) (#8405)
A button is 60 points tall and its label starts 32 points down, so two
lines of the label font (31 points) ran 3 points past it. Two-line
labels now take the font size plus 2 points per line and start higher
when they would still run past the button, leaving 2 points below.
One-line labels are unchanged.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 18:07:43 +00:00
semmelrinde aca93d1557 Swedish: translate the 203 messages main gained since batch 1 (batch 3) (#8387)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 18:07:40 +00:00
N3MI-DG 6fffd745fd Insert Part: the Length list opens on the default length, with no "Default" item (#8020) (#8022)
* claim: #8020

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* Insert Part: the Length list opens on the default length (#8020)

The list carried an item called "Default" above the standard lengths. It
never said which length it stood for, and one of the lengths below it
always was that length, so the list offered the same length twice under
two names. Change Part Size has always listed concrete lengths.

The item is gone and the list opens on the length the part would be given
anyway. The default cannot be worked out in the dialog, because it is not
one rule: a cap screw or bolt takes the first standard length at or above
2.5 d, a set screw the first at or above d, a dowel pin the first at or
above 4 d. parts.library now reports default_length beside each size's
table values, taken from the shape the engine would build, and the dialog
selects it; the test checks that report against what an insert without a
length is actually built to, for every size of every family.

Leaving the length alone behaves as "Default" did: a new size resolves
the list again, so M6 to M12 moves the selection from 20 to 30. A length
chosen by hand stays until the size changes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* Insert Part: the labels test skips default_length too

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: bherbruck <brennen.herbruck@gmail.com>
2026-10-28 17:58:03 +00:00
Tyler Gregorcyk 4a7a8f31f8 Sphere, Torus and Cone dialogs: place them by their centre or base (#5638) (#8328)
* claim: #5638

* Sphere, Torus and Cone dialogs: place them by their centre or base (#5638)

The Box and Cylinder dialogs already had typed X, Y and Z placement
fields; the Sphere, Torus and Cone dialogs now do too. Sphere and Torus
show Placement: Center and take a picked point like the Box; Cone shows
Placement: Base Center like the Cylinder. The fields take expressions,
and Edit Feature shows and keeps the stored centre or base.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 17:39:31 +00:00
Daniel a1a801fb31 Feature dialog: draw the busy spinner in the footer row (#8362)
With the dialog buttons at the bottom, the spinner shown while the preview
computes or OK applies was painted on its own after the footer: at the
card's left edge and one control height up from its bottom. The footer
insets its row by 12 pt at the sides and 10 pt above and below and centres
the buttons, so the spinner sat outside that inset and about 10 pt below
the buttons' centre line.

Panel::feature now draws the spinner through the footer's left slot, so it
shares the row's inset and vertical centre, in the space the footer already
leaves for it before the status text. The rect is published as
dialog:footer:spinner, and a panel test checks it lies in the footer row,
at its left inset and on the OK button's centre line. The spinner in the
title row (buttons at the top) is unchanged.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 17:32:56 +00:00
semmelrinde 2a6e7105cc Italian: translate the 159 messages main gained since batch 1 (batch 3) (#8361)
* Italian: translate the 132 messages main gained since batch 1 (batch 3)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Italian: the Appearances panel's 27 Render messages

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 17:32:56 +00:00
semmelrinde 035e065b27 Russian: translate the 247 messages main gained since batch 1 (batch 3) (#8363)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 17:32:21 +00:00
semmelrinde 67bda4dfd1 Malay: translate the 199 messages main gained since batch 1 (batch 3) (#8368)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 17:32:17 +00:00
semmelrinde aba05eb951 Dutch: translate the 199 messages main gained since batch 1 (batch 3) (#8366)
* Dutch: translate the 199 messages main gained since batch 1 (batch 3)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Dutch: Spoed for a thread's pitch, as the catalog's Pitch (review)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 17:31:27 +00:00
semmelrinde b8bae7222a Japanese: translate the 29 Render entries that still held English (#8357)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 17:31:27 +00:00
semmelrinde 32eea80c98 Czech: translate the 203 messages main gained since batch 1 (batch 3) (#8376)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 17:31:21 +00:00
semmelrinde fa19a49db9 Indonesian: translate the 247 messages main gained since batch 1 (batch 3) (#8364)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 17:31:20 +00:00
github-actions[bot] 6ef3d71e02 Regenerate generated files and fold pending files [skip ci] 2026-10-28 20:37:10 +00:00
semmelrinde bd6e8ef567 French: translate the 149 messages main gained since batch 1, Render included (batch 3) (#8379)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 17:30:29 +00:00
semmelrinde 5df84bbaf5 Turkish: translate the 340 messages main gained since batch 1, Render included (batch 3) (#8380)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 17:30:08 +00:00
github-actions[bot] eaea3e9087 Regenerate generated files and fold pending files [skip ci] 2026-10-28 20:04:18 +00:00
github-actions[bot] c03a43c88c Regenerate generated files and fold pending files [skip ci] 2026-10-28 19:54:52 +00:00
semmelrinde b32448f713 Ukrainian: translate the 340 messages main gained since batch 1, Render included (batch 3) (#8381)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 17:29:47 +00:00
semmelrinde f3a23d1c75 Galician: translate the 199 messages main gained since batch 1 (batch 3) (#8367)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 17:29:34 +00:00
semmelrinde 2dc406ae86 Norwegian Bokmål: translate the 198 messages main gained since batch 1 (batch 3) (#8375)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 17:24:56 +00:00
Nathan Dane 293ed5fab7 Render inspector: Appearance editor with the look chain, scope, mixed values and Advanced (#6281) (#6432)
* Render inspector: selection-following appearance panel with the look chain, Applies to and edit controls

* Render appearance: Glass, Clear coat, Maps, Saved optics and Reflections sections

* Update Render navigation tests for dedicated editors

* Exercise Focus keyboard protection through the Library search field
2026-10-28 17:23:16 +00:00
semmelrinde d2456921ca French: translate the 295 messages the catalog was missing (#8012)
* French: translate the 205 messages the catalog was missing

The French catalog lacked 205 of the English messages, so parts of
Preferences, the hole presets, the slicer messages, the Render
workspace and the Assistant showed in English. They are translated in
one pending file, with the catalog's terms (Esquisse, Fonction,
Bossage, Appui, Clip, Prise de vue) and its non-breaking space before
: ; ? and !.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Translate the 90 messages main added since (the navigation bar's)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 17:22:21 +00:00
semmelrinde 93d1e09bf7 Hungarian: translate the 203 messages main gained since batch 1 (batch 3) (#8373)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 17:09:02 +00:00
semmelrinde dddae33285 Romanian: translate the 203 messages main gained since batch 1 (batch 3) (#8374)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 17:08:54 +00:00
semmelrinde 1eec6d90b7 Sketch text: Bold in a variable font sets its weight axis (#8211) (#8331)
A variable font (one file for every weight, as most web fonts ship) has no face marked bold,
so Bold failed with "has no bold face". Without a bold face, a face whose wght axis reaches past
semibold is now set to weight 700. ttf-parser gets its variable-fonts feature for that.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 17:08:27 +00:00
semmelrinde 405217c3e5 Czech: translate the Render workspace's 584 messages (batch 2) (#8323)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 16:58:48 +00:00
austin62jake 86342b8c5c DXF import: an elliptical arc comes in as exact conic arcs, not a fitted spline (#8155) (#8241)
* claim: #8155

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019FAWPuFoh9qxn2uS2j53QZ

* DXF import: an elliptical arc comes in as exact conic arcs (#8155)

A partial ELLIPSE (how Fusion, and SolidCraft's own DXF export, write an
elliptical arc) was read as a degree-3 spline fitted through 16 samples,
which strays from the ellipse between them: 0.84 mm on a 300-degree arc
of a 200 x 40 mm ellipse. It is now read as exact rational-quadratic
conic pieces of at most a quarter turn each, which the sketch keeps as
conics. A conic arc written by SolidCraft's DXF export now reads back as
the same conic.

The arc's sweep is taken with rem_euclid instead of a loop that added a
turn at a time, which ran for billions of turns on a start angle of 1e11.

sketch.drawing_bounds and the width/height sizing of sketch.insert_dxf
measure a conic by points along it, not by its apex, which can lie
outside the curve.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019FAWPuFoh9qxn2uS2j53QZ

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-28 16:56:17 +00:00
Colin Faulkingham 95ba99d710 Move/Copy: a triad drag ends where the button is released (#8265) (#8309)
* claim: #8265

* Move/Copy: a triad drag ends where the button was released (#8265)

A frame carries all the input queued since the last one, so the release
that ends a drag and further pointer movement — the hand keeps moving as
the button goes up, or input is queued during a busy frame — arrive
together, and the frame's latest pointer position is already past the
release. The drag's final change was read from it, so the value, the
preview and the command both jumped to wherever the mouse had got to;
pressing Enter right after the release closed the window first, which is
why that worked around it. Rotate and occurrence moves share the triad.

The final change now comes from the release event's own position, which
the raw input carries (egui's processed pointer events drop it). The
regression test sends a release at 20 mm and a move to 30 mm in one frame:
30 mm before, 20 mm after.

Fixes #8265.
2026-10-28 16:53:41 +00:00
raykholo dd2e44bb12 Raise the largest file SolidCraft opens with a setting or launch flag (#4086) (#7565)
* claim: #4086

* Raise the largest file SolidCraft opens with a setting or launch flag (#4086)

* Translate the file size limit strings

* Size limits: design files are .sc now, .solidcraft still read
2026-10-28 16:52:29 +00:00
github-actions[bot] 506f79c092 Regenerate generated files and fold pending files [skip ci] 2026-10-28 19:23:10 +00:00
semmelrinde 2b7159f363 Romanian: translate the Render workspace's 733 messages (batch 2) (#8343)
* Romanian: translate the Render workspace's 733 messages (batch 2)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Romanian: the Render tree's switch hint is a verb

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 16:41:23 +00:00
semmelrinde 895264c4cd Swedish: translate the Render workspace's 733 messages (batch 2) (#8344)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 16:41:17 +00:00
github-actions[bot] 48ba6ff3c6 Regenerate generated files and fold pending files [skip ci] 2026-10-28 18:54:51 +00:00
Homero Thompson f103468dba Params: a list parameter refuses a wrong type instead of losing entries (#6651) (#6683)
* claim: #6651

* test(#6651): a list parameter of the wrong type is refused

A list parameter such as a cut's `targets` or an export's `bodies` loses entries without an error: a value of the wrong type reads as an empty list, which most commands take to mean "every body". The regression test drives the engine the way a user does: two bodies, a box cut that crosses both and is meant for one of them, and a `targets` of the wrong type. The command must refuse it and leave the design as it was.

* fix(#6651): a list parameter refuses a wrong type instead of losing entries

A list parameter of the wrong type was read as an empty list, and an empty
list means "every body" to most commands: a cut meant for one body cut every
body it touched and the command reported success.

A wrong type is now an error that names the parameter, the offending entry
index and the value it got. A list longer than 10000 entries is an error
instead of being cut short. `null` stays absent, as the schema contract says,
and a plain string is still a list of one. The 80 call sites now propagate the
error instead of losing entries; the commands that take feature keys, which
may be named or numbered, read them with their own reader.
2026-10-28 16:25:53 +00:00
Lars Jansen dca332201f Status bar: the sketch's state, what is being edited and the design's units (#7243) (#7248)
* claim: #7243

* feat(ui): status bar with the sketch's state, what is being edited and the design's units (#7243)
2026-10-28 16:25:32 +00:00
bherbruck 37a586dd61 Release 0.25.1 2026-10-27 20:58:30 -04:00
bherbruck a79f40a711 Release 0.25.0 2026-10-27 18:05:39 -04:00
bherbruck b5728f284b Release 0.24.1 2026-10-27 08:34:27 -04:00
bherbruck 5965439a15 Release 0.24.0 2026-10-26 19:23:21 -04:00
bherbruck 586a358ed4 Release 0.23.1 2026-10-26 07:07:21 -04:00
bherbruck 7770f8982d Release 0.23.0 2026-10-25 18:18:39 -04:00
bherbruck 72ad6383ef Release 0.22.1 2026-10-25 10:38:39 -04:00
bherbruck 0537623a75 Release 0.22.0 2026-10-24 18:53:43 -04:00
bherbruck 65d288227e Release 0.21.0 (rc.2's code, version only)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 20:51:08 -04:00
bherbruck fedb3bcdb1 Release 0.21.0-rc.2 2026-10-23 17:14:38 -04:00
bherbruck 097b8b7550 Release 0.21.0-rc.1
The tree is main at f120285c9 exactly; the previous release commit is kept as a parent so release only moves forward.
2026-10-23 13:48:05 -04:00
bherbruck af7ca3a8a2 Release 0.21.0-rc.1
The tree is main at b31fddb98 exactly; the previous release commit is kept as a parent so release only moves forward.
2026-10-23 13:37:43 -04:00
bherbruck 27ddb725c7 Release 0.21.0-rc.1
The tree is main at 2bf3d4e11 exactly; the previous release commit is kept as a parent so release only moves forward.
2026-10-23 12:10:02 -04:00
bherbruck a06bdf5cfc Release 0.20.0
The tree is main at 030187452 exactly; the previous release commit is kept as a parent so release only moves forward.
2026-10-22 18:34:40 -04:00
bherbruck 33fdcdb3a0 Release 0.19.0
The tree is main at 5899e5b6c exactly; the previous release commit is kept as a parent so release only moves forward.
2026-10-21 21:13:33 -04:00
bherbruck c07ab5f8f9 Release 0.18.4
The tree is main at 728f753b8 exactly; the previous release commit is kept as a parent so release only moves forward.
2026-10-21 12:26:34 -04:00
bherbruck fea32f8aac Release 0.18.3
The tree is main at 034aa60d4 exactly; the previous release commit is kept as a parent so release only moves forward.
2026-10-21 08:46:37 -04:00
bherbruck 4927214976 Release 0.18.2
The tree is main at 57bcc4083 exactly; the previous release commit is kept as a parent so release only moves forward.
2026-10-20 22:09:18 -04:00
bherbruck b621819c0c Release 0.18.1
The tree is main at 522ae7755 exactly; the previous release commit is kept as a parent so release only moves forward.
2026-10-20 17:39:11 -04:00
bherbruck ec552a5300 Release 0.18.0
The tree is main at c3151fb7f exactly; the previous release commit is kept as a parent so release only moves forward.
2026-10-20 16:28:59 -04:00
bherbruck e0cc740cc3 Release 0.17.0
The tree is main at 511faedcf exactly; the 0.16.x release commits are kept as a parent so release only moves forward.
2026-10-20 11:41:48 -04:00
bherbruck 5de48e916d Release 0.16.2 2026-10-19 00:39:30 +00:00
bherbruck 80af7bbe3e Release 0.16.2
Version 0.16.2: 0.16.1 with the rigid orbit fix (#2753). Same design format (27).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 00:38:53 +00:00
bherbruck 191e983423 Fix orbit about the picked point (regression in 0.16.0) (#2753)
Orbiting about the point under the cursor (or the origin) turned the camera
about its target and then panned to put the pivot back. The pan works at the
target's depth with the parallel-view scale, so in a perspective view the
pivot slid off its pixel and the model swung about the camera.

The camera now turns rigidly about the pivot: Camera::orbit_about keeps the
pivot's coordinates in the camera's frame and rebuilds the target from the
new orientation, so the pivot stays exactly on its pixel in both projections.
The Shift snap spring and view.navigate's pivot orbit use the same.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit e88779218)
2026-10-19 00:38:52 +00:00
bherbruck 2b9445b049 Release 0.16.1 2026-10-18 20:16:21 +00:00
bherbruck 7ddf48ca16 Release 0.16.1
Version 0.16.1: 0.16.0 with the orbit fix (reverts #2142). Same design format (27).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 20:12:04 +00:00
bherbruck d2f6848377 Revert #2142: orbit about the picked point like 0.15.0
#2142 made orbiting about the point under the cursor turn the camera in place instead of turning the part about that point. Restore the 0.15.0 behaviour.

This reverts commit cac4bccea8.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 20:12:00 +00:00
bherbruck 0b6d6fecd8 Release 0.16.0 2026-10-18 18:16:11 +00:00
bherbruck fa691707c2 Release 0.15.0 2026-10-17 13:54:24 +00:00
bherbruck b9a55c74e2 Release 0.15.0
Version 0.15.0; the pending design-format changes are folded into format 26.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 13:53:44 +00:00
bherbruck 2bb9c81069 Release 0.14.0 2026-10-16 09:19:14 +00:00
bherbruck cedb51b8ea Release 0.14.0
Version 0.14.0; the pending design-format changes are folded into format 25.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 09:19:10 +00:00
bherbruck 66d13059dd Release 0.13.1 2026-10-15 21:56:43 +00:00
bherbruck 800ea40c0d Release 0.13.1
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 21:56:35 +00:00
bherbruck 20442eecd3 Agent chat on Windows: start npm agents through their .cmd shim
npm puts a Unix shell script with the bare name (codex-acp,
claude-code-acp, gemini) beside the .cmd shim. The lookup tried the bare
name first, so every npm-installed agent failed with "not a valid Win32
application (os error 193)". Windows now only considers .exe/.cmd/.bat,
and a command saved with the bare path runs the shim beside it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 60ea8c69d2)
2026-10-15 21:51:01 +00:00
bherbruck 22d1cd7032 Release 0.13.0 2026-10-15 20:34:13 +00:00
bherbruck 6a0dc18655 Fix the Windows 32-bit and macOS release builds
On 32-bit Windows SetWindowLongPtrW is SetWindowLongW, which takes and
returns i32, so the window-procedure hook didn't compile for i686.
The macOS app bundle now signs the bundled solidcraft-cli before the
bundle itself; codesign refuses a bundle with an unsigned helper.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 94e76cd97e)
2026-10-15 20:34:12 +00:00
bherbruck e006dbf1af Release 0.13.0
The tree is the 0.13.0 version commit (8241a750fa) on main exactly; the previous release is kept as a parent so release only moves forward.
2026-10-15 19:59:50 +00:00
bherbruck 8241a750fa Release 0.13.0
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 19:59:42 +00:00
bherbruck 41779cf7bb Release 0.12.0: release branch follows main again after the 0.11.1 patch
The tree is main at c36a6f9f exactly; the 0.11.1 patch commit is kept as a parent so release only moves forward.
2026-10-15 13:32:01 +00:00
bherbruck b01b9689c8 Release 0.11.1
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 20:41:41 +00:00
bherbruck 4426da6f5d Windows: start Direct3D 12 first, and Vulkan only without a D3D12 GPU (#1190)
* Windows: start Direct3D 12 first, and Vulkan only without a D3D12 GPU

wgpu started Vulkan, D3D12 and OpenGL together and preferred Vulkan, so
every Windows start loaded all installed Vulkan drivers. An old Intel
Vulkan driver (igvk64.dll) crashed 0.10.1 at startup inside the driver.

The app now probes D3D12, then Vulkan, then OpenGL, one backend at a
time, and starts only the first with a hardware adapter (WARP when none
has one). WGPU_BACKEND still wins; graphics.json's "backend" sets the
order by hand; the software renderer (safe mode, the retry) uses D3D12
alone. A new Windows CI job starts the real app under several settings.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CI: a test filter YAML parses

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CI: the startup smoke test writes graphics.json where the app reads it

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* CI: run the WARP shader tests one at a time

WARP's shader JIT (d3d10warp.dll) crashed twice in 124 runs of the gpu
tests with four test threads, with a null read inside its own optimizer
while several devices compiled compute pipelines at once. Serial runs
did not crash.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 95ea05e7c8)
2026-10-14 20:41:37 +00:00
bherbruck 5ead82e627 Release 0.11.0: release branch follows main again after the 0.10.1 patch
The tree is main at cccbe125 exactly; c29b0d2f (0.10.1) is kept as a parent so release only moves forward.
2026-10-14 20:07:41 +00:00
bherbruck c29b0d2f13 Release 0.10.1 2026-10-14 14:41:19 +00:00
bherbruck 480fd8d517 Fix the startup crash on D3D12 with FXC: CPU fallback for the tessellation pipeline, FXC-friendly shader (#1098) (#1099)
* GPU tessellation: a pipeline the device cannot build falls back to CPU meshing instead of crashing (#1098)

Build the tessellation compute pipeline inside error scopes; TessGpu::new returns an error,
and the viewport logs it and meshes bodies on the CPU. A Windows CI job builds the pipeline
with D3D12's FXC on the WARP adapter.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Tessellation shader: basis functions in one-dimensional local arrays, so D3D12's FXC compiles it (#1098)

FXC has to unroll loops that write an array inside a struct (Basis.n0/n1) or a 2-D array
(ndu) by a counter, and cannot with run-time trip counts (X3511). A2.2 basis functions in a
local 1-D array returned whole; derivatives from the degree p-1 functions; the pole step
offsets computed rather than indexed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 14:41:16 +00:00
bherbruck 4c09fa5355 Hovered and selected faces light solidly again over GPU-drawn bodies (#1064)
Since the model's mesh went back to the reference mesher (#940), the GPU viewport drew
opaque bodies from their display plans while hover and selection lit faces with the
reference mesh's triangles. Two triangulations of the same face at equal depth fought, so
a hovered face shimmered in wedges instead of lighting whole.

Faces lit over a body drawn from its plan now use the plan's own triangles
(ModelBody::plan_mesh, evaluated once on the CPU), and the highlight pass gets a small
depth bias toward the eye so f32 rounding between the GPU and CPU evaluations of the same
triangles cannot speckle it either.

Test: every face of a box with a pocket and a round boss, hovered and rendered offscreen
through the viewport's real pipelines on the GPU path, lights the same pixels as on the
CPU path (skipped without a GPU adapter).

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 12:56:47 +00:00
651 changed files with 115170 additions and 3986 deletions
+3
View File
@@ -364,6 +364,9 @@ jobs:
cargo test -p xtask ui_containers --locked
- name: Sorted lists
run: cargo xtask lists
# New UI text must reach every complete catalog; report it here, before review (#8542).
- name: Translations in the complete catalogs
run: cargo xtask i18n --check
- name: Agent router and skills cite real files
run: |
cargo xtask skills
+7
View File
@@ -602,6 +602,13 @@ Original SolidCraft drawings, Open for owner review; no runtime assignments.
| assets/locales/sr.json | Tarik Sijercic (tsijercic1) | Original Serbian (ekavian, Cyrillic) translation of SolidCraft's English catalog; no commercial CAD text used | MIT OR Apache-2.0 |
| assets/icons/ui/design/svg/model/finish_edit.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
| `assets/locales/pending/sketch-tracking-guides.json` | SolidCraft contributors | Original alignment-guide preference labels and help text | MIT OR Apache-2.0 |
| assets/locales/pending/point-clouds.json | SolidCraft contributors | Original point-cloud UI strings and translations | MIT OR Apache-2.0 |
| assets/icons/ui/design/svg/model/feature_group.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
| assets/icons/ui/design/svg/model/mesh_body.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
| assets/icons/ui/design/svg/model/timeline_play.svg | SolidCraft contributors | Original history playback icon; canonical grey_cube base and original action cue | MIT OR Apache-2.0 |
| assets/icons/ui/design/svg/model/timeline_stop.svg | SolidCraft contributors | Original history playback icon; canonical grey_cube base and original action cue | MIT OR Apache-2.0 |
| assets/icons/ui/design/svg/flat/status_pin.svg | SolidCraft contributors | Original analytic pin icon for persistent viewport results | MIT OR Apache-2.0 |
| assets/locales/pending/render-wear.json | SolidCraft contributors | Original UI labels and translations | MIT OR Apache-2.0 |
## Code adapted from sibling projects
+8 -1
View File
@@ -278,6 +278,11 @@ Some files gain an item in many pull requests at once. They are kept so that two
each add an item only meet when their items are neighbours, which spares everyone a conflict
and a fresh CI run:
- **Growing Rust lists**: use slices (`const ITEMS: &[Item] = &[...];`) without a written
length. `cargo xtask lists` rejects non-test const/static arrays with more than ten lines
of entries, except fixed standard or algorithm tables listed with reasons in `xtask/src/lists.rs`.
Built-in themes need only a JSON file in `assets/styles/ui/themes/`, with a unique nonnegative
integer `order` (the picker order) and its own `provenance` line; keep existing order values.
- **Message catalogs** (`assets/locales/*.json`): one message per line, sorted by id. Add your
message anywhere and run `cargo xtask lists --fix`; `cargo xtask lists` (in `cargo xtask ci`
and the Lists workflow) fails on an unsorted catalog or an id that appears twice.
@@ -300,7 +305,9 @@ and a fresh CI run:
- **Design format**: one file per change, never an edit to a shared number (above).
- **New UI strings and attribution rows**: one new file per change, `assets/locales/pending/<slug>.json`
and `attribution/pending/<slug>.md`, instead of editing the catalogs or the ATTRIBUTION.md table;
`cargo xtask fold-pending` folds them on `main` (see the README in each folder).
`cargo xtask fold-pending` folds them on `main` (see the README in each folder). A new English
message also needs every catalog delivered complete (`COMPLETE` in `crates/ui-egui/src/i18n.rs`:
today ar, he, ja, vi, and zh) in the same pending file; `cargo xtask i18n --check` reports any gap.
## Sending a change
Generated
+33 -28
View File
@@ -1692,9 +1692,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099"
dependencies = [
"cfg-if",
"js-sys",
"libc",
"r-efi 6.0.0",
"rand_core 0.10.1",
"wasm-bindgen",
]
[[package]]
@@ -3771,9 +3773,9 @@ checksum = "eec689c0bc40ff2458a5977b6619cb718087084a18e02a131c599b62d05e1a5f"
[[package]]
name = "rustls-webpki"
version = "0.103.15"
version = "0.103.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3c3cf1d8b1e7d4927e2d154c3fcb02979afb9939629c62cd9048d4f07b60ac2"
checksum = "4443b1b6d39d7c663139942cc4558262562d2c84123bb6282ef177009ca8b281"
dependencies = [
"ring",
"rustls-pki-types",
@@ -4208,7 +4210,7 @@ dependencies = [
[[package]]
name = "solidcraft"
version = "0.25.1"
version = "0.26.1"
dependencies = [
"block2 0.6.2",
"eframe",
@@ -4233,6 +4235,7 @@ dependencies = [
"serde_json",
"solidcraft-3dx-client",
"solidcraft-engine",
"solidcraft-gpu",
"solidcraft-space-mouse",
"solidcraft-ui-egui",
"ureq",
@@ -4243,11 +4246,11 @@ dependencies = [
[[package]]
name = "solidcraft-3dx-client"
version = "0.25.1"
version = "0.26.1"
[[package]]
name = "solidcraft-cli"
version = "0.25.1"
version = "0.26.1"
dependencies = [
"image",
"log",
@@ -4259,7 +4262,7 @@ dependencies = [
[[package]]
name = "solidcraft-derive"
version = "0.25.1"
version = "0.26.1"
dependencies = [
"proc-macro2",
"quote",
@@ -4268,7 +4271,7 @@ dependencies = [
[[package]]
name = "solidcraft-doc"
version = "0.25.1"
version = "0.26.1"
dependencies = [
"log",
"serde",
@@ -4285,7 +4288,7 @@ dependencies = [
[[package]]
name = "solidcraft-engine"
version = "0.25.1"
version = "0.26.1"
dependencies = [
"image",
"log",
@@ -4306,7 +4309,7 @@ dependencies = [
[[package]]
name = "solidcraft-geom"
version = "0.25.1"
version = "0.26.1"
dependencies = [
"serde",
"serde_json",
@@ -4315,7 +4318,7 @@ dependencies = [
[[package]]
name = "solidcraft-gpu"
version = "0.25.1"
version = "0.26.1"
dependencies = [
"image",
"log",
@@ -4335,7 +4338,7 @@ dependencies = [
[[package]]
name = "solidcraft-io"
version = "0.25.1"
version = "0.26.1"
dependencies = [
"cadmpeg-core",
"cadmpeg-ir",
@@ -4359,7 +4362,7 @@ dependencies = [
[[package]]
name = "solidcraft-kernel"
version = "0.25.1"
version = "0.26.1"
dependencies = [
"log",
"proptest",
@@ -4379,7 +4382,7 @@ dependencies = [
[[package]]
name = "solidcraft-mcp"
version = "0.25.1"
version = "0.26.1"
dependencies = [
"serde_json",
"solidcraft-engine",
@@ -4388,7 +4391,7 @@ dependencies = [
[[package]]
name = "solidcraft-render"
version = "0.25.1"
version = "0.26.1"
dependencies = [
"image",
"moxcms",
@@ -4402,25 +4405,27 @@ dependencies = [
[[package]]
name = "solidcraft-sketch"
version = "0.25.1"
version = "0.26.1"
dependencies = [
"harfrust",
"serde",
"serde_json",
"solidcraft-geom",
"thiserror 2.0.21",
"ttf-parser",
"unicode-bidi",
]
[[package]]
name = "solidcraft-space-mouse"
version = "0.25.1"
version = "0.26.1"
dependencies = [
"serde",
]
[[package]]
name = "solidcraft-ui-egui"
version = "0.25.1"
version = "0.26.1"
dependencies = [
"arboard",
"egui",
@@ -4450,7 +4455,7 @@ dependencies = [
[[package]]
name = "solidcraft-web"
version = "0.25.1"
version = "0.26.1"
dependencies = [
"eframe",
"egui",
@@ -4561,7 +4566,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd"
dependencies = [
"fastrand",
"getrandom 0.4.3",
"getrandom 0.3.4",
"once_cell",
"rustix 1.1.5",
"windows-sys 0.61.2",
@@ -4919,9 +4924,9 @@ dependencies = [
[[package]]
name = "typed-path"
version = "0.12.3"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e28f89b80c87b8fb0cf04ab448d5dd0dd0ade2f8891bae878de66a75a28600e"
checksum = "9ce898823d8cd0f028662d2f349694b1af0a5cc9be83f1d213a00d3147445e1e"
[[package]]
name = "typeid"
@@ -5358,9 +5363,9 @@ dependencies = [
[[package]]
name = "webpki-root-certs"
version = "1.0.9"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b96554aa2acc8ccdb7e1c9a58a7a68dd5d13bccc69cd124cb09406db612a1c9b"
checksum = "58ec80e73fd8baf57bf0d9615554c75348bda990d6d5bbeab964dd068319fecb"
dependencies = [
"rustls-pki-types",
]
@@ -5841,8 +5846,6 @@ checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650"
[[package]]
name = "winit"
version = "0.30.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6755fa58a9f8350bd1e472d4c3fcc25f824ec358933bba33306d0b63df5978d"
dependencies = [
"ahash",
"android-activity",
@@ -5995,7 +5998,7 @@ checksum = "e450f9b2ed1dff33c94c12589a87338689467b9c4f5d8a5710bd09a847d2c8a7"
[[package]]
name = "xtask"
version = "0.25.1"
version = "0.26.1"
dependencies = [
"proc-macro2",
"serde",
@@ -6293,16 +6296,18 @@ dependencies = [
[[package]]
name = "zip"
version = "9.0.4"
version = "9.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a954114b47a54df49f83d2722814e86b23d4bb1b54a1b90fb7d92b41619ddc22"
checksum = "1156b39d142a34b999c2310a50455e0cb3760bf7efad0122f796d813bee26ccb"
dependencies = [
"crc32fast",
"flate2",
"getrandom 0.4.3",
"indexmap",
"memchr",
"nix 0.31.3",
"typed-path",
"windows-sys 0.61.2",
"zopfli",
]
+6 -2
View File
@@ -5,7 +5,7 @@ members = ["crates/*", "apps/*", "xtask"]
exclude = ["vendor"]
[workspace.package]
version = "0.25.1"
version = "0.26.1"
edition = "2024"
license = "MIT OR Apache-2.0"
rust-version = "1.95"
@@ -80,7 +80,7 @@ cadmpeg-ir = "=0.6.3"
cadmpeg-registry = { version = "=0.6.3", default-features = false, features = ["fcstd", "rhino", "step"] }
# fonts (sketch text outlines; MIT OR Apache-2.0, pure Rust)
ttf-parser = { version = "0.25", default-features = false, features = ["std"] }
ttf-parser = { version = "0.25", default-features = false, features = ["std", "variable-fonts"] }
# Ends a process group with the system call (MIT; already in the tree through zip).
nix = { version = "0.31", default-features = false, features = ["signal"] }
@@ -161,6 +161,10 @@ matext4cgmath = { path = "vendor/matext4cgmath" }
# Keep OpenGL pipelines, resolve textures and CAD callbacks at the same safe sample count.
egui-wgpu = { path = "vendor/egui-wgpu" }
# Deliver trackpad pinch and rotation gestures on Wayland (zwp_pointer_gestures_v1), which
# winit 0.30 never binds and eframe 0.36 still requires winit 0.30.
winit = { path = "vendor/winit" }
# Mutation testing (cargo-mutants, docs/mutation-testing.md): the ci profile with incremental
# builds, since every mutant rebuilds the crates above the one it changes.
[profile.mutants]
+3 -3
View File
@@ -58,9 +58,9 @@
- **Web:** [try it in your browser][web-app], no install.
ARM64 and 32-bit builds, portable zip, .deb, .rpm, Flatpak and the other packages are on the
[downloads page](docs/downloads.md). The downloads aren't signed yet: on Windows choose
**More info**, then **Run anyway** in SmartScreen; on macOS right-click SolidCraft and choose **Open**
the first time. On SolidCraft 0.11 to 0.14, download once by hand; see
[downloads page](docs/downloads.md). The macOS app is signed with a Developer ID and notarized by
Apple. The Windows downloads aren't signed yet: choose **More info**, then **Run anyway** in
SmartScreen. On SolidCraft 0.11 to 0.14, download once by hand; see
[updating](https://docs.solidcraft.io/guide/updates.html#updating-from-011-to-014).
## What works
+694
View File
@@ -80,3 +80,697 @@ permanently.
- Discord: <https://discord.gg/FtU4NQNVDH>
- Releases: <https://github.com/tangency-labs/solidcraft/releases>
- Contributing: [CONTRIBUTING.md](CONTRIBUTING.md)
Status as of **2026-10-14**. SolidCraft supports parametric modelling (sketch →
features → parametric timeline) as an open, pure-Rust, agent-drivable application.
## At a glance
| Question | Answer |
|---|---|
| Where are we? | **M0 and M13 done; M1, M2, M5–M7, M9, M10, M14 in progress.** Sketch with solver and the full SKETCH create/modify set; extrude, revolve (two sides, symmetric, to object), fillet/chamfer (variable radius, chord length, a radius per edge, corner patches), holes, threads (cosmetic and modelled), patterns, mirror, shell (inside/outside/both), draft, loft, sweep, coil, split body and split face, delete face, construction planes, axes and points; persistent naming of faces and edges; parameters and configurations; components, joints, motion studies, exploded views; sheet metal and a plastic enclosure subset; STEP/IGES/3MF/STL/OBJ/DXF; FreeCAD/Rhino import; autosave and crash recovery; desktop and browser (wasm) app, CLI, MCP server. |
| Features | Every registered command by area — [docs/features.md](docs/features.md) (`cargo xtask features`); registry breadth does not establish workflow or geometric depth |
| Reference tests | [Current case count and results](docs/oracle.md): public cases in `tests/oracle/` with analytic or FreeCAD-computed expected values, checked by the reference-test job in [CI](.github/workflows/ci.yml). |
| Tests | Solver, profiles, kernel booleans/blends/measures, expressions, timeline, persistent naming, file formats and migrations, assemblies, sheet metal, engine end-to-end, hostile-input fuzz over every command and headless UI scenarios. `cargo xtask ci` reports the current passing counts. |
| Gates | `cargo xtask ci`: fmt, clippy -D warnings, tests, asset attribution, layering, wasm32 build — green |
| Time to a useful alpha (M0–M6) | ≈ **82 agent hours** remain (sum of the M1–M6 estimates below) |
Optional GPU viewport ambient occlusion is available in View settings and Graphics preferences,
with persistent settings, Performance/Quality graphics presets (Quality combines AO, Fine tessellation and adaptive 2× supersampling; manual combinations show Custom), and the
`view.ambient_occlusion` and `view.graphics_preset` commands. See [display settings](docs/ambient-occlusion.md).
## Scope (owner decision, 2026-10-07)
The issue batch adds preservation of blind pockets in through cuts, associative projected
offsets and plastic face placements, XZ (+Y normal) with a v6 migration preserving older
designs, interactive angle placement, file-picker sketch imports, Home/recent controls,
toolbar overflow, and the remaining component-frame and assembly WIP work. The enclosure
acceptance scenarios now include board resizes; STEP reopening is automated. See [WIP reconciliation](docs/wip-reconciliation.md).
Face-based Extrude Join (including outward Press Pull) now defaults to the picked body,
so edge-touching assembly neighbours stay separate regardless of body order (#226).
In scope, in priority order:
1. SOLID and SKETCH (now).
2. Parameters / functional constraints (done: see `parameters.*`, `expr.evaluate`; unit-aware,
cycles reported with their path, rename follows references, deletes list their users):
user parameters with units and expressions (+-*/, ^,
parentheses, sin/cos/sqrt/min/max/floor/ceil/round, unit conversion), model parameters
d1, d2… for every dimension and feature input, references between parameters with a
dependency graph and cycle detection, re-evaluation on change, comments, favourites,
CSV/JSON import and export.
3. Components and assemblies with joints (M9).
4. SHEET METAL: flange, contour flange, bend, unfold/refold, flat pattern with DXF export, sheet
metal rules (thickness, K-factor, bend radius) (M10).
5. A small PLASTIC subset for enclosures, after sheet metal: Boss, Rib, Web, Lip/Groove, Snap Fit.
Deferred until further notice: MESH, FORM (T-splines), SURFACE beyond what solids need (scope proposed in #772), PCB / 3D
PCB / Package, Render, Animation, Simulation, Manufacture/CAM, Drawings.
## Milestones
| # | Milestone | Status | Hours left |
|---|---|---|---|
| M0 | Vertical slice | done | — |
| M1 | Sketch depth: command coverage implemented — projection/intersect/include as linked geometry (auto-project on faces, lost-reference warnings, break link), full SKETCH create/modify set (slots, polygons, tangent arcs/circles, ellipse, fit/control splines, conic, text, trim/extend/break, fillet/chamfer, offset, mirror, patterns, move/scale, blend curve, centerline), constraints incl. curvature and polygon with over-constraint refusal, Shift-picked line midpoints in Horizontal/Vertical using persisted points and ordinary constraints (#2087), driven/arc-length/linear-diameter dimensions, AutoConstrain, DXF/SVG insert, 3D sketch curves (Project To Surface, Intersection Curve, Isoparametric Curve, Spun Profile), exact free-form profiles (B-spline/NURBS edges, any spline degree, curves cut by crossings), sweeps and pipes along 3D sketch curves, canvases and decals, curvature combs. Exact free-form Extend and certified associative offsets now preserve geometry and IDs through edits, deletion and reopen. Occurrence-frame 3D wires now store explicit coordinate spaces and retain points and analytic fits through moves, refresh, undo and reopen. Constructive sketch solving (Owen 1991, Fudos & Hoffmann 1997) ahead of the numerical solver: points and rigid clusters are placed on the branch the sketch had, so dimension edits and drags keep their solution; edits that would turn a sketch over are refused; drags re-solve only the sketch per frame. Remaining workflow repairs: mixed offset junctions, legacy natural-spline seams, and damaged legacy wire links lacking frame provenance | in progress | 4 |
| M2 | Robust modelling: coplanar booleans in the kernel, holes (placed on faces, at distances from reference edges, and on sketch points), threads (cosmetic, then modelled), patterns, mirror, shell, draft, split, construction geometry | in progress | 16 |
| M1 | Sketch depth: command coverage implemented — projection/intersect/include as linked geometry (auto-project on faces, lost-reference warnings, break link), full SKETCH create/modify set (slots, polygons, tangent arcs/circles, ellipse, fit/control splines, conic, text, trim/extend/break, fillet/chamfer, offset, mirror, patterns, move/scale, blend curve, centerline), constraints incl. curvature and polygon with over-constraint refusal, Shift-picked line midpoints in Horizontal/Vertical using persisted points and ordinary constraints (#2087), drawing snaps to where two lines, circles or arcs cross (#4967), driven/arc-length/linear-diameter dimensions, AutoConstrain, DXF/SVG insert, 3D sketch curves (Project To Surface, Intersection Curve, Isoparametric Curve, Spun Profile), exact free-form profiles (B-spline/NURBS edges, any spline degree, curves cut by crossings), sweeps and pipes along 3D sketch curves, canvases and decals, curvature combs. Exact free-form Extend and certified associative offsets now preserve geometry and IDs through edits, deletion and reopen. Occurrence-frame 3D wires now store explicit coordinate spaces and retain points and analytic fits through moves, refresh, undo and reopen. Constructive sketch solving (Owen 1991, Fudos & Hoffmann 1997) ahead of the numerical solver: points and rigid clusters are placed on the branch the sketch had, so dimension edits and drags keep their solution; edits that would turn a sketch over are refused; drags re-solve only the sketch per frame. Remaining workflow repairs: mixed offset junctions, legacy natural-spline seams, and damaged legacy wire links lacking frame provenance | in progress | 4 |
| M2 | Robust modelling: coplanar booleans in the kernel, holes (placed on faces and on sketch points), threads (cosmetic, then modelled), patterns, mirror, shell, draft, split, construction geometry | in progress | 16 |
| M3 | General fillets and chamfers (curved edges, chains, vertex blends); saddle rolling-ball surfaces now use continuous seam sections and arc-length fitting with shared contact boundaries and bounded accuracy checks; tiny rim edges remain selected instead of nearby wall seams when filleting (#2498) | in progress | 30 |
| M4 | Files: STEP import (done — [docs/step-import.md](docs/step-import.md)), FreeCAD/Rhino solids through cadmpeg (done, desktop, browser and CLI), 3MF export and 3MF/STL import as mesh bodies (done), 3MF with B-rep face tags ([docs/formats/3mf-face-tags.md](docs/formats/3mf-face-tags.md), done), constant-section parametric mesh reconstruction, DXF sketches, OBJ import, PLY/XYZ point clouds as a modelling reference and PLY meshes (done — [docs/point-clouds.md](docs/point-clouds.md), #5151) | in progress | 6 |
| M5 | Persistent naming of faces and edges (docs/book/src/dev/naming.md): faces named from their exact kernel-reported history (sketch curve sides, caps, revolve sections, primitive sides, blends, shell inner walls, pattern/mirror copies; split pieces told apart by the faces around them, lumps of a cut body named after their faces), edges by their faces; fillets/chamfers, sketches on faces, shell/draft/offset/replace faces, hole placements, joint origins and face appearances resolve by name first and warn when the entity split or vanished: done. sheet metal edges by base sketch line and flange side, shell inner faces, sweep and loft roles: done. kernel-reported face history: done (merged faces answer to every name; operations without history yet fall back to geometric names, flagged unverified; format 14 keeps older designs' geometric names). Left: history through sheet metal, plastic, surface and emboss features; FaceSource certificates through history | in progress | 20 |
| M6 | UI depth: selection feedback and origin (done), timeline editing (done: hover and selection highlight modifier faces, including fillets and chamfers; edit feature, history marker drag, dependency-checked single and multi-item reorder, suppress, rename, delete with dependents, re-resolved references; redefining selections refreshes persistent edge/face references while retaining feature identity and dimension names; responsive feature history with width-driven icons/names/title, snapping width resize, bottom/left/browser-stack docking, shared-column collapse, rollback bar, multi-selection and persistent folders), right-docked dialogs (done), live previews for every feature dialog (done), keyboard-first commands with on-canvas value boxes and sketch inline dimensions (done), drag manipulators with automatic join/cut (done: extrude incl. two sides, fillet, shell, hole depth, move, pattern spacing, revolve rotator, extrude taper), dark theme (done), right-click menu with Repeat (done), measure tool (done), section analysis (done), selection filter (done), drag-solve of sketch points (done); appearance controls now preserve body/face/component targeting, named transparent looks, reuse/search and override removal; Browser Expand All / Collapse All (`browser.expand_all`, `browser.collapse_all`) on the design and component menus; preferences | in progress | 6 |
| M7 | Thin extrude (walls along open or closed curves: centre, inside, outside or two sides; mitred corners, crossing walls joined; #721), sweep, loft (incl. to a point), rib and web (to next / depth), emboss (planar faces and exact radial emboss/deboss of bounded orthogonal profiles on complete exterior cylinders/sleeves), thread (cosmetic, and modelled M3–M20 outside and inside: the ISO profile screwed in as a faceted cut), coil (smooth B-spline helical walls), pipe, pattern on path, patterns of bodies and components, replace face (parallel), align, remove, feature copy/paste: done. Unique eligible cylindrical targets are inferred for new Emboss features. Left: general curved-face emboss and exact (unfaceted) modelled threads | in progress | 12 |
| M8 | Surface workspace (#772). Done: Patch (sketch regions; edge loops filled G0, plus `crown`), Stitch, Thicken (planes and cylinders), Extend (straight edges of planar surfaces), Trim (by a plane, a face or sketch curves swept onto the surface, keeping a side or the picked regions; mutual trim of two surfaces, extended to meet and stitched, #767), Delete Face (healing), Boundary Fill, zebra/draft/curvature-map analysis, Surface Extrude/Revolve/Sweep/Loft from open and closed curves, Offset, Unstitch and Reverse Normal; the continuity-driven core (`kernel/src/bridge.rs`, G0–G3 Hermite rows) with **Blend** (`surface.blend`, #764: edge chains along one or several faces, closed rims paired seam to seam or from picked seams, a dialog), **Match** (`surface.match`), **Boundary** (`surface.boundary`, #763 — two sketch curves exact with G0–G3, three or four as the flat patch of their loop, and curve networks: Coons and Gordon surfaces through sketch, 3D-sketch or edge curves, a point for a three-sided side, G1/G2 against the faces along one direction's edges, joined into their body on request; G1/G2 on two sides that meet at a corner waits for the Gregory-type corner), **Fair** (`surface.fair`, CV fairing), **continuity analysis** (`inspect.continuity`, #770; a toolbar tool with edge markers and a legend, and curvature combs along face isocurves) and a multi-section **loft** with per-end continuity and crown, and guide rails on solid and surface lofts (one or two, scaling or stretching the sections between; #201). Also in the Class-A pass: G1…G4 blend curves in the sketch, chord and variable-radius fillets on curved edges (with honest refusals where the fit cannot hold), and a G2 corner patch where filleted edges meet (kernel; the command refuses until the patch's sections can be sewn to the blends' contacts). Left: bias/form-factor fillet sections (design recorded), a Gregory-type corner, surface Fillet between separate surface bodies (#769), Ruled (#762), Untrim (#761), curved-face Extend (#760), and every remaining #757–#772 item | deferred | — |
| M9 | Components and assemblies: New Component / Create Components from Bodies, active component, per-component origin/bodies/sketches/timeline entries, occurrences with transforms, Copy/Paste vs Paste New, nested Browser tree with visibility and isolate; Ground, Move/Copy of occurrences, joints (rigid, revolute, slider, cylindrical, pin-slot, planar, ball) by joint origins with limits and Drive Joints, closed kinematic loops (four-bar, slider-crank: the loop's other joints follow the driven one on its branch, and driving stops where a loop can no longer close), cams (`joint.cam`: a revolute cam drives a slider or revolute follower along a closed sketch profile or the cam's edges, knife, roller or flat followers, worked out again when the profile changes; drives, studies, closed loops, contact sets), As-built Joint, Rigid Group, Contact Sets (driving and motion studies stop where bodies in a set would pass through each other), Motion Study (joint values keyed along a timeline, playback, export of occurrence positions as JSON/CSV), motion analysis (joint values and a point's path charted over a study as value, velocity and acceleration; the parts that collide along a study, with the steps where they do), Exploded views (automatic or by hand, shown without changing placements, and exported as an animation coming apart and back together); interference, per-component physical properties; STEP with assembly structure; URDF export for robot simulators (links with meshes, mass and inertia; joint chains whose values match Drive Joints; docs/urdf.md). Physical properties now measure material-aware component/occurrence placements, descendants and repeated instances, including pending moves and body reassignment offsets; contact geometry and automatic exploded centres respect those offsets. Groundwork done: component tree, occurrences with transforms (instances, Paste New), world placement, active component as authoring frame, ground, Capture/Revert Position, moving bodies and sketches. UI: ASSEMBLE panel dialogs for New Component, Joint (snaps on faces, edges, circles and vertices; animated motion preview; offsets, flip, limits), As-built Joint, Joint Origin, Rigid Group, Drive Joints (live slider), Motion Link, Cam and Interference (overlaps shown red); joints in the timeline and the Browser | in progress | 32 |
| M10 | Sheet metal: flange (base, edge, contour), hem, unfold/refold, convert, flat pattern + DXF, rules: done. PLASTIC enclosure subset: Boss, Rib, Web, Lip/Groove, Snap Fit, Rest, Plastic Rules (library, edit, assign; rule draft and clearance as feature defaults): done, tested against hand-computed geometry. UI: SHEET METAL and PLASTIC tabs with dialogs (live preview, Edit Feature, pre-selection) for Flange, Hem, Unfold/Refold, Convert, Sheet Metal Rules, Create Flat Pattern (flat view with bend lines, bend table CSV/JSON and DXF export with exact circle/arc/line cutouts), Boss, Lip/Groove, Snap Fit, Rest, Manage and Assign Plastic Rules; Fold (bend along a sketch line); flanges meeting at a corner closed at any angle with the rule's gap; edge flanges with their own angle and height per edge in one feature; corner reliefs (notch, round, rectangular, tear) chosen by the rule; Convert to Sheet Metal from a solid or shelled body by its bend edges (flat faces, sharp bends) | in progress | 36 |
| M11 | 2D drawings | deferred | — |
| M12 | Release: cross-platform packages, verification and deliberate publication implemented; original current-UI demo refreshed. Trusted distribution signing and broader performance work remain | in progress | 16 |
| M14 | Configurations: a table of rows (parameter expressions and feature suppressions per row) switched with config.activate (undoable, all or nothing), kept through parameter renames and feature deletes (config.configure, config.table, config.column/row/activate). Per-row body materials and appearances (library looks, custom colour/opacity and clearing overrides), undoable activation and save/reopen: done. Ordered typed configuration rules, atomic validation and structured rule editing: done. Component appearance and certified semantic face style columns, atomic preview/apply and independent-copy remapping: done. Exact constructed sketch-side and immutable imported-face lineage now preserve legacy names and reject retargeting. Left: ambiguous shifted/two-sided caps | in progress | 4 |
| M13 | Never lose work: atomic saves (temporary file, flush, rename; a crash at any moment leaves the old file or the new one) with the replaced version kept as `<file>.bak`; autosave of unsaved changes to the recovery folder every 5 minutes (preference) and after big operations, only when something changed; "Recover unsaved design?" on the next launch (`doc.recovery_list`, `doc.recover`, `doc.recovery_discard`); a kill-mid-save test (process killed while saving a 0.5 MB design 25 times). File format: `"format": "solidcraft/12"`, older formats upgraded step by step (`doc::format`), newer ones refused with a message, out-of-range numbers and broken placements refused; a corpus of designs saved by M0, components-era, joints-era and current builds (apps/solidcraft-cli/tests/corpus) that must open and evaluate as saved; damaged and hostile variants (truncation, bit flips, hostile values, removed keys, repeated features, deep nesting) never panic | done | 6 |
| M15 | Frames and weldments (#4003): structural members along 2D and 3D sketch lines, butt and mitre corners, trim to faces and bodies, end caps, gussets, cosmetic welds and a cut list. Done: the profile library (`frame.profile.list`, `frame.profile.properties`, `frame.profile.insert`): bar, round bar, rectangular and round tube, angle, channel and I-beam, each SolidCraft's own parametric definition with exact fillet arcs and exact section properties (area, centroid, second moments), tested against hand-computed values; members (`frame.member`): one body per straight line of a 2D or 3D frame sketch, following parameter edits, with a built-in profile (its dimensions parameter expressions) or a profile sketch (its drawn material by alternating nested loops), anchor, angle and mirror; each member's name kept with its line. Left: corners, trims, end caps, gussets, welds, cut list, FRAME tab and dialogs | in progress | 60 |
M6 navigation preferences include **Touchpad**: Shift + pointer movement pans, Alt/Option +
pointer movement orbits without a mouse button, and vertical scrolling zooms. Other presets
retain their saved two-finger scroll preference; camera motion is available through
`view.navigate` and modifier-aware `ui.move` automation.
With the **Fusion** preset and two-finger pan enabled, two fingers pan and Shift + two fingers
orbit freely, with pinch zoom and mouse bindings unchanged. The shared navigation handler
applies the same gestures to model and Render views and blocks orbit on flat pages.
UI redesign (#2016): the File/start view (#2027) uses shared light/dark navigation,
action tiles, recent rows and sample cards, with recovery review and Save As/Export
entry points. Document loading, sample caches and recovery safety retain their
existing command paths.
M11 precursor: File → Export Current View as DXF exports shown placed bodies and sketches from the current
camera as a 2D millimetre drawing, with hidden edges omitted or dashed. Vector occlusion splits
partly hidden edges and includes curved silhouettes. Repeated part meshes and triangle
hierarchies are shared; bounded desktop preparation and occlusion use up to eight workers.
Curves are approximated; drawing sheets,
annotations and exact projected curves remain deferred. See [view DXF](docs/view-dxf.md).
Drawing foundations: [RFC #860](https://github.com/tangency-labs/solidcraft/issues/860)
and the [foundation ledger](docs/drawing-foundations.md) track the bounded implementation
packages. The first geometry increment defines validated section records in a plane-local
frame; the ledger separates that contract from section producers and the Drawing workspace.
Desktop view DXF export runs in the file-operation worker with five-stage progress and
cooperative cancellation. Curve tolerance (0.0001–1 mm, default 0.01 mm) is remembered alongside
the hidden-edge setting. Cancelled exports preserve the model and the previous destination;
completed drawings publish atomically. The browser still exports synchronously.
## Interactive modelling
- Modelled threads preview their cut before OK using the background worker on desktop.
Browser users apply the cut with OK to avoid blocking on every edit.
- Thread resolves a suggested metric size when a cylindrical face is picked. Diameter and
pitch selectors expose the existing metric designation parameter; custom designations stay
editable, and Automatic size returns to the face's suggestion. Cosmetic/modelled and
full/partial-length options remain available. This does not add tolerance classes or
left-hand threads.
- New Body extrusion and face-offset previews show completed intermediate geometry while a
drag continues, then catch up to the exact final value. Changes to the selected geometry,
operation or feature still discard obsolete results. Distance arrows and their value boxes
follow the current frame's input.
- Large fine modelled threads use pitch-based helix resolution and tighter faceted
reconstruction fallbacks, preserving thin crests and closed shells on large shafts.
## Physical material data
- Physical material card validation (#923/#922) provides typed SI mechanical and
thermal data, per-property sources/conditions and isotropic/orthotropic stability
checks through read-only `material.properties.validate`. It does not assign or
persist properties, provide a solver or enable rendering; see
[the contract and staged follow-ups](docs/physical-material-cards.md).
- Directional elasticity (#994) queries the validated card in material-local axes
through read-only `material.properties.directional`, with source/condition review.
It does not assign body frames, predict structural behavior or enable a solver.
## Library foundations (#785, #786, #787)
- Local scalar libraries (#846) inspect/export bounded portable catalogs and copy exact
selected appearance/material revisions into existing design definitions in one undo step.
Appearance offers local loading/search/export; physical materials use existing commands.
This slice is independent of the render stack and does not change the document format.
See [the contract and limits](docs/book/src/dev/local-libraries.md).
- Proposed phases cover offline bundled/project/user packs, physical materials and
appearances, editable wood mapping, and parameterized component/assembly families.
Stable identity/revision, copied design definitions, provenance and resource limits
apply from the first implementation. Existing material, appearance and standard-part
commands remain the application paths. See [the proposal](docs/book/src/dev/libraries.md)
for source/license review and acceptance gates. This is planning only: pack loading,
texture rendering and expanded component families are not implemented by this entry.
## Render foundation
- Original starter appearances (#1722): 34 opaque recipes through existing commands, with six explicitly unavailable glass recipes and preserved legacy looks; see [the contract](docs/render-starter-appearances.md).
- Bounded linear film accumulation (#1696) supplies caller-admitted mean/variance storage and complete-pass views; actual progressive consumers remain separate. See [the film contract](docs/render-film.md).
- Definition-local visual mapping (#1214) supplies a bounded numerical frame, physical repeat coordinates and a deterministic one-time grain-axis suggestion. It adds no saved record or texture consumer; see [the mapping contract](docs/render-visual-mapping.md).
- Explicit texture normalization (#1218) produces completed float RGBA with
role-aware linear color/data semantics, bounded matrix/TRC ICC conversion and
opt-in EXIF orientation. It retains high-precision raw samples and records lossy
gamut clipping only when explicitly requested. It is not a renderer/resource
consumer; see [the supported policy and limits](docs/render-texture-normalization.md).
- Opt-in opaque PBR (#1046) connects persisted surface parameters to the integrated
product viewport and CPU PNG, using a fixed direct-light studio. Geometry and mass
stay unchanged. HDRI, transmission and textures remain separate gates.
See [the consumer and limitations](docs/render-opaque-pbr.md).
- Combined integration is tracked in #842, with independent scalar libraries in
#863 and richer PBR/material-card transport in #1086. See [phase boundaries and validation gates](docs/render-integration.md).
Render/library consumers use the merged asynchronous picker (#1127). Material-card
UI (#1094), texture mapping and HDRI lighting remain explicit follow-ups.
- R4a adds bounded CPU product-image jobs, cancellation and atomic PNG export through
engine commands, the Render panel, CLI and persistent MCP. Immutable captures and
results stay outside persistence/undo; native workers and cooperative browser tasks
share the same work protocol. See [jobs, limits and export](docs/render-jobs.md).
- R3 adds an overlay-free product scene and the integrated Render workspace, with
runtime GPU host capabilities, per-document drafts and named camera/background
controls. Design keeps its camera and drawing policy. Raster transparency remains
approximate; PBR and environments are later slices. See
[workspace and scene contracts](docs/render-workspace.md).
- R2 adds bounded named render setups in document format 21 and the read/save
`render.settings.get/set` commands. Proven render-only changes preserve geometry
and prepared world data through undo/redo and checkpoint restore. This slice does
not add a Render workspace, PBR, environments or image jobs; see
[settings and refresh policy](docs/render-settings.md).
- Bounded PNG/JPEG texture admission (#900) validates in-memory sources and returns
completed RGBA8 pixels with explicit color/data roles. It is an input utility only:
ICC/16-bit normalization, local wood mapping, resource persistence and the renderer
consumer remain separate work. See [limits and licensed-file probes](docs/render-texture-input.md).
- The initial opaque surface numerical contract for #1004 provides bounded linear
color/metallic/roughness/IOR admission and an original tested direct-light BRDF.
The numerical module alone advertises no capabilities; the installed consumer above
provides rendering. See
[the model, evidence and remaining consumer gates](docs/render-surface.md).
- A bounded cooperative Radiance RGBE input utility is available in L1 render;
it does not yet enable HDRI/PBR rendering or a document import command. See
[the input contract](docs/render-hdr-input.md) and #813 for integration work.
- R1 adds renderer-independent backend/profile metadata, strict request resolution and
bounded image/scratch admission checks, exposed by the read-only `render.backends`
command. It describes the current CPU raster snapshot path without evaluating the model.
The legacy Design snapshot route remains unchanged. Later slices above provide the
workspace/jobs and opaque PBR; HDRI and optional engines remain future work. See [the contract](docs/render-backends.md)
and [the phased proposal (#620)](https://github.com/bherbruck/solidcraft/issues/620).
## Dimensioning and error reporting
- Operation length fields share design-unit defaults and input evaluation, including secondary
distances, thin walls, blend controls, sheet/plastic rules, joints and motion keys. Canvas
handles and sketch previews use the same lengths as committed geometry. Existing stored
millimetre values retain their size when edited in a design using another unit (#3271).
- MCP `execute` accepts `verbose: false`, sharing the compact reply helper used by
`batch`: body changes and created sketch IDs stay, while repeated lists are omitted.
Both tools retain full replies by default.
- Sketch Create groups drawing variants under Line, Rectangle, Circle, Arc, Slot,
Polygon and Spline. Each open part remembers its last interactive choice per family
across sketch sessions and document-tab switches; closing the part resets these UI choices.
- Inscribed, circumscribed and edge polygon tools preview their actual outline before
placement, including orientation and the selected side count.
- Construction (X) preserves the active sketch drawing tool, picked anchors and inline
dimension values, so line type can change while a shape is in progress.
- Planar sketch construction previews and hover feedback keep the same dashed pattern as
committed geometry; centerlines retain their dash-dot pattern.
- Point has a default Sketch CREATE toolbar button alongside the existing drawing tools.
Saved custom layouts are preserved; Reset Toolbar restores the default Point button.
- Construction planes cannot take an origin-plane name (XY, XZ, YZ, Top, Front, Right). Plane
arguments reject such a name when an older design's construction plane already has it. Use
the other alias, the construction feature's numeric ID or an explicit plane; existing
stored references keep their saved meaning. Section Analysis uses the same check.
- Sketch text can be edited from a letter interior or outline's context menu or the Edit Text command.
Interior selection requires every profile boundary to belong to the same text source;
the editor highlights the whole source without replacing profile selections.
Content, baseline X/Y, height and rotation update the original text source in one undo step;
cancelling or rejecting an invalid value preserves the sketch. Position and height fields
use the document units captured when editing starts; generated outlines remain associated
with their text source, and untouched inputs preserve their saved internal values.
Dragging a text outline moves the entire source in one undo step; Escape restores the
gesture. Move/Copy on a selected text outline provides unit-aware X/Y distances and rotation
about its baseline; copies keep an independent editable text source.
- Repeating the initial point of a planar multi-point sketch drawing tool is neutral: the tool
waits for a distinct point without a degenerate-shape error or history entry. Typed input
and programmatic commands retain their validation.
- Circular-pattern and angled-plane axes reject explicitly supplied malformed or expression
origins instead of silently rotating about zero. Numeric origins remain in millimetres;
associative axis expressions and construction-axis references remain unsupported.
- Single-line and rectangle-side dimensioning supports selecting a line or its two endpoints.
Type a value and press Enter to commit one undo step; rejected values remain editable and
cancellation leaves the sketch unchanged. Fit keeps geometry clear of the Sketch Palette
and navigation controls, including enlarged displays and nested pending placements.
- Sketch Dimension takes a line and a circle or arc (#1803): it measures from the line to the
circle's edge (the gap, 0 when tangent, or how far the edge reaches past a line that cuts
it), drives it like any other dimension and keeps the circle on its side of the line.
- Sketch Dimension takes a point and a circle or arc, or two circles or arcs (#4064): it
measures to the circle's edge (from the point, or between the two edges: the gap, 0 when
they touch, how far they overlap, or the narrowest gap between nested circles).
- Sketch annotations, live drawing lengths and Measure use document units. Inches show
three decimals and retain a meaningful fourth digit. Bare length dimension entry captures
the current design unit; changing units leaves existing geometry and expressions intact.
Component/canvas distance controls, sketch cursor coordinates, flat-pattern dimensions
and pocket depths, interference volumes and parts-library lengths also use design units.
- Curvature and Polygon constraints accept complete preselected operands. Fix/Unfix
consumes complete point/curve selections consistently; mixed or ambiguous selections
retain the picking workflow. Rejected constraints preserve selection and undo history.
- Contextual error reporting: a **Create Issue** action beside feature errors opens a
reviewable GitHub issue draft with the error, operation settings, build diagnostics and
useful reproduction context. The draft is editable, with optional capture of the actual
viewport and copy/save controls. Opening GitHub does not submit the issue. Help also exposes
reporting for unexpected results that did not produce an error.
- The header exposes **Report a bug**, including an accessible compact control on
narrow windows. It opens the same editable report and screenshot review without
changing the active model or a pending dimension.
- Crash reports: every panic (in a command, in the kernel, anywhere else) and every unclean
exit (abort, stack overflow, kill: found at the next start through a locked per-run command
journal) leaves a local report with the backtrace, version and commit, the command and the
design that reproduce it (`solidcraft-cli crashes replay <id>`). Repeats are counted, not
rewritten; at most 20 reports, 50 MB and 90 days. The app shows them after a crash (Help >
Crash Reports…) with a reviewed issue draft; agents read them through
`diagnostics.crash_reports`, the MCP `crash_reports` tool or the CLI. Nothing is sent
anywhere. See [crash reports](docs/crash-reports.md).
- Agent chat (off by default, desktop): a side panel that drives a coding agent the user
already has (Claude Code through its ACP adapter, Codex, Gemini CLI, OpenCode, Grok Build, …) over the
Agent Client Protocol, under the user's own login; SolidCraft stores no keys. The agent works
through SolidCraft's MCP tools on a gated endpoint of its own: file actions wait for Allow or
Deny, crash reports are off limits, 24 changes per message, one undo step per message, and
the agent's whole process group ends with the panel or the app. Docks left or right,
minimises to a strip. Grok Build discovery includes `~/.grok/bin` and reuses the user's
Grok login. See [agent chat](docs/agent-chat.md).
- Command scripts from designs (#886): `timeline.export_script` (CLI `solidcraft-cli script`)
writes a design's history as a script that `eval` and `run` replay into the same design —
user parameters, units, sheet metal and plastic rules and materials as their own commands,
then each feature through `timeline.add` with its ids, names and dimension parameters kept,
so every feature kind replays exactly and a failing feature fails the same way. Trimming the
script after a step gives the design at that step. Appearances, folders, views and
configurations are listed as left out; components and joints are not supported yet.
## 0.2.0 release batch
- Includes the new axis navigation, adaptive sketch drawing/picking, origin-corner repairs,
durable supported profile/face references, endpoint dimensioning and contextual reporting.
- Smooth ruled-wall display joins are hidden only within the supported geometric certificate;
authored splits and actual creases remain protected. Wireframe retains physical edges.
- Paste New uses a bounded current-geometry comparison for supported convex line/circle
prisms with separated circular holes; unsupported shapes retain the existing strict check.
- Common-bore Union retries check additional boundary curves before recutting the bore,
preventing the reproduced thin-web loss. Unknown additional trims refuse; inherited
common-cylinder trims retain their existing policy, so this is not a general Boolean proof.
- Exact full-path assembly joint editing remains separate work and is not part of this batch.
- Stable 0.2.0 is published: all release payload checksums, native cold reopening, deployed
web app and both Flatpak architectures were verified. The replacement README demo uses
the original electronics enclosure story and animated pointer in the actual English
0.2.0 UI, at 4× playback. Publication follows [the release workflow](docs/releasing.md).
## 0.2.1 critical fixes
- Separated multi-profile Join/Cut extrusions into one solid target batch their tools using
conservative construction bounds, avoiding a Boolean rebuild for every profile. Live
extrusion previews build only their tools; confirmation validates the final Boolean.
- Coplanar selected body faces share one linked sketch and one extrusion. Automatic Join/Cut
keeps the evaluator's participant scope, including parts of an empty imported component. Desktop OK/Enter
computes on a scratch session in the background, with atomic acceptance and cancellation.
Planar section stitching projects lines/arcs analytically and removes duplicate endpoints.
- Imported rotated face groups can check all full start-face seams in one guarded
construction. Separated tools may batch a Join when each meets the same single body;
nearby uninvolved bodies retain the original contact decisions. Regression comparisons
cover all four extrusion operations.
- Inward multi-face cuts retain every eligible target and subtract separated tools together.
Safe interior classification handles roundoff at shared imported line/arc endpoints.
Straight extrusion feedback caches existing face/profile triangles and updates the display
directly, including a newly opened STEP's single identity component placement; other
extents, moved or repeated components and curved sketch profiles keep the Engine preview.
- The extrusion fixes retain tracked Boolean history and the current `solidcraft` packages.
Confirmation and tool previews use main's shared background calculation. Main's collapsed
blend-wall refusal and its tests are retained, including smaller valid radii and mirrored parts.
- Axis view and navigation controls stay anchored to the viewport when feature dialogs or
the command palette open, at normal and enlarged display scales. Fit still accounts for
dialog coverage; covered controls do not receive clicks through dialogs.
- Eligible planar faces survive fillet, chamfer and shell operations with exact source
certificates. Sketches placed directly on the enclosure wall and inner floor follow
width and wall changes, including after the USB cut and cold reopening.
- Remove artificial straight-wall and rounded-corner subdivisions left by shell and
extrusion cuts. Identical generated wall segments span adjacent slabs as one physical
face, with exact full-height supports and boundary stitching. Preserve authored face
splits and face appearances. Permanent regressions cover material, STEP, reopening and
unaffected bodies across the extrusion end plane.
- Feature dialogs use the available screen height for their fields, with OK and Cancel
outside the scrolling region, including enlarged display scales.
- Design format 13 records shell-face attachments. Older designs remain readable;
newly saved designs require 0.2.1 or later. Ambiguous or unsupported faces still refuse
attachment rather than guessing a plane.
- Saved projections from a removed strip retain their geometry and report the lost
reference. Explicitly reselect the wall to repair that projection.
## Workspace layouts (#2029)
- General preferences save Floating or Compact using the universal UI containers.
Compact joins the workspace selector and ribbon, docks the content-hugging Browser
flush beneath them with a square join, and opens tool sheets below the compass.
Sheets remain draggable, rounding all corners away from their right dock; footer
backgrounds follow the same corners. A separate preference hides ribbon icon labels
for a shorter ribbon in either layout.
Assistant keeps the outermost edge and History keeps its chosen dock. Switching
retains the active tool, camera, selection and design; system windows and menus
keep their existing behavior.
## View navigation
- Navigation has an opt-in Free orbit preference for mouse and 3D-mouse rotation through
both poles with roll. It defaults off, preserving existing preset snapping and pole limits.
The SolidWorks face menu offers Normal to Selection (`view.normal_to`), shared with Look At
and Ctrl+8, including repeat-to-flip, preserving scale and projection.
- Desktop Ctrl/Cmd +/- and 0 change or reset the saved UI scale. The scale slider keeps
its layout stable during a drag and applies the selected scale on release.
- OpenSCAD navigation preset: left drag orbits, right/middle drag pans, Shift+right/middle
drag zooms, and the wheel zooms. Available in the shared desktop/web Navigation preferences.
- Compact clickable signed X/Y/Z axis tips, smooth drag-to-orbit, and Shift-orbit snapping
to 26 standard and diagonal views. Pointer motion accumulates independently of a lightly
damped spring, with a boundary margin to prevent flicker. Z-up/Y-up and the nearest square
top/bottom heading are preserved. Diagonals include 45-degree edge and isometric corner views.
## Known limitations
- Scheduled and manual CI scan locked dependency advisories, bans and sources with
cargo-deny. Vulnerabilities fail the scan; unmaintained crates warn. Local vendored
patches require separate upstream review because advisory databases cannot version-match
their path dependencies. Pull requests retain the existing licence checks.
- Associative shell-face sketches require a unique certified planar source. Nested shell
attachments and ambiguous coincident sources remain unsupported.
- G2 fillets: exact quintic blends of straight edges between planar faces, with one planar
end face at each end, including sloped ends (#2708). The UI and `solid.fillet` expose
`curvature` (alias `g2`); the size is an equivalent circular setback. Curved faces/edges,
multi-face ends and corner junctions remain unsupported.
- Fillets and chamfers: constant, variable-radius and chord-length fillets; a radius per edge,
rounds next to earlier rounds of another radius, and smooth corner patches where three rounds
meet (a sphere for equal radii); perpendicular corner fillets after a closed ring of earlier
rounds preserve the ring's radii and the enclosed planar face (#1557);
mitres between separate rounds of the same radius keep their endpoint tangent, so a later
fillet can select an upright and its adjoining bottom mitre as one chain (#2422);
straight edges (convex or concave) between planar faces with perpendicular
planar end faces (equal-distance chamfers also meet sloped planar end faces, including inner
basin rims within the rim width); convex fillets also meet sloped planar ends and reflex
corners around pocket rims, with unequal wall slopes and extensions confined to the face;
connected equal-distance chamfers also trim each other across unequal sloped rim walls;
curved chamfer chains with straight planar ends can terminate across two existing planar
bevel faces, splitting their shared seam; picks on the same tangent chain are applied once (#1303);
whole smooth loops of a planar face, picked whole or by one edge (tangent
chain), including circles and walls at any angle (boss bases and tops, bores, pocket floors,
plate outlines), loops with sharp corners between straight or mixed arc/line edges (straight
blends meet in mitres; perpendicular curved walls use offset intersections, with D-rim removal
checked within 0.1% of analytic offset slices), runs of
neighbouring edges along a planar face's loop (two top edges of a box: mitred, ending square;
with the edge between them too, the corner becomes a sphere octant),
rounded corners rounded again (sphere octants, tori at concave corners); every edge of a
convex planar body or of an extruded part; fillets inside patterns; closed chains of curved
edges between any two smooth sides (a branch pipe on a main pipe), by a rolling ball (the
blend a rational B-spline through exact arcs), closed or ending at planar faces square to the
edges, where straight or curved cap edges are trimmed to the contacts (the straight edge
between two overlapping extruded arcs); knife edges, where the two faces have opposite
normals (a wall that runs out tangent into a face: the ball that fits there); an edge that
runs out along an end face tangent to one side (the arc top edge of that wall), cut where the
blend meets it; rounds that end in an earlier round on curved faces, in any order (the rounds
of two edges at a vertex meet in a crease, as on a box), picked together or one after the
other, except a round after a round of the edge between the wall and a flat face that it
would run over; the three edges at a vertex of any smooth faces, of one radius, end in a
piece of sphere. A limiting blend that collapses a side wall into coincident boundary
curves is refused as too large rather than returning an unmeshable face (#1113).
- Booleans: prisms along one direction (plates with holes, slots, patterns of them, equal
sections stacked end to end) are combined exactly in 2D. Qualified axial cuts preserve
annular holes with overrun cutters, including inward Press Pull after a joined extrusion;
curved wall qualification rejects false transverse axes instead of filling holes.
Bodies touching along one whole face
(a part and its mirror image) are stitched; coincident planar faces are pushed apart when
their neighbours are planes or cylinders. Other coincident curved configurations can still
fail. Bounded containment classification preserves fully internal cavities and nested
material islands independently of shell order, with STEP round-trip and material-membership
regressions. Near-contact curved shells use the general boolean path rather than a
containment shortcut. Spheres are built from six pole-free patches.
- Mass properties come from fine tessellation (curved faces within ~1e-4 relative); triangles
that cut through curved faces (trimmed faces after booleans) are split onto the surface first.
- STEP import (our own reader, crates/kernel/src/step_in) reads solids (B-rep with analytic and B-spline geometry), units,
product names, colours and assemblies; analytic offsets on planes, cylinders, cones, spheres
and regular tori are read exactly (signed/nested distances, units and face sense). Freeform
offset surfaces and pcurve-only edges are not read yet,
and assembly components are flattened into bodies. Closed periodic faces (torus, B-spline
bands) are split in two for meshing; measure() uses a finer tolerance for small radii.
- Persistent naming follows the kernel's exact face history (docs/book/src/dev/naming.md):
references resolve by name first, follow splits and merges, and warn when the entity split,
merged or vanished, or was found by geometry only (operations that report no history yet).
New planar sketch attachments use exact box, extrusion cap/side and immutable imported-face
source certificates with checked target and author occurrence paths. A missing or changed
source fails explicitly; Redefine Sketch Plane previews reattachment or a fixed plane while
retaining current geometry and dimension identities. Unsupported modified faces need an
explicit fixed plane. Legacy attachments retain their original resolver behavior.
- Modelled threads are cut as a faceted body (curved faces within 1/200 of the pitch); Extrude
and Revolve To Object on a curved face cut the tool back to the target's surface.
- Explicit sketch breaks preserve exact ellipses, fit/control splines (including high degrees)
and conics; analytic trim/break also sees free-form cutters. Free-form curves cut at a tangent
touch (no clean crossing) enter that profile as polylines.
Sweeps along 3D sketch curves follow their polyline (smooth walls when the path is smooth).
A sweep with a twist, an end scale or a parallel or direction orientation (#771) follows its
path that way too, even along sketch lines and arcs: B-spline walls through stations, ruled
walls through denser stations where the path has corners or the profile has holes.
Guide rails (one or two, #771) do the same: each station meets every rail once, and the rail
turns the profile and scales it (or stretches it across to the rail) against the start; two
rails carry it between them. Rails along a path with sharp corners are refused for now.
- Extend intersects exact ellipses and rational/high-degree splines without moving the line or
circular support. Associative free-form offsets have a whole-span 0.002 mm normal-distance
certificate and refine within bounded node limits while retaining existing IDs.
At the node limit, geometric certificate subdivisions accommodate unequal spline parameter
speeds without changing stored nodes or relaxing the distance tolerance (#971).
Associated offset fit nodes stay hidden from display, picking and snapping; dragging the
editable source updates the derived boundary live. Break Association restores point editing.
Singular, self-intersecting and ambiguous curves refuse atomically; mixed junctions and nonsmooth
closed natural-spline seams remain limitations. New explicitly closed fit splines and closed
offset outputs use periodic C2 interpolation, supporting repeated certified offsets; older
natural splines are preserved. Clicking the starting fit point deliberately closes a new loop.
Newly captured adaptive profile references with complete source coverage retain their outer
and hole identities through span-count changes, including parameter edits after extrusion.
Partial, intersected or ambiguous boundaries do not qualify for these whole-source references.
Legacy curve-span multisets remain exact and unchanged; already-lost selections may need
reselection. Format 12 stores the new bounded whole-boundary references.
Projected analytic boundaries follow nested loop identities through resizing, including
stationary holes and rounded corners. Supported convex, tangent line-and-arc boundaries
can lose or regain corner arcs during an inset while preserving reserved curve identities
and linked profile selections. Format 12 saves those associations; compatible older closed
offsets upgrade structurally without changing their curve IDs. Breaking an association
freezes its current boundary and materializes downstream profile references. Child offsets
of a boundary with retired arcs still require breaking its association first; mixed or
nonconvex junctions and retained references to disappearing individual arcs remain limited.
- Extrude and Revolve editors retain original direction, extent expressions, explicit targets,
axes, From/To inputs and All-profile intent. No-op edits preserve downstream dimension names
and selected occurrence frames; cancel and successful edits preserve one-step undo history.
Placed feature edits preview through the edited timeline entry, and cylindrical Emboss guides
use the sketch's actual target, author or uniquely placed third-component frame.
Revolve rotators follow the actual signed axis and support symmetric and two-sided extents;
dragging a To Object extent converts its derived value to an explicit angle. Legacy reversed-axis
symmetric geometry is preserved through format 11's explicit legacy convention. New revolves
use the sketch-normal direction for each selected profile, including To Object and curved
target trimming, independently of the selected axis sign.
- Cylindrical emboss/deboss wraps bounded orthogonal line profiles, including holes, concave
outlines and nested islands, onto complete exterior cylinders or coaxial sleeves with exact
radial walls. New features infer a unique eligible cylinder when the face field is empty;
ambiguous targets require an explicit face. Saved target
and author occurrence paths retain the chosen placements; missing/split faces refuse rather
than retarget. General free-form profiles, seams, stepped cylinders and other curved surfaces
remain unsupported. STEP round-trip and independent radial/volume checks cover this subset.
- Shell and offset faces work on bodies of planes, cylinders, cones, spheres and tori (convex or not:
filleted boxes, bosses, domes, countersinks; corners where four or more planes meet, such as a
floor falling to a drain, as long as the corner's edges are all convex or all concave); draft on convex planar bodies and on walls (planes, cylinders → cones) between caps; lofts through three or more sections are smooth (B-spline sides through every section), two
sections ruled. Circular-meridian barrels retain curved inner walls through either axial
opening (#2421). Solid lofts preserve holes through sections with matching hole counts
(#2435), including inner walls and caps with openings; a hole cannot appear or disappear
between sections, and sections with holes cannot collapse to a point.
- Sketch corner tools: fillet and all three chamfer modes pick a connected corner even when
its endpoint overlaps the fixed origin or a loose point. Ordinary drawing still snaps to
the origin; clicked UI regressions verify geometry, closed profiles and undo.
- Sketch display: drawing, picking, highlighting, tool previews and profile shading share
adaptive projected curve boundaries. Fit, zoom, display scale and placed sketch frames
invalidate the display cache without changing CAD geometry or timeline history. Work
budgets and clipped paths prevent unbounded sampling or invented edges across the eye plane.
The Sketch Palette scrolls its options on short windows and enlarged displays while
keeping constraint status and Finish Sketch visible.
- Face projection: closed boundaries have a deterministic outer-first order. Refresh matches
existing geometry before assigning positions, retaining saved curve IDs and constraints
across enumeration changes and resize, including concentric circles. Ambiguous identities
retain the last geometry and report a lost reference; permutation matching is bounded.
- Project accepts complete supported preselection in one undo step. Visible external sketch
curves and points retain their source sketch identity; model geometry, axes and planes use
the existing linked projection commands. Rejection preserves the document and selection;
mixed selections retain ordinary tool-first picking.
- Inline sketch dimensions: Tab and Shift+Tab cycle within the active shape's value boxes,
selecting visited values for replacement. Expression completion retains forward-Tab
priority; real keyboard regressions cover rectangles, lines and single-value circles.
Typed lengths, radii, line angles, signed arc sweeps and slot lengths persist as constraints
and expressions through save/reopen. Shape creation and its dimensions form one undo step;
rejected values keep the editable field focused.
- Repeated components: Browser selection, visibility, properties, copy and Move/Copy use
checked occurrence paths. Active nested occurrences author planar sketches and solids in
their selected frame. Pending moves compose through parents; dialog cancellation restores
its selected move. Source materials and body/face appearances follow transformed instances.
Shared nested definitions remain shared. Deep Paste New copies reachable definition graphs,
independent feature/input histories, styles and internal motion records, with bounded geometry
checks and explicit external-link notices. Paste New selects the copy while preserving the active
authoring context. Imported periodic STEP seams survive placement and reexport with shared
topology and appearances intact. Recorded body transfers preserve historical Join/Cut membership,
material, placements and machining data through edits, copying, undo and reopen. New 3D wires
record their coordinate frame; legacy wires migrate from known provenance without changing
coordinates. Broken legacy links with missing provenance can require explicit refresh or relink.
See [occurrence workflows](docs/occurrence-workflows.md).
- Toolbar drops on panel labels, gaps and margins append commands with insertion feedback;
button drops keep insert-before ordering.
- Parameters and Configurations have distinct actions in the SOLID toolbar's CONFIGURE panel.
Parameters opens the user/model variable editor; Configurations opens the configuration table.
Configure remains available in the panel dropdown.
- Parameter creation supports Enter with validation and continued keyboard entry. Shared
expression autocomplete supports Up/Down selection, Enter/Tab acceptance and Escape dismissal;
accepting a suggestion does not submit a parameter or trigger viewport shortcuts.
- Movable window title bars follow the app's dark/light header palette. Radial right-click
menus are opt-in in Preferences > Navigation; ordinary context menus remain the default.
- Desktop distribution: running Windows windows and executable resources use the app icon;
packaging validates icon resources. Nix installs launchers, MIME data and generated icons,
with explicit launch apps and Vulkan-loader/driver discovery. Flatpak feed instructions
register the required runtime source; release checks exercise desktop modelling on X11/Wayland.
- OpenGL rendering clamps effective anti-aliasing to 1x across UI pipelines, textures and CAD
callbacks to prevent black frames. Other backends retain the requested sample count, and
stored preferences remain unchanged.
- Configuration rules: ordered typed conditions can drive parameters and suppressions or
restrict values. Preview explains effective values without modifying the document; applying
rules validates rows atomically. Length expressions retain their authoring units across
document-unit changes. The UI supports structured All/Any/Not conditions and rule ordering.
Component styles and certified semantic face styles are available; unsupported lineage refuses
atomically, and stale certified face paint cannot jump to another surface. See [configurations](docs/configurations.md).
- Sheet-metal material: inherited holes, crossing edge notches, overlapping cuts and retained
islands share the same boundaries in flat preview, DXF and unfolded solids. Detached material
pieces survive unfold/refold as one logical sheet group, including split flanged sheets.
Cut-outs made in the flat pattern cross bends at any angle or curved: their edges fold to
helices and curves on the bend, their walls square to the sheet. Free-form bases use bounded
sampling.
Parallel prismatic partial-depth cuts retain pocket side and depth through transfer and
unfold/refold, with separate pocket contours in preview and DXF. Planar Intersect preserves
exact holes and retained islands, including the union of multiple selected profiles, and
records complementary depth layers as pockets while retaining the stock gauge. Unsupported
tapered or bend-crossing machining refuses atomically instead of restoring material later.
Sketches attach to a sheet's flat faces (base and flanges, either side) by panel, in the
flat pattern's coordinates, and follow it through rebuilds and unfold/refold.
A flange on another flange's far edge (a return) follows that flange's closed end and keeps
clear of the flange beside it, and the returns of one feature are mitred toward each other
with the rule's gap where their flanges meet at a corner; returns of separate features, and
flanges on returns, are not closed toward each other.
- Rolling-ball fillet accuracy: independent offset-cylinder tee references check surface
distance, actual trimmed tessellation, supporting-cylinder contacts and tangency at two
scales. The measured trimmed-part error is below 0.0001 mm; this is an analytic geometry
check. Under-resolved fits return an error.
- Contact driving checks the trajectory between clear endpoints, including linked joints,
playback and sparse motion exports. Checks use bounded tessellation samples, not exact
continuous collision detection; local thin walls and small details remain limitations.
See [contact-set limits and recovery](docs/contact-sets.md).
## Assembly dragging
The design's first part is grounded when it is made, and a left-button drag repositions a free part (`occurrence.drag`: one undo step, exact occurrence paths including repeated jointed definitions, any floating-chain member carries the chain, grounded parts and joints hold where present, Escape cancels).
## 3D sketch bridges
3D sketch drawing snaps to points on other visible sketch planes without flattening them onto
the active plane. Bridge endpoints capture their source positions; associative endpoint links,
construction-plane selection of 3D wires and loft guide rails remain separate work.
Feature dialog header chevrons collapse and restore the form without discarding selections
or edited values, including the Appearance panel.
## Construction on 3D paths
Plane Along Path has a viewport path selector, fractional position, live preview and timeline
editing. Construction planes and points resolve drawn 3D wires without applying their sketch
plane a second time. Curved paths use sampled segments; multi-curve chains, absolute distance
and reference-object placement remain separate work, as do loft rails and centerlines.
## Design properties (#1015)
- Designs carry project, part number, revision, author, organization, description and licence
in an optional `metadata` object (File → Design Properties…, `document.metadata.*`,
`inspect_design`). STEP and IGES headers and 3MF model metadata take the fields their format
has a place for. Other tools keep their own data under a reverse-DNS key, kept as it is
through open, edit and save and never exported. See [design properties](docs/book/src/guide/files.md#design-properties).
Per-component properties (a part number per component) can follow with the same type.
## Document-opening performance
- Desktop STEP import prepares consecutive independent solids in bounded batches with up
to eight workers, retaining serial traversal, result order and persistent source identities.
The web path remains serial. Original multi-solid fixtures show 64–81% lower complete
import times; single-solid assembly parts are not scheduled across nodes. See
[measurements and limits](docs/perf.md#parallel-step-body-preparation-2026-10-12).
- Design containers (#303, phase one) separate and deduplicate STEP, raw images and
lossless binary mesh arrays while keeping plain JSON as a supported Save As/export
format. Generated-mesh storage measurements reduce serialization and decoding work;
a seekable reader defers original blobs until after provisional display.
See [container format](docs/design-container.md) and [performance measurements](docs/perf.md).
- Warm saves with explicit `cache: true` can include a versioned native B-rep cache through SolidCraft-owned topology
and geometry records, with a separate truck adapter and bounded binary reader. Exact
face-source certificates and operation history survive codec round trips. A provisional
picture can be generated before original blobs are read; editing and measurement wait
for authoritative reconstruction. Cached metadata binds preview and reconstruction to
the same document despite concurrent file writes. Default saves omit this cache and never force cold
evaluation or meshing; explicit `preview: true` remains a separate warm-mesh option.
Keys, resource budgets and document/revision guards reject incompatible, hostile or
stale results. A second modelling kernel still requires its own tested adapter.
- Warm saves with explicit `cache: true` can also carry a bounded PNG thumbnail from already cached meshes.
Home reads it without rebuilding the design when its local picture is missing;
mismatched or malformed thumbnails fall back to normal generation. The image is
kernel-independent and saving never forces cold meshing to produce it.
- Cold rebuild profiling separates parsing, geometry, placement, display meshing and
thumbnails. Straight-line closest-point projection and exact curved-surface evaluation
reuse reduce repeated work without relaxing geometry checks. Three alternating optimized
benchmark runs reduce median rebuild time by 26% on the public sensor enclosure and 22%
on a local case assembly; shape measurements and topology match the original build.
See [performance measurements](docs/perf.md). Further cold Boolean and import costs remain.
- Prepared assembly geometry survives selection and view changes while real geometry and
placement changes invalidate it. A Pi assembly edge-selection probe drops from 9.24 s to
0.57 s; initial opening is unchanged. Actual Windows desktop profiling measures 15.87 s
median opening, with 82% spent rebuilding geometry; halving full opening remains open.
## Kernel
- Successful Boolean retries report their strategy and numerical adjustments as
feature warnings and structured inspection data. Diagnostics survive cached
evaluation, undo/redo and cold reopening; the robustness runner counts retry
events by strategy and reports any bounded-log truncation. Existing geometry
acceptance checks remain in force.
- Cylinders of one radius whose axes cross (a second bore across a bore of the same size, a pipe
tee of equal pipes) touch at two points, where the mesh intersection cannot trace the curves
and a boolean cannot tell the four arms of the crossing apart. When the ordinary boolean fails
on such a pair, both faces are split along the line of their cylinder through the touching
points (the solids are unchanged), the boolean is taken of those, and its history is composed
back over the operands as given (#788). The result keeps the split lines as edges of the bore
walls. A crossing the ordinary route fails on and the split faces do not help (a radius of 17.5
in a 45 mm block with a tool of 80 mm) is still refused.
- Boolean intersection-curve construction refuses point-only, collapsed and non-finite
polylines without panicking. Direct constructor regressions retain valid open endpoints
and closed spherical intersections; the original interactive trigger remains unidentified.
- Shell of a stepped, joined planar body no longer creates horizontal subdivisions across
continuous walls. Fresh axis-aligned Cut walls are stitched using their exact construction
support and shared topology, preserving real steps and intentional boundaries. The local
reported case returns from 86 to 49 faces with unchanged material and bounds; regressions
cover stepped stock, STEP round trips and saved projections from removed pieces.
truck (Apache-2.0) behind our own `kernel` crate, with our own blend operation and boolean
retry/validation; see `plan/adr/0001-geometry-kernel.md` (local) — summary in README.
+9 -9
View File
@@ -353,7 +353,7 @@ rustls-native-certs 0.8.5 (Apache-2.0 OR ISC OR MIT)
rustls-pki-types 1.15.1 (MIT OR Apache-2.0)
rustls-platform-verifier 0.7.1 (MIT OR Apache-2.0)
rustls-platform-verifier-android 0.2.0 (MIT OR Apache-2.0)
rustls-webpki 0.103.15 (ISC)
rustls-webpki 0.103.16 (ISC)
rustversion 1.0.23 (MIT OR Apache-2.0)
ruzstd 0.9.1 (MIT)
schannel 0.1.29 (MIT)
@@ -435,7 +435,7 @@ truck-topology 0.6.0 (Apache-2.0)
ttf-parser 0.25.1 (MIT OR Apache-2.0)
twox-hash 2.1.5 (MIT)
type-map 0.5.1 (MIT/Apache-2.0)
typed-path 0.12.3 (MIT OR Apache-2.0)
typed-path 0.13.0 (MIT OR Apache-2.0)
typeid 1.0.3 (MIT OR Apache-2.0)
typenum 1.20.1 (MIT OR Apache-2.0)
uds_windows 1.2.1 (MIT)
@@ -474,7 +474,7 @@ wayland-sys 0.31.11 (MIT)
web-sys 0.3.106 (MIT OR Apache-2.0)
web-time 1.1.0 (MIT OR Apache-2.0)
webbrowser 1.2.4 (MIT OR Apache-2.0)
webpki-root-certs 1.0.9 (CDLA-Permissive-2.0)
webpki-root-certs 1.0.10 (CDLA-Permissive-2.0)
weezl 0.1.12 (MIT OR Apache-2.0)
wgpu 30.0.1 (MIT OR Apache-2.0)
wgpu-core 30.0.1 (MIT OR Apache-2.0)
@@ -552,7 +552,7 @@ zeroize_derive 1.5.0 (Apache-2.0 OR MIT)
zerotrie 0.2.5 (Unicode-3.0)
zerovec 0.11.8 (Unicode-3.0)
zerovec-derive 0.11.6 (Unicode-3.0)
zip 9.0.4 (MIT)
zip 9.1.3 (MIT)
zlib-rs 0.6.8 (Zlib)
zmij 1.0.23 (MIT)
zopfli 0.8.3 (Apache-2.0)
@@ -596,7 +596,7 @@ pin-project 1.1.13, pin-project-internal 1.1.13, pin-project-lite 0.2.17, piper
rustix 0.38.44, rustix 1.1.5, rustversion 1.0.23, semver 1.0.28, serde 1.0.229, serde_core 1.0.229,
serde_derive 1.0.229, serde_derive_internals 0.30.0, serde_json 1.0.151, serde_path_to_error 0.1.20,
serde_repr 0.1.21, simd_cesu8 1.2.0, smol_str 0.2.2, syn 1.0.109, syn 2.0.119, syn 3.0.6, thiserror
1.0.69, thiserror 2.0.21, thiserror-impl 1.0.69, thiserror-impl 2.0.21, typed-path 0.12.3, typeid
1.0.69, thiserror 2.0.21, thiserror-impl 1.0.69, thiserror-impl 2.0.21, typed-path 0.13.0, typeid
1.0.3, unicode-ident 1.0.26, utf8-zero 0.8.1, wasi 0.11.1+wasi-snapshot-preview1, wasip2
1.0.4+wasi-0.2.12, wit-bindgen 0.57.1, x11-dl 2.21.0, xdg-home 1.3.0, zbus-lockstep 0.5.2,
zbus-lockstep-macros 0.5.2, zbus_names 3.0.0, zmij 1.0.23, zvariant_utils 2.1.0, zvariant_utils
@@ -1339,7 +1339,7 @@ libc 0.2.190, litrs 1.0.0, num_enum 0.7.6, num_enum_derive 0.7.6, proc-macro2 1.
ref-cast 1.0.27, ref-cast-impl 1.0.27, rustc-hash 2.1.3, rustversion 1.0.23, semver 1.0.28, serde
1.0.229, serde_core 1.0.229, serde_derive 1.0.229, serde_derive_internals 0.30.0, serde_json
1.0.151, serde_path_to_error 0.1.20, serde_repr 0.1.21, syn 2.0.119, syn 3.0.6, thiserror 1.0.69,
thiserror 2.0.21, thiserror-impl 1.0.69, thiserror-impl 2.0.21, typed-path 0.12.3, typeid 1.0.3,
thiserror 2.0.21, thiserror-impl 1.0.69, thiserror-impl 2.0.21, typed-path 0.13.0, typeid 1.0.3,
unicode-ident 1.0.26, utf8-zero 0.8.1
================================================================================
@@ -12431,7 +12431,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================================================
rustls-webpki 0.103.15
rustls-webpki 0.103.16
================================================================================
Except as otherwise noted, this project is licensed under the following
@@ -15274,7 +15274,7 @@ IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
================================================================================
webpki-root-certs 1.0.9
webpki-root-certs 1.0.10
================================================================================
# Community Data License Agreement - Permissive - Version 2.0
@@ -16401,7 +16401,7 @@ IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
================================================================================
zip 9.0.4
zip 9.1.3
================================================================================
The MIT License (MIT)
+35 -7
View File
@@ -23,6 +23,7 @@
//! solidcraft-cli icon --out F.png|F.ico [--size N] the app icon (packaging; drawn, not a file)
//!
//! --debug (with any command) SolidCraft's debug log on stderr (or RUST_LOG=LEVEL)
//! --max-file-size SIZE (with any command) read STEP and design files up to SIZE (2GB, 1500MB; at most 16GB)
//! ```
#![deny(clippy::unwrap_used, clippy::expect_used, clippy::panic, clippy::unimplemented, clippy::todo, clippy::unreachable)]
#![forbid(unsafe_code)]
@@ -99,7 +100,7 @@ const USAGE_BENCH_EDIT: &str = " solidcraft-cli bench-edit <script.json|recipe.
/// `save-stress`'s lines in the usage: the file saved over and over.
const USAGE_SAVE_STRESS: &str = " solidcraft-cli save-stress <path> <rounds>\n";
/// The flags every command takes, at the end of the top-level usage.
const USAGE_DEBUG: &str = " --debug, with any command: what SolidCraft logs (why a body has no display plan, why a save left its\n model cache out), on stderr; RUST_LOG=error|warn|info|debug|trace sets one level for every crate\n";
const USAGE_DEBUG: &str = " --debug, with any command: what SolidCraft logs (why a body has no display plan, why a save left its\n model cache out), on stderr; RUST_LOG=error|warn|info|debug|trace sets one level for every crate\n --max-file-size SIZE, with any command: read STEP and import files and design files up to SIZE for this run\n (for example 2GB or 1500MB; at most 16GB; the defaults are 512 MB and 256 MB, and a smaller SIZE keeps them)\n";
/// The commands the CLI takes, in the order the top-level usage lists them.
const COMMANDS: &[Command] = &[
@@ -131,6 +132,10 @@ const COMMANDS: &[Command] = &[
fn main() -> ExitCode {
let mut args: Vec<String> = std::env::args().skip(1).collect();
logger::init(&mut args);
if let Err(e) = max_file_size(&mut args) {
eprintln!("error: {e}");
return ExitCode::FAILURE;
}
let r = match args.first().map(String::as_str) {
// Asked-for help is not an error: the command's usage on stdout, exit 0. It is read
// before the command runs, so `--help` never starts a run (a fuzz run, a server).
@@ -205,6 +210,28 @@ fn main() -> ExitCode {
}
}
/// Take `--max-file-size SIZE` (or `--max-file-size=SIZE`), which any command takes, out of the
/// arguments and raise the file size limits for this run (#4086). A bad size is an error.
fn max_file_size(args: &mut Vec<String>) -> Result<(), String> {
let mut size = None;
let mut i = 0;
while let Some(arg) = args.get(i) {
if arg == "--max-file-size" {
let value = args.get(i + 1).cloned().ok_or("--max-file-size needs a size, for example --max-file-size 2GB")?;
args.drain(i..i + 2);
size = Some(value);
} else if let Some(value) = arg.strip_prefix("--max-file-size=") {
size = Some(value.to_string());
args.remove(i);
} else {
i += 1;
}
}
let Some(size) = size else { return Ok(()) };
let bytes = solidcraft_engine::io::limits::parse_flag(&size).map_err(|e| format!("--max-file-size: {e}"))?;
solidcraft_engine::io::limits::set_override(Some(bytes))
}
fn pretty(v: &Value) -> String {
serde_json::to_string_pretty(v).unwrap_or_default()
}
@@ -241,11 +268,12 @@ fn wants_help(args: &[String]) -> bool {
pub fn read_json(path: &str) -> Result<Value, String> {
// Through the engine's file access, which refuses anything that is not a regular file and
// reads no more than the cap: a character device or a FIFO would otherwise never end.
let s = solidcraft_engine::io::vfs::read_to_string(path, solidcraft_engine::io::MAX_DESIGN_BYTES).map_err(|e| format!("{path}: {e}"))?;
let s = solidcraft_engine::io::vfs::read_to_string(path, solidcraft_engine::io::limits::max_design_bytes())
.map_err(|e| format!("{path}: {}", solidcraft_engine::io::limits::explain(solidcraft_engine::io::limits::Kind::Design, e)))?;
serde_json::from_str(&s).map_err(|e| format!("{path}: {e}"))
}
/// A session from a design file, a STEP/3MF/STL file, a command script, or an oracle recipe.
/// A session from a design file, a STEP/3MF/STL file, a point cloud, a command script, or an oracle recipe.
pub fn load(path: &str) -> Result<Session, String> {
load_checked(path, solidcraft_engine::schema::ParamCheck::Off)
}
@@ -255,11 +283,11 @@ pub fn load(path: &str) -> Result<Session, String> {
fn load_checked(path: &str, check: solidcraft_engine::schema::ParamCheck) -> Result<Session, String> {
let mut s = Session::default();
s.param_check = check;
if solidcraft_engine::io::is_step_path(path) || solidcraft_engine::io::is_mesh_path(path) {
if solidcraft_engine::io::is_step_path(path) || solidcraft_engine::io::is_mesh_path(path) || solidcraft_engine::io::is_point_cloud_path(path) {
s.execute("doc.open", &json!({"path": path})).map_err(|e| e.to_string())?;
return Ok(s);
}
let bytes = solidcraft_engine::io::vfs::read(path, solidcraft_engine::io::MAX_DESIGN_BYTES).map_err(|e| format!("{path}: {e}"))?;
let bytes = solidcraft_engine::io::limits::read(path, solidcraft_engine::io::limits::Kind::Design).map_err(|e| format!("{path}: {e}"))?;
if solidcraft_engine::io::is_design_container(&bytes) {
let doc = solidcraft_engine::io::read_design(&bytes).map_err(|e| format!("{path}: {e}"))?;
let mut session = Session::opened_at(doc, None, Some(path));
@@ -820,8 +848,8 @@ pub(crate) fn cmd_bench_open(args: &[String]) -> Result<(), String> {
let path = args.first().ok_or("usage: solidcraft-cli bench-open <design.sc | part.step> [--parse-only]")?;
let t = std::time::Instant::now();
let step = solidcraft_engine::io::is_step_path(path);
let limit = if step { solidcraft_engine::io::MAX_STEP_BYTES } else { solidcraft_engine::io::MAX_DESIGN_BYTES };
let bytes = solidcraft_engine::io::vfs::read(path, limit).map_err(|e| format!("{path}: {e}"))?;
let kind = if step { solidcraft_engine::io::limits::Kind::Step } else { solidcraft_engine::io::limits::Kind::Design };
let bytes = solidcraft_engine::io::limits::read(path, kind).map_err(|e| format!("{path}: {e}"))?;
let read_ms = t.elapsed().as_secs_f64() * 1000.0;
println!("{}", json!({"step": "read", "ms": read_ms, "bytes": bytes.len()}));
let t = std::time::Instant::now();
+31
View File
@@ -157,3 +157,34 @@ fn render_help_keeps_the_registered_gpu_request_controls() {
}
}
}
/// `--max-file-size` (#4086), with any command: the usage names it, a bad size stops the run
/// with the reason, and a design over the default limit opens once the flag raises it.
#[test]
fn max_file_size_raises_the_limit_and_refuses_bad_sizes() {
let output = Command::new(env!("CARGO_BIN_EXE_solidcraft-cli")).arg("--help").output().unwrap();
assert!(String::from_utf8_lossy(&output.stdout).contains("--max-file-size"));
for size in ["17GB", "2", "lots"] {
let output = Command::new(env!("CARGO_BIN_EXE_solidcraft-cli")).args(["--max-file-size", size, "exec", "file.new"]).output().unwrap();
assert!(!output.status.success(), "{size} was accepted");
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(stderr.starts_with("error: --max-file-size"), "{size}: {stderr}");
}
let output = Command::new(env!("CARGO_BIN_EXE_solidcraft-cli")).args(["exec", "file.new", "--max-file-size=2GB"]).output().unwrap();
assert!(output.status.success(), "{}", String::from_utf8_lossy(&output.stderr));
// A sparse design file just over the default 256 MB: refused unread, then read with the flag
// (and refused for what it holds, which is no design).
let dir = std::env::temp_dir().join(format!("solidcraft-cli-4086-{}", std::process::id()));
std::fs::create_dir_all(&dir).unwrap();
let path = dir.join("big.solidcraft");
std::fs::File::create(&path).unwrap().set_len((256 << 20) + 1).unwrap();
let path = path.to_string_lossy().to_string();
let output = Command::new(env!("CARGO_BIN_EXE_solidcraft-cli")).args(["eval", &path]).output().unwrap();
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(!output.status.success() && stderr.contains("too large") && stderr.contains("--max-file-size"), "{stderr}");
let output = Command::new(env!("CARGO_BIN_EXE_solidcraft-cli")).args(["--max-file-size", "1GB", "eval", &path]).output().unwrap();
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(!output.status.success() && !stderr.contains("too large"), "{stderr}");
let _ = std::fs::remove_dir_all(&dir);
}
+6 -2
View File
@@ -40,6 +40,8 @@ pub enum Intent {
Open,
/// Add its bodies to the open design (STEP, 3MF, STL).
Insert,
/// Import it as a theme: it was dropped on Preferences' Import tile (#8226).
Theme,
}
/// A stored design, as the file panel lists it.
@@ -615,13 +617,15 @@ fn choose_file(accept: &str) -> Result<js_sys::Promise, String> {
}
/// Read files dropped on the page.
pub fn take_drops(files: &Rc<Files>, raw: &mut egui::RawInput) {
/// `theme`: the pointer is over Preferences' Import tile, so the files are themes.
pub fn take_drops(files: &Rc<Files>, raw: &mut egui::RawInput, theme: bool) {
let intent = if theme { Intent::Theme } else { Intent::Insert };
for f in std::mem::take(&mut raw.dropped_files) {
let files = files.clone();
spawn_local(async move {
let name = f.path().file_name().map(|n| n.to_string_lossy().to_string()).unwrap_or_else(|| "dropped".into());
match f.bytes_async().await {
Ok(b) => files.arrive(name, b, Intent::Insert),
Ok(b) => files.arrive(name, b, intent),
Err(e) => files.say(format!("{name}: {e}"), true),
}
});
+47 -2
View File
@@ -112,6 +112,13 @@ fn check_download_size(current: usize, incoming: u64) -> Result<(), String> {
Ok(())
}
/// Ctrl+W (⌘W, without Shift or Alt) while a design is shown closes it in the app, so the
/// browser must not close the tab (#5366). On the start page the browser closes the tab.
#[cfg(any(target_arch = "wasm32", test))]
fn closes_design(key: &str, command: bool, shift: bool, alt: bool, design_shown: bool) -> bool {
design_shown && command && !shift && !alt && key.eq_ignore_ascii_case("w")
}
#[cfg(target_arch = "wasm32")]
mod web {
use std::rc::Rc;
@@ -163,6 +170,23 @@ mod web {
thread_local! {
/// An open design has unsaved changes: leaving the page asks first.
static UNSAVED: std::cell::Cell<bool> = const { std::cell::Cell::new(false) };
/// A design is shown (not the start page): Ctrl+W closes it, not the browser tab.
static DESIGN_SHOWN: std::cell::Cell<bool> = const { std::cell::Cell::new(false) };
}
/// Ctrl+W (⌘W) closes the design shown, as on the desktop; on the start page it is left to
/// the browser, which closes the tab (#5366). Browsers that keep Ctrl+W to themselves still
/// close the tab, after asking when a design is unsaved ([`ask_before_unload`]).
fn keep_ctrl_w_for_the_design(window: &web_sys::Window) {
let on_key = wasm_bindgen::closure::Closure::<dyn FnMut(web_sys::KeyboardEvent)>::new(|e: web_sys::KeyboardEvent| {
let command = e.ctrl_key() || e.meta_key();
if crate::closes_design(&e.key(), command, e.shift_key(), e.alt_key(), DESIGN_SHOWN.with(std::cell::Cell::get)) {
e.prevent_default();
}
});
let _ = window.add_event_listener_with_callback_and_bool("keydown", on_key.as_ref().unchecked_ref(), true);
// The listener lives as long as the page.
on_key.forget();
}
/// The browser's "leave site? changes you made may not be saved" prompt while a design has
@@ -271,6 +295,10 @@ mod web {
!companion
});
for (name, bytes, intent) in incoming {
if intent == Intent::Theme {
solidcraft_ui_egui::prefs::import_theme_bytes(&mut self.app, bytes);
continue;
}
let design = solidcraft_engine::io::is_design_path(&name);
let path = if design && intent == Intent::Open {
// A design from the computer is kept in the browser (a copy), so Save works.
@@ -287,7 +315,7 @@ mod web {
};
match intent {
Intent::Open => self.app.open_path(&path),
Intent::Insert => self.app.drop_path(&path),
Intent::Insert | Intent::Theme => self.app.drop_path(&path),
}
self.files.panel.set(false);
}
@@ -625,6 +653,7 @@ mod web {
self.space_mouse.logic(&mut self.app, ctx);
self.files_tick(ctx);
UNSAVED.with(|u| u.set(solidcraft_ui_egui::documents::any_dirty(&self.app)));
DESIGN_SHOWN.with(|d| d.set(solidcraft_ui_egui::toolbar::design_shown(&self.app)));
}
fn raw_input_hook(&mut self, ctx: &egui::Context, raw: &mut egui::RawInput) {
let now = raw.time.unwrap_or_else(|| ctx.input(|i| i.time));
@@ -632,7 +661,8 @@ mod web {
ctx.request_repaint_after(delay);
}
if self.launch.persists() {
files::take_drops(&self.files, raw);
let theme = solidcraft_ui_egui::prefs::theme_drop_target(&self.app, ctx);
files::take_drops(&self.files, raw, theme);
} else {
raw.dropped_files.clear();
}
@@ -724,6 +754,7 @@ mod web {
ask_before_unload(&window);
}
leave_tab_switching_to_browser(&window);
keep_ctrl_w_for_the_design(&window);
let Some(document) = window.document() else { return };
let Some(canvas) = document.get_element_by_id(CANVAS_ID).and_then(|e| e.dyn_into::<web_sys::HtmlCanvasElement>().ok()) else {
log::error!("missing <canvas id=\"{CANVAS_ID}\">");
@@ -956,4 +987,18 @@ mod tests {
assert!(!browser_switches_tabs("Tab", false));
assert!(!browser_switches_tabs("s", true));
}
#[test]
fn ctrl_w_closes_the_design_not_the_tab() {
// Ctrl+W and ⌘W (either case of the key) close the design shown.
assert!(closes_design("w", true, false, false, true));
assert!(closes_design("W", true, false, false, true));
// On the start page the browser closes the tab.
assert!(!closes_design("w", true, false, false, false));
// Ctrl+Shift+W (close the window), plain W and other keys stay the browser's or the app's.
assert!(!closes_design("W", true, true, false, true));
assert!(!closes_design("w", true, false, true, true));
assert!(!closes_design("w", false, false, false, true));
assert!(!closes_design("s", true, false, false, true));
}
}
+2
View File
@@ -28,6 +28,8 @@ neg_cmp_op_on_partial_ord = "allow"
[dependencies]
solidcraft-engine = { workspace = true }
# The D3D12 shader compiler the window starts with (#6756).
solidcraft-gpu = { workspace = true }
solidcraft-ui-egui = { workspace = true }
solidcraft-space-mouse = { workspace = true }
eframe = { workspace = true, features = ["default_fonts", "wgpu", "accesskit", "wayland", "x11", "links"] }
+16 -1
View File
@@ -4,6 +4,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let icon = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("../../assets/icons/app/windows/exports/solidcraft-executable.ico");
println!("cargo:rerun-if-changed={}", icon.display());
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-env-changed=CARGO_PKG_VERSION");
if std::env::var("CARGO_CFG_TARGET_OS")? != "windows" {
return Ok(());
}
@@ -11,7 +12,21 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let copy = out.join("solidcraft.ico");
std::fs::copy(icon, &copy)?;
let rc = out.join("solidcraft.rc");
std::fs::write(&rc, format!("1 ICON \"{}\"\n", copy.display().to_string().replace('\\', "/")))?;
let icon_line = format!("1 ICON \"{}\"\n", copy.display().to_string().replace('\\', "/"));
std::fs::write(&rc, format!("{icon_line}{}", version_resource(&std::env::var("CARGO_PKG_VERSION")?)))?;
embed_resource::compile_for(&rc, ["solidcraft"], embed_resource::NONE).manifest_required()?;
Ok(())
}
/// The Windows version resource (what Explorer's Details tab shows and what a launcher reads).
/// `FileVersion` and `ProductVersion` are the package version verbatim (`0.25.1`, `0.26.0-rc.1`):
/// ArtCraft's launcher parses the `ProductVersion` string as semver, so a fourth `.0` would not
/// read. The binary `FILEVERSION` fields need four numbers and take the leading `major.minor.patch`.
fn version_resource(version: &str) -> String {
let mut numbers = version.split(['-', '+']).next().unwrap_or("").split('.').map(|p| p.parse::<u16>().unwrap_or(0));
let mut next = || numbers.next().unwrap_or(0);
let (major, minor, patch) = (next(), next(), next());
format!(
"1 VERSIONINFO\nFILEVERSION {major},{minor},{patch},0\nPRODUCTVERSION {major},{minor},{patch},0\nFILEOS 0x40004\nFILETYPE 0x1\n{{\nBLOCK \"StringFileInfo\"\n{{\nBLOCK \"040904B0\"\n{{\nVALUE \"CompanyName\", \"SolidCraft contributors\"\nVALUE \"FileDescription\", \"SolidCraft, parametric 3D CAD\"\nVALUE \"FileVersion\", \"{version}\"\nVALUE \"InternalName\", \"solidcraft\"\nVALUE \"OriginalFilename\", \"solidcraft.exe\"\nVALUE \"ProductName\", \"SolidCraft\"\nVALUE \"ProductVersion\", \"{version}\"\n}}\n}}\nBLOCK \"VarFileInfo\"\n{{\nVALUE \"Translation\", 0x0409, 1200\n}}\n}}\n"
)
}
+14 -1
View File
@@ -761,12 +761,15 @@ fn main() -> eframe::Result {
let mut sample = false;
// `--theme-file PATH`: follow that theme file for this run without saving it (#7573).
let mut theme_file: Option<String> = None;
let mut max_file_size = None;
let mut args = std::env::args().skip(1);
while let Some(a) = args.next() {
match a.as_str() {
"--control" => control_port = args.next().and_then(|p| p.parse().ok()),
"--sample" => sample = true,
"--theme-file" => theme_file = args.next(),
"--max-file-size" => max_file_size = Some(args.next()),
s if s.starts_with("--max-file-size=") => max_file_size = Some(s.strip_prefix("--max-file-size=").map(str::to_string)),
"--safe-mode" => safe_mode = true,
"--version" | "-V" => {
println!("solidcraft {}", env!("CARGO_PKG_VERSION"));
@@ -787,13 +790,21 @@ fn main() -> eframe::Result {
}
"--help" | "-h" => {
println!(
"usage: solidcraft [--control PORT] [--sample] [--theme-file THEME.json] [--crash-log] [--safe-mode] [design.sc | part.step]"
"usage: solidcraft [--control PORT] [--sample] [--theme-file THEME.json] [--crash-log] [--safe-mode] [--max-file-size SIZE] [design.sc | part.step]"
);
return Ok(());
}
_ => files.push(a),
}
}
// `--max-file-size 2GB`: the largest files this run reads, over Preferences, never saved (#4086).
if let Some(value) = max_file_size {
let applied = startup::max_file_size(value.as_deref()).and_then(|bytes| solidcraft_engine::io::limits::set_override(Some(bytes)));
if let Err(error) = applied {
eprintln!("SolidCraft: {error}");
return Err(eframe::Error::AppCreation(std::io::Error::other(error).into()));
}
}
// Settings that don't read are moved aside; launches that never got a window are counted,
// and after a few in a row this one starts in safe mode (docs/book/src/guide/troubleshooting.md).
let mut notes: Vec<String> = Vec::new();
@@ -1113,6 +1124,8 @@ fn wgpu_options(cpu: bool, preference: Option<&str>) -> eframe::egui_wgpu::WgpuC
let intel_mac = cfg!(all(target_os = "macos", target_arch = "x86_64"));
let indirect = std::env::var(startup::INDIRECT_VALIDATION_ENV).ok();
setup.instance_descriptor.flags = startup::window_instance_flags(setup.instance_descriptor.flags, intel_mac, indirect.as_deref());
// Never a `dxcompiler.dll` another program put on PATH (#6756).
setup.instance_descriptor.backend_options.dx12.shader_compiler = solidcraft_gpu::dx12_compiler();
let environment = std::env::var("WGPU_ADAPTER_NAME").ok();
let adapter = graphics().and_then(|v| v.get("adapter").and_then(serde_json::Value::as_str).map(str::to_string));
startup::configure_adapter(setup, cpu, environment, adapter);
+21 -2
View File
@@ -255,7 +255,7 @@ pub const FLOAT_DEPTH_STENCIL: eframe::wgpu::Features = eframe::wgpu::Features::
/// asks for a float one only when whichever it picks has it.
pub fn float_depth_everywhere(options: &eframe::egui_wgpu::WgpuConfiguration) -> bool {
let eframe::egui_wgpu::WgpuSetup::CreateNew(setup) = &options.wgpu_setup else { return false };
let mut desc = eframe::wgpu::InstanceDescriptor::new_without_display_handle_from_env();
let mut desc = solidcraft_gpu::instance_descriptor_from_env();
desc.backends = setup.instance_descriptor.backends;
let instance = eframe::wgpu::Instance::new(desc);
let adapters = pollster::block_on(instance.enumerate_adapters(setup.instance_descriptor.backends));
@@ -272,6 +272,7 @@ pub fn has_hardware_adapter(backends: eframe::wgpu::Backends) -> bool {
let mut desc = eframe::wgpu::InstanceDescriptor::new_without_display_handle();
desc.backends = backends;
desc.flags = eframe::wgpu::InstanceFlags::from_build_config().with_env();
desc.backend_options.dx12.shader_compiler = solidcraft_gpu::dx12_compiler();
let instance = eframe::wgpu::Instance::new(desc);
let adapters = pollster::block_on(instance.enumerate_adapters(backends));
let found: Vec<String> = adapters.iter().map(|a| format!("{} ({:?})", a.get_info().name, a.get_info().device_type)).collect();
@@ -302,6 +303,14 @@ pub fn system_title_bar(windows: bool, backends: eframe::wgpu::Backends) -> bool
windows && backends.contains(Backends::GL) && !backends.intersects(Backends::DX12 | Backends::VULKAN)
}
/// The `--max-file-size` value (#4086): a size such as `2GB` or `1500MB`, at most 16 GB. It raises
/// the largest STEP/import and design file this run reads, over the saved preference, without
/// saving anything. A missing or bad value stops the start with this error.
pub fn max_file_size(value: Option<&str>) -> Result<u64, String> {
let value = value.ok_or("--max-file-size needs a size, for example --max-file-size 2GB")?;
solidcraft_engine::io::limits::parse_flag(value).map_err(|e| format!("--max-file-size: {e}"))
}
/// The message shown when no window could be opened at all.
pub fn no_window_message(error: &str, settings: Option<&Path>) -> String {
let folder = settings.map(|d| d.display().to_string()).unwrap_or_else(|| "the SolidCraft settings folder".into());
@@ -324,6 +333,16 @@ mod tests {
["Integrated", "Discrete small", "Discrete large"].into_iter().map(|name| AdapterChoice { name: name.into(), compatible: true }).collect()
}
#[test]
fn max_file_size_parses_sizes_and_refuses_bad_ones() {
assert_eq!(max_file_size(Some("2GB")), Ok(2 << 30));
assert_eq!(max_file_size(Some("1500MB")), Ok(1500 << 20));
for bad in [None, Some(""), Some("2"), Some("17GB"), Some("lots"), Some("-1GB")] {
let error = max_file_size(bad).unwrap_err();
assert!(error.contains("--max-file-size"), "{bad:?}: {error}");
}
}
#[test]
fn adapter_names_environment_override_and_missing_card_fallback() {
let cards = cards();
@@ -573,7 +592,7 @@ mod tests {
if cfg!(target_os = "windows") && std::env::var_os(WGPU_BACKEND_ENV).is_none() {
assert_eq!(backends, eframe::wgpu::Backends::DX12);
}
let mut desc = eframe::wgpu::InstanceDescriptor::new_without_display_handle_from_env();
let mut desc = solidcraft_gpu::instance_descriptor_from_env();
desc.backends = backends;
let instance = eframe::wgpu::Instance::new(desc);
let adapters = pollster::block_on(instance.enumerate_adapters(backends));
+1 -1
View File
@@ -1,5 +1,5 @@
//! Built-in model appearances: names, sRGB colours and metalness.
pub const LIBRARY: [(&str, [u8; 3], f64); 20] = [
pub const LIBRARY: &[(&str, [u8; 3], f64)] = &[
("Aluminum - Satin", [204, 208, 214], 1.0),
("Aluminum - Anodized Black", [44, 46, 50], 1.0),
("Aluminum - Anodized Blue", [52, 92, 160], 1.0),
+1 -1
View File
@@ -1,7 +1,7 @@
//! Original illustrative opaque finishes; not measured optical or engineering data.
//! (name, sRGB color, metal fraction, perceptual roughness). IOR is an illustrative 1.5.
//! Separate names preserve the scalar library's appearance and saved assignments.
pub const OPAQUE_FINISHES: [(&str, [u8; 3], f64, f64); 6] = [
pub const OPAQUE_FINISHES: &[(&str, [u8; 3], f64, f64)] = &[
("Steel - Satin PBR", [158, 164, 172], 1.0, 0.4),
("Aluminum - Satin PBR", [204, 208, 214], 1.0, 0.3),
("Copper - Clean PBR", [204, 122, 80], 1.0, 0.25),
+1 -1
View File
@@ -16,7 +16,7 @@ const fn glass(transmission_linear_rgb: [f64; 3], ior: f64, reference_path_mm: f
GlassRecipe { transmission_linear_rgb, dielectric_ior: ior, reference_path_mm, boundary }
}
pub const STARTER_PACK: [VisualPreset; 40] = [
pub const STARTER_PACK: &[VisualPreset] = &[
VisualPreset::opaque(
"starter.wood.oak-honey",
"Wood - Honey Oak Uniform Preview",
+3
View File
@@ -206,3 +206,6 @@ constraint = [
construction = [
"centerline", "construction", "infinite",
]
mesh = [
"mesh_body",
]
@@ -103,6 +103,7 @@ extend false
extrude false
eye false
fastener false
feature_group false
fillet false
finish false
finish_edit false
@@ -143,6 +144,7 @@ loft false
lookat false
material false
measure false
mesh_body false
mesh_export false
min_radius false
mirror false
@@ -257,6 +259,7 @@ split_face false
spun false
star false
status_error false
status_pin false
status_recovery false
style false
style_hidden_edges false
@@ -288,6 +291,8 @@ svg false
sweep false
text false
thread false
timeline_play false
timeline_stop false
torus false
trace false
trim false
@@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
<title>Pinned result</title>
<path d="M32 57C25 48 14 35 14 24A18 18 0 0 1 50 24C50 35 39 48 32 57Z" fill="none" stroke="currentColor" stroke-width="5.6" stroke-linejoin="round" stroke-linecap="round"/>
<path d="M25 24A7 7 0 1 0 39 24A7 7 0 1 0 25 24Z" fill="none" stroke="currentColor" stroke-width="5.6" stroke-linejoin="round" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 429 B

@@ -0,0 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
<title>Feature group</title>
<path d="M28.5 11L50.5 11A4.5 4.5 0 0 1 55 15.5L55 28.5A4.5 4.5 0 0 1 50.5 33L28.5 33A4.5 4.5 0 0 1 24 28.5L24 15.5A4.5 4.5 0 0 1 28.5 11Z" fill="#8e9faf" stroke="#34465b" stroke-width="2.55" stroke-linejoin="round" stroke-linecap="round"/>
<path d="M21 20L43 20A4.5 4.5 0 0 1 47.5 24.5L47.5 37.5A4.5 4.5 0 0 1 43 42L21 42A4.5 4.5 0 0 1 16.5 37.5L16.5 24.5A4.5 4.5 0 0 1 21 20Z" fill="#b8c3cf" stroke="#34465b" stroke-width="2.55" stroke-linejoin="round" stroke-linecap="round"/>
<path d="M13.5 29L35.5 29A4.5 4.5 0 0 1 40 33.5L40 46.5A4.5 4.5 0 0 1 35.5 51L13.5 51A4.5 4.5 0 0 1 9 46.5L9 33.5A4.5 4.5 0 0 1 13.5 29Z" fill="#b9ddf8" stroke="#34465b" stroke-width="2.55" stroke-linejoin="round" stroke-linecap="round"/>
<path d="M16 40L33 40" fill="none" stroke="#236ead" stroke-width="4.25" stroke-linejoin="round" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 947 B

@@ -0,0 +1,12 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
<title>Mesh body</title>
<path d="M8.62 18.5L32 32L32 59L8.62 45.5Z" fill="#328bd3"/>
<path d="M55.38 18.5L32 32L32 59L55.38 45.5Z" fill="#236ead"/>
<path d="M32 5L55.38 18.5L32 32L8.62 18.5Z" fill="#b9ddf8"/>
<path d="M8.62 18.5L55.38 18.5" fill="none" stroke="#34465b" stroke-width="2.55" stroke-linejoin="round" stroke-linecap="round"/>
<path d="M8.62 18.5L32 59" fill="none" stroke="#34465b" stroke-width="2.55" stroke-linejoin="round" stroke-linecap="round"/>
<path d="M55.38 18.5L32 59" fill="none" stroke="#34465b" stroke-width="2.55" stroke-linejoin="round" stroke-linecap="round"/>
<path d="M32 5L55.38 18.5L55.38 45.5L32 59L8.62 45.5L8.62 18.5Z" fill="none" stroke="#34465b" stroke-width="2.55" stroke-linejoin="round" stroke-linecap="round"/>
<path d="M8.62 18.5L32 32L55.38 18.5" fill="none" stroke="#34465b" stroke-width="2.55" stroke-linejoin="round" stroke-linecap="round"/>
<path d="M32 32L32 59" fill="none" stroke="#34465b" stroke-width="2.55" stroke-linejoin="round" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><title>Play History</title><path d="M11.22 20L32 32L32 56L11.22 44Z" fill="#b8c3cf"/><path d="M52.78 20L32 32L32 56L52.78 44Z" fill="#8e9faf"/><path d="M32 8L52.78 20L32 32L11.22 20Z" fill="#e2e8ef"/><path d="M32 8L52.78 20L52.78 44L32 56L11.22 44L11.22 20Z" fill="none" stroke="#34465b" stroke-width="2.55" stroke-linejoin="round" stroke-linecap="round"/><path d="M11.22 20L32 32L52.78 20" fill="none" stroke="#34465b" stroke-width="2.55" stroke-linejoin="round" stroke-linecap="round"/><path d="M32 32L32 56" fill="none" stroke="#34465b" stroke-width="2.55" stroke-linejoin="round" stroke-linecap="round"/><path d="M35 34L56 46L35 58Z" fill="#ffffff" stroke="#ffffff" stroke-width="4.55" stroke-linejoin="round" stroke-linecap="round"/><path d="M35 34L56 46L35 58Z" fill="#236ead" stroke="#236ead" stroke-width="2.55" stroke-linejoin="round" stroke-linecap="round"/></svg>

After

Width:  |  Height:  |  Size: 935 B

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><title>Stop History</title><path d="M11.22 20L32 32L32 56L11.22 44Z" fill="#b8c3cf"/><path d="M52.78 20L32 32L32 56L52.78 44Z" fill="#8e9faf"/><path d="M32 8L52.78 20L32 32L11.22 20Z" fill="#e2e8ef"/><path d="M32 8L52.78 20L52.78 44L32 56L11.22 44L11.22 20Z" fill="none" stroke="#34465b" stroke-width="2.55" stroke-linejoin="round" stroke-linecap="round"/><path d="M11.22 20L32 32L52.78 20" fill="none" stroke="#34465b" stroke-width="2.55" stroke-linejoin="round" stroke-linecap="round"/><path d="M32 32L32 56" fill="none" stroke="#34465b" stroke-width="2.55" stroke-linejoin="round" stroke-linecap="round"/><path d="M36 35L53 35A2 2 0 0 1 55 37L55 54A2 2 0 0 1 53 56L36 56A2 2 0 0 1 34 54L34 37A2 2 0 0 1 36 35Z" fill="#ffffff" stroke="#ffffff" stroke-width="4.55" stroke-linejoin="round" stroke-linecap="round"/><path d="M36 35L53 35A2 2 0 0 1 55 37L55 54A2 2 0 0 1 53 56L36 56A2 2 0 0 1 34 54L34 37A2 2 0 0 1 36 35Z" fill="#236ead" stroke="#236ead" stroke-width="2.55" stroke-linejoin="round" stroke-linecap="round"/></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

+11
View File
@@ -15,6 +15,17 @@ pub(crate) fn transport_glyph(p: &egui::Painter, c: egui::Pos2, what: &str, col:
}
"back" => tri(-1.0, 0.0),
"forward" => tri(1.0, 0.0),
// Play History: larger than the step arrows so it doesn't read as Forward, and two bars
// while it plays.
"play" => {
let pts = vec![pos2(c.x - 4.5, c.y - 7.0), pos2(c.x + 6.5, c.y), pos2(c.x - 4.5, c.y + 7.0)];
p.add(egui::Shape::convex_polygon(pts, col, Stroke::NONE));
}
"pause" => {
for dx in [-3.0, 3.0] {
p.rect_filled(Rect::from_center_size(pos2(c.x + dx, c.y), vec2(3.0, 12.0)), 0.5, col);
}
}
_ => {
tri(1.0, -1.0);
bar(5.0);
+641 -18
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+9
View File
@@ -618,6 +618,7 @@
"appearance.pbr_opaque": "Uigennemsigtig PBR",
"appearance.roughness": "Ruhed",
"appearance.surface_response": "Overfladens reaktion på lys",
"at the face": "ved fladen",
"browser.body_name": "Emne{number}",
"browser.calibrate_title": "Kalibrér: {name}",
"browser.capture_many": "{count} komponenter er flyttet, men deres positioner er ikke registreret.",
@@ -923,6 +924,7 @@
"cmd.sketch_spline_control_point": "Spline med kontrolpunkter",
"cmd.sketch_spline_control_point_5": "Spline med kontrolpunkter (grad 5)",
"cmd.sketch_spline_fit_point": "Spline gennem punkter",
"cmd.sketch_spline_reverse": "Vend splinens retning",
"cmd.sketch_spun_profile": "Omdrejningsprofil",
"cmd.sketch_toggle_driven": "Skift mellem styrende og afledt mål",
"cmd.sketch_trim_path": "Trim langs bane",
@@ -1290,6 +1292,13 @@
"prefs.left_click": "Venstreklik",
"prefs.live_input": "Løbende input",
"prefs.live_preview": "Løbende forhåndsvisning",
"prefs.max_file_size": "Største fil, der kan åbnes",
"prefs.max_file_size_design": "Designfiler",
"prefs.max_file_size_flag": "Denne kørsel blev startet med --max-file-size {size}, som gælder, indtil SolidCraft lukkes. Disse indstillinger gælder ved start uden denne valgmulighed.",
"prefs.max_file_size_note": "Standard: 512 MB og 256 MB; højst 16 GB. Åbning af en fil kræver flere gange dens størrelse i hukommelse. Et design med en stor import kan kræve en højere grænse for designfiler for at kunne gemmes og åbnes igen.",
"prefs.max_file_size_step": "STEP- og importfiler",
"prefs.max_file_size_web": "Webappen åbner STEP- og importfiler op til 512 MB og design op til 256 MB: en browserfane kan ikke rumme større filer. Grænserne kan hæves i skrivebordsappen.",
"prefs.megabytes": "MB",
"prefs.minutes": "minutter",
"prefs.minutes_suffix": " min",
"prefs.mouse": "Mus og pegefelt",
+610
View File
@@ -180,6 +180,8 @@
"Designs you open or save appear here.": "Designs, die Sie öffnen oder speichern, erscheinen hier.",
"Determined by To Object. Choose Angle to edit the angular extent.": "Bestimmt durch Bis Objekt. Wählen Sie Winkel, um den Winkelbereich zu bearbeiten.",
"Diameter": "Durchmesser",
"Did this assembly open the wrong way up?": "Wurde diese Baugruppe falsch herum geöffnet?",
"Did this part open the wrong way up?": "Wurde dieses Teil falsch herum geöffnet?",
"Dimension new shapes": "Neue Formen bemaßen",
"Direction": "Richtung",
"Discard": "Verwerfen",
@@ -590,6 +592,7 @@
"Square": "Quadrat",
"Stand it up": "Aufrichten",
"Stand it up: a quarter turn about X, as one Move feature you can undo.": "Aufrichten: eine Vierteldrehung um X, als ein Verschieben-Merkmal, das sich rückgängig machen lässt.",
"Stand this assembly up?": "Diese Baugruppe aufrichten?",
"Stand this part up?": "Dieses Teil aufrichten?",
"Start angle": "Startwinkel",
"Start bulge": "Startausbauchung",
@@ -757,6 +760,7 @@
"appearance.pbr_opaque": "Opakes PBR",
"appearance.roughness": "Rauheit",
"appearance.surface_response": "Oberflächenverhalten",
"at the face": "an der Fläche",
"bom.group_children": "Unterteile in der Zeile ihres Teils",
"browser.body_name": "Körper {number}",
"browser.calibrate_title": "Kalibrieren: {name}",
@@ -765,6 +769,7 @@
"browser.capture_one": "Eine Komponente wurde verschoben, ihre Position ist aber nicht erfasst.",
"browser.component_name": "Komponente {number}",
"browser.edit_canvas_title": "Leinwand bearbeiten: {name}",
"browser.edit_point_cloud_title": "Punktwolke bearbeiten: {name}",
"browser.move_title": "Verschieben: {name}",
"browser.parameters": "Parameter ({count})",
"browser.precision": "Genauigkeit: {precision}",
@@ -779,6 +784,9 @@
"cam.roller": "Rolle",
"cam.roller_pick": "Rolle (optional)",
"cam.tip_pick": "Spitze (optional)",
"camera.shot_pitch": "Nickwinkel",
"camera.shot_roll": "Rollwinkel",
"camera.shot_yaw": "Gierwinkel",
"choose a profile": "ein Profil wählen",
"choose the cam's and the follower's joints": "die Gelenke von Nocken und Stößel wählen",
"choose the joints to couple": "die zu koppelnden Gelenke wählen",
@@ -786,9 +794,12 @@
"click sketch curves": "Skizzenkurven anklicken",
"cmd.appearance_assign": "Erscheinungsbild",
"cmd.appearance_chain": "Aussehen-Herkunft",
"cmd.appearance_copy": "Look kopieren",
"cmd.appearance_favorite": "Look favorisieren",
"cmd.appearance_library": "Erscheinungsbild-Bibliothek",
"cmd.appearance_list": "Erscheinungsbilder auflisten",
"cmd.appearance_paint": "Aussehen aufmalen",
"cmd.appearance_paste": "Look einfügen",
"cmd.appearance_pick_up": "Aussehen aufnehmen",
"cmd.appearance_replace": "Erscheinungsbild ersetzen",
"cmd.assembly_bom": "Stückliste",
@@ -992,6 +1003,10 @@
"cmd.plastic_rest": "Auflage",
"cmd.plastic_rules": "Kunststoffregeln auflisten",
"cmd.plastic_snap_fit": "Rastverbindung",
"cmd.pointcloud_delete": "Punktwolke löschen",
"cmd.pointcloud_edit": "Punktwolke bearbeiten",
"cmd.pointcloud_insert": "Punktwolke einfügen",
"cmd.pointcloud_list": "Punktwolken",
"cmd.render_aging_describe": "Mehrschichtige Oberflächenalterung",
"cmd.render_backends": "Render-Backends",
"cmd.render_batch": "Alle Aufnahmen rendern",
@@ -1014,15 +1029,26 @@
"cmd.render_library_surface_prepare": "Erstellte Oberflächenmaps vorbereiten",
"cmd.render_library_surface_unbind": "Remove Surface Binding",
"cmd.render_library_targets": "Ziele für Render-Ressourcen suchen",
"cmd.render_lights_add": "Licht hinzufügen",
"cmd.render_lights_duplicate": "Render-Licht duplizieren",
"cmd.render_lights_list": "Render-Lichter auflisten",
"cmd.render_lights_mute": "Licht stummschalten",
"cmd.render_lights_remove": "Render-Licht entfernen",
"cmd.render_lights_set": "Render-Licht einstellen",
"cmd.render_lights_solo": "Licht allein anzeigen",
"cmd.render_optics_bind": "Optische Einstellungen zuweisen",
"cmd.render_optics_unbind": "Zuweisung optischer Einstellungen entfernen",
"cmd.render_output_size": "Render-Ausgabegröße festlegen",
"cmd.render_preflight": "Renderanfrage prüfen",
"cmd.render_preflight_copy": "Render-Prüfbericht kopieren",
"cmd.render_preset_apply": "Studio-Voreinstellung anwenden",
"cmd.render_preset_resolve": "Studio-Voreinstellung überprüfen",
"cmd.render_quality_prepare": "Festes Sampling-Budget überprüfen",
"cmd.render_result_close": "Renderbild schließen",
"cmd.render_result_copy": "Renderbild kopieren",
"cmd.render_result_pin": "Angezeigtes Render-Ergebnis behalten",
"cmd.render_result_regrade": "Lineares Master-Rendering erneut farbkorrigieren",
"cmd.render_result_view": "Renderbild anzeigen",
"cmd.render_scene": "Renderszene prüfen",
"cmd.render_settings_apply": "Renderkamera anwenden",
"cmd.render_settings_capture_hdr": "Render-Einstellungen mit HDR speichern",
@@ -1125,6 +1151,7 @@
"cmd.sketch_spline_control_point_5": "Spline mit Kontrollpunkten (Grad 5)",
"cmd.sketch_spline_fit_point": "Spline mit Fitpunkten",
"cmd.sketch_spline_insert_point": "Splinepunkt hinzufügen",
"cmd.sketch_spline_reverse": "Splinerichtung umkehren",
"cmd.sketch_spun_profile": "Gedrehtes Profil",
"cmd.sketch_toggle_diameter": "Radius / Durchmesser umschalten",
"cmd.sketch_toggle_driven": "Abhängiges Maß umschalten",
@@ -1166,11 +1193,13 @@
"cmd.timeline_export_script": "Befehlsskript exportieren",
"cmd.timeline_inspect": "Merkmal prüfen",
"cmd.timeline_paste": "Merkmale einfügen",
"cmd.timeline_play": "Verlauf abspielen",
"cmd.timeline_redefine": "Merkmal bearbeiten",
"cmd.timeline_rename": "Umbenennen",
"cmd.timeline_reorder": "Merkmal neu ordnen",
"cmd.timeline_roll_to": "Verlaufsmarkierung verschieben",
"cmd.timeline_rollback": "Zeitleistenmarkierung verschieben",
"cmd.timeline_stop": "Verlauf anhalten",
"cmd.timeline_suppress": "Merkmal unterdrücken",
"cmd.view.render_browser": "Render-Browser",
"cmd.view.render_dock": "Render-Panel verschieben",
@@ -1192,8 +1221,11 @@
"cmd.view_list": "Benannte Ansichten auflisten",
"cmd.view_navigate": "Ansicht navigieren",
"cmd.view_navigation_bar": "Navigationsleiste",
"cmd.view_next_tab": "Nächster Tab",
"cmd.view_normal_to": "Senkrecht zur Auswahl",
"cmd.view_previous_tab": "Vorheriger Tab",
"cmd.view_rename": "Benannte Ansicht umbenennen",
"cmd.view_render_frame": "Render-Bildhilfen",
"cmd.view_right": "Rechte Seitenansicht",
"cmd.view_save": "Neue benannte Ansicht",
"cmd.view_shots_strip": "Aufnahmenleiste",
@@ -1204,10 +1236,14 @@
"color.copy": "Klicken, um Farbwerte zu kopieren",
"color.edit": "Klicken, um Farbe zu bearbeiten",
"color.gamma": "Farbwerte im Gammaraum 0-255 anzeigen",
"color.hex": "Hex",
"color.hex_help": "#rrggbb oder #rrggbbaa eingeben; sechs Ziffern behalten die Deckkraft bei",
"color.hex_hint": "#rrggbb",
"color.hue": "Farbton",
"color.linear": "Farbwerte im linearen Raum 0-1 anzeigen",
"color.saturation_value": "Sättigung und Wert",
"color.selected": "Ausgewählte Farbe",
"config.column_filter_empty": "Keine passenden Spalten",
"contact.components_count": "{count} Komponenten",
"contact.enabled_label": "aktiviert",
"coupling.gear_1": "Zahnrad 1",
@@ -1318,6 +1354,7 @@
"help.licences": "Lizenzen",
"help.mit": "MIT-Lizenz",
"help.notice": "NOTICE",
"help.pointcloud.insert": "Fügt einen PLY-, XYZ- oder PTS-Scan als Punktwolke neben dem Modell ein. Verwenden Sie ihn als Referenz beim Modellieren anhand von Messdaten.",
"help.solid.chamfer": "Schneidet die gewählten Kanten mit einer ebenen Fase im eingestellten Abstand ab. Damit brechen Sie scharfe Kanten oder erleichtern das Einführen eines Stifts oder einer Schraube.",
"help.solid.combine": "Kombiniert Körper: vereinigt sie, zieht sie von einem Zielkörper ab oder behält nur das gemeinsame Volumen; die Werkzeugkörper können erhalten bleiben. Damit fügen Sie Teile zusammen, schneiden eine Form mit einer anderen aus oder finden, wo sich zwei Körper überschneiden.",
"help.solid.extrude": "Zieht ein Skizzenprofil über eine Strecke in die dritte Dimension und fügt dabei Material hinzu oder entfernt es. Damit machen Sie aus einer flachen Kontur einen Block, eine Erhebung oder eine Tasche.",
@@ -1331,6 +1368,9 @@
"help.solid.shell": "Höhlt einen Körper aus, lässt Wände in der eingestellten Dicke stehen und kann gewählte Flächen öffnen. Für Kästen, Deckel und andere dünnwandige Teile.",
"help.solid.sweep": "Führt ein Skizzenprofil entlang eines Pfads und erzeugt so einen Körper. Für Rohre, Schienen, Griffe und alle Teile mit gleichbleibendem Querschnitt entlang einer Kurve.",
"help.third_party": "Drittanbieterlizenzen",
"help.timeline.play": "Die verbleibenden Features nacheinander abspielen, mit einer halben Sekunde Pause nach jedem Neuaufbau. Diesen Befehl erneut ausführen oder Escape drücken, um anzuhalten; Zum Ende springt sofort ans Ende.",
"history.sketch_under_constrained": "Unterbestimmt ({count} Freiheitsgrade)",
"history.sketch_under_constrained_one": "Unterbestimmt ({count} Freiheitsgrad)",
"hole_presets.confirm_delete": "Löschen bestätigen",
"hole_presets.delete": "Löschen",
"hole_presets.delete_prompt": "Möchten Sie diese persönliche Vorlage wirklich löschen? Bereits vorhandene Bohrungen bleiben unverändert.",
@@ -1705,6 +1745,8 @@
"prefs.bodies_folders_never": "Nie",
"prefs.bodies_folders_several": "Nur bei mehreren Körpern",
"prefs.bottom": "Unten",
"prefs.bottom_centre": "Unten mittig",
"prefs.bottom_right": "Unten rechts",
"prefs.browser": "Browser",
"prefs.built_in": "Integriert",
"prefs.button_left": "Ziehen mit der linken Maustaste",
@@ -1756,6 +1798,8 @@
"prefs.history": "Verlauf",
"prefs.history_origin_bodies": "Ursprung und Körper oben zeigen",
"prefs.history_origin_bodies_note": "Der Verlauf links oder unter dem Browser beginnt mit dem Körper-Ordner der aktiven Komponente und dem Ursprung, mit Augen und Menüs wie im Browser. Der Verlauf unten bleibt unverändert.",
"prefs.history_play_button": "Schaltfläche „Verlauf abspielen“ in den Verlaufssteuerelementen",
"prefs.history_play_button_note": "Fügt „Verlauf abspielen“ zwischen „Einen Schritt zurück“ und „Einen Schritt vor“ in die Verlaufssteuerelemente ein. Mit einem Rechtsklick auf die Steuerelemente lässt sich die Schaltfläche auch ein- oder ausblenden.",
"prefs.history_sketches": "Skizzen",
"prefs.history_sketches_in_order": "In Erstellungsreihenfolge",
"prefs.history_sketches_note": "Wenn „Skizzen“ auf „Unter dem zugehörigen Feature“ eingestellt ist, wird jede Skizze im linken Verlauf eine Ebene unter dem ersten daraus erstellten Feature angezeigt, sofern der Bereich breit genug für die Namen ist. Die Timeline unten zeigt weiterhin die Reihenfolge, in der die Elemente erstellt wurden.",
@@ -1763,6 +1807,7 @@
"prefs.hold_stop_snapping": "Gedrückt halten, um das Einrasten zu deaktivieren",
"prefs.icons_only": "Nur Symbole",
"prefs.imported_file": "Importierte Datei",
"prefs.in_browser": "Im Browser",
"prefs.input": "Eingabe",
"prefs.interface": "Oberfläche",
"prefs.interface_language": "Oberflächensprache",
@@ -1774,15 +1819,33 @@
"prefs.left": "Links",
"prefs.left_click": "Linksklick",
"prefs.linked_designs": "Verknüpfte Designs",
"prefs.max_file_size": "Maximale Dateigröße zum Öffnen",
"prefs.max_file_size_design": "Designdateien",
"prefs.max_file_size_flag": "Dieser Lauf wurde mit --max-file-size {size} gestartet. Der Wert gilt, bis SolidCraft geschlossen wird. Diese Einstellungen gelten beim Start ohne diese Option.",
"prefs.max_file_size_note": "Standard: 512 MB und 256 MB; höchstens 16 GB. Das Öffnen einer Datei benötigt ein Mehrfaches ihrer Größe im Arbeitsspeicher. Ein Design mit großem Import benötigt zum Speichern und erneuten Öffnen eventuell eine höhere Grenze für Designdateien.",
"prefs.max_file_size_step": "STEP- und Importdateien",
"prefs.max_file_size_web": "Die Web-App öffnet STEP- und Importdateien bis 512 MB und Designs bis 256 MB: Ein Browser-Tab kann keine größeren Dateien aufnehmen. In der Desktop-App lassen sich diese Grenzen erhöhen.",
"prefs.megabytes": "MB",
"prefs.minutes_suffix": " min",
"prefs.origin_plane_names": "Namen der Ursprungsebenen",
"prefs.origin_plane_names_note": "Namen in Browser, Dialogen und Listen. {top} ist XY, {front} ist XZ und {right} ist YZ, mit Z nach oben. Befehle, Skripte und gespeicherte Konstruktionen behalten XY, XZ und YZ.",
"prefs.search": "Einstellungen suchen",
"prefs.search_empty": "Keine passenden Einstellungen",
"prefs.sketch_conflict_colour": "Widersprüchliche Geometrie in der Konfliktfarbe",
"prefs.sketch_conflict_colour_note": "Solange die Bedingungen einer Skizze im Konflikt stehen, werden auch die Kurven und Punkte, die eine nicht erfüllte Bedingung hält, in der Konfliktfarbe gezeichnet, nicht nur ihr Symbol oder ihre Bemaßung. Aus: Sie behalten ihre üblichen Farben.",
"prefs.sketch_state_icons": "Skizzensymbole in der Farbe ihres Zustands",
"prefs.sketch_state_icons_note": "Im Verlauf und im Browser nimmt das Symbol einer Skizze die Farbe ihres Zustands an (unterbestimmt, vollständig bestimmt oder im Konflikt), und ihr Tooltip nennt den Zustand. Aus: Alle Skizzen haben dasselbe Symbol.",
"prefs.sketch_tab_always": "Registerkarte Skizze immer zeigen",
"prefs.sketch_tab_always_note": "Die Registerkarte Skizze bleibt im Menüband direkt nach Modell, auch wenn keine Skizze offen ist. Ihre Zeichenwerkzeuge beginnen dann eine Skizze auf der ausgewählten Ebene oder Fläche oder auf der Ebene, die Sie als Nächstes wählen, und das Werkzeug ist darin bereit.",
"prefs.sketch_tracking_guides": "Ausrichtungshilfen für Mittelpunkte",
"prefs.sketch_tracking_guides_note": "Den Mauszeiger über einen Kreismittelpunkt oder eine Kantenmitte bewegen und dann waagerecht oder senkrecht bewegen, um eine temporäre gepunktete Hilfslinie anzuzeigen.",
"prefs.stand_up_unknown": "Für Dateien aus unbekannten Programmen",
"prefs.stand_up_unknown.ask": "In einem Dialog fragen",
"prefs.stand_up_unknown.note": "Einen Hinweis zeigen",
"prefs.stand_up_unknown.off": "Nicht anbieten",
"prefs.stand_up_unknown_note": "Wie das Aufrichten angeboten wird, wenn der Dateikopf kein Programm nennt, das bekanntlich mit Y nach oben speichert. Ein Hinweis erscheint nur, wenn die Datei auf dem Rücken zu liegen scheint; „In einem Dialog fragen“ fragt wie bisher bei jeder solchen Datei.",
"prefs.status_bar": "Statusleiste",
"prefs.status_bar_note": "Eine schmale Leiste am unteren Fensterrand zeigt, was gerade bearbeitet wird, den Zustand der offenen Skizze in seiner Farbe und die Einheiten der Konstruktion; ein Klick auf die Einheiten ändert sie. Der Zustand der Skizze steht dann nicht mehr in der Ecke der Ansicht.",
"prefs.theme_file_or_paste": "Datei oder Einfügen",
"prefs.theme_follow": "Einer Designdatei folgen",
"prefs.theme_follow_error": "Nicht angewendet: {error}. Das letzte gültige Design bleibt aktiv.",
@@ -1793,6 +1856,7 @@
"prefs.theme_import_hint": "Klicken, um eine Designdatei zu wählen, eine hierher ziehen oder mit kopiertem Design Strg+V (Cmd+V auf dem Mac) drücken",
"prefs.theme_paste": "Design einfügen",
"prefs.theme_paste_none": "Die Zwischenablage enthält kein SolidCraft-Design",
"prefs.toast_place": "Hinweise",
"properties.title": "Eigenschaften: {name}",
"recovery.days_ago": "vor {count} Tagen",
"recovery.detail": "{file} · {features} Merkmale · automatisch gespeichert {when}",
@@ -1802,7 +1866,47 @@
"recovery.never_saved": "nie gespeichert",
"render.add_ground": "Add fitted ground to setup",
"render.all_shots_label": "Alle Aufnahmen",
"render.appearance_editor.absorption": "Absorption",
"render.appearance_editor.base_colour": "Grundfarbe",
"render.appearance_editor.body_reason": "Optische Bindungen gelten für einen ganzen Körper. Wählen Sie Körper, um diese Einstellungen zu bearbeiten.",
"render.appearance_editor.boundary": "Grenzfläche",
"render.appearance_editor.box": "Quader",
"render.appearance_editor.choose_image": "Bild wählen…",
"render.appearance_editor.closed": "Geschlossener Körper",
"render.appearance_editor.coat": "Klarlack",
"render.appearance_editor.cpu_reason": "Benötigt CPU-Strahlverfolgung.",
"render.appearance_editor.glass": "Glas und Absorption",
"render.appearance_editor.glass_enable": "Physikalisches Glas für diesen Körper verwenden",
"render.appearance_editor.glass_note": "Geschlossenes Glas verwendet geometrische Abstände. Es kann nicht mit Klarlack oder Texturen auf demselben Körper kombiniert werden.",
"render.appearance_editor.gpu_reason": "Benötigt GPU-Pfadverfolgung.",
"render.appearance_editor.ior": "IOR",
"render.appearance_editor.maps": "Texturen",
"render.appearance_editor.normal": "Normale",
"render.appearance_editor.normal_strength": "Normalenstärke",
"render.appearance_editor.origin": "Ursprung",
"render.appearance_editor.recipe": "Rezept",
"render.appearance_editor.reflection_sampling": "Abtastung für alle reflektierenden Körper",
"render.appearance_editor.reflections": "Reflexionen",
"render.appearance_editor.remove": "Gespeicherte entfernen",
"render.appearance_editor.remove_note": "Die gespeicherte Optik wird aus dieser Aufnahme entfernt. Geometrie und zugewiesene Looks bleiben erhalten.",
"render.appearance_editor.remove_title": "Gespeicherte Optik entfernen?",
"render.appearance_editor.replace": "Gespeicherte Optik dieses Körpers ersetzen",
"render.appearance_editor.revalidate": "Diesen Körper erneut prüfen",
"render.appearance_editor.save": "Diese Optik speichern",
"render.appearance_editor.save_reason": "Zum Speichern wird physikalisches Glas auf einem aktuellen GPU-Körper benötigt. Klarlack und lokale Bildtexturen bleiben vorübergehend.",
"render.appearance_editor.saved": "Mit dieser Aufnahme gespeichert",
"render.appearance_editor.saved_state": "Diese Optik ist mit dieser Aufnahme gespeichert.",
"render.appearance_editor.scatter_reason": "Innere Streuung benötigt einen geschlossenen Körper.",
"render.appearance_editor.temporary": "Diese Optik gilt vorübergehend in diesem Tab. Speichern Sie sie mit der Aufnahme.",
"render.appearance_editor.thickness": "Dicke",
"render.appearance_editor.thickness_reason": "Dicke gilt für dünne Schichten; geschlossenes Glas verwendet geometrische Abstände.",
"render.appearance_editor.thin": "Dünne Schicht",
"render.appearance_editor.u_repeat": "U-Wiederholung",
"render.appearance_editor.v_repeat": "V-Wiederholung",
"render.appearance_editor.v_up": "Textur-V zeigt nach oben",
"render.appearance_editor.weight": "Gewicht",
"render.appearances": "Erscheinungsbilder",
"render.assign_help": "Klicken wendet den Look auf die Auswahl an. Ziehen zeigt eine Vorschau; ohne Auswahl startet Malen.",
"render.background": "Szenenhintergrund",
"render.bloom_enable": "Darstellungs-Bloom",
"render.bloom_help": "Kreativer Ausgabeglanz aus linearen Glanzlichtern mit drei normierten Durchläufen. Radius in Ausgabepixeln; Addition vor sRGB. Keine Linsen-, Volumen- oder Konvergenzsimulation. Das rohe EXR bleibt unverändert.",
@@ -1810,12 +1914,92 @@
"render.bloom_radius": "Bloom-Radius",
"render.bloom_strength": "Bloom-Stärke",
"render.bloom_threshold": "Linearer Glanzlichtschwellwert",
"render.browse_looks": "Durchsuchen…",
"render.camera_pitch": "Kameraneigung",
"render.camera_set": "Render-Kamera einstellen",
"render.category_metal": "Metall",
"render.category_paint": "Lack",
"render.category_plastic": "Kunststoff",
"render.category_wood": "Holz",
"render.check_opaque": "Transparenz: nur undurchsichtige Oberflächen; Hintergrund-Alpha wird unterstützt.",
"render.check_sorted_alpha": "Transparenz: Näherung mit sortiertem Alpha.",
"render.check_transmission": "Transparenz: physikalische Transmission.",
"render.children.absolute_floor": "Absolute Untergrenze",
"render.children.adaptive": "Adaptiv",
"render.children.add_look_reason": "Einen Look hinzufügen, um Aktivierung und Stärke zu bearbeiten.",
"render.children.all_shots": "Alle Aufnahmen",
"render.children.bloom": "Bloom",
"render.children.check": "Prüfen",
"render.children.check_now": "Jetzt prüfen",
"render.children.chromatic": "Chromatisch",
"render.children.compact": "Kompakt",
"render.children.contrast": "Kontrast",
"render.children.copy_image": "Kopieren",
"render.children.copy_job": "Auftrags-JSON kopieren",
"render.children.copy_request": "Anfrage-JSON kopieren",
"render.children.coverage_error": "Abdeckungsfehler",
"render.children.cpu": "CPU-Raytracing",
"render.children.denoise": "Rauschen im fertigen Bild reduzieren",
"render.children.depth": "Pfadtiefe",
"render.children.distortion": "Verzeichnung",
"render.children.edge_samples": "Kanten-Samples",
"render.children.effects_banner": "Diese Effekte benötigen GPU-Pathtracing. Das Öffnen ändert die Methode nicht.",
"render.children.enable_adaptive": "Unabhängige Pilotabtastung aktivieren, um adaptive Grenzen zu bearbeiten.",
"render.children.enable_bloom": "Bloom aktivieren, um Stärke, Schwelle und Radius zu bearbeiten.",
"render.children.finishing": "Nachbearbeitung",
"render.children.flare": "Lichtreflexe",
"render.children.fresnel": "Fresnel-Schichten",
"render.children.ghosts": "Geisterringe",
"render.children.glass": "Glastransport",
"render.children.go_to": "Zu {editor}",
"render.children.grain": "Korn",
"render.children.halo": "Lichthof",
"render.children.hdr": "HDR",
"render.children.keep_master": "Lineares Rohbild behalten",
"render.children.last_result": "Zuletzt: {number} · {width} × {height} · {phase}",
"render.children.lens_effects": "Objektiveffekte",
"render.children.look_summary": "{tone} · {count} Looks",
"render.children.looks": "Kreative Looks",
"render.children.memory": "Speicher",
"render.children.method": "Methode",
"render.children.minimum": "Minimum",
"render.children.needs_cpu": "Benötigt CPU-Raytracing. Das Öffnen ändert die Methode nicht.",
"render.children.nested": "Zertifizierte verschachtelte Dielektrika",
"render.children.not_checked": "Nicht geprüft",
"render.children.path": "Pathtracing",
"render.children.pilots": "Pilot-Samples",
"render.children.preview": "Vorschaudaten",
"render.children.progressive_reason": "Progressiv wählen, um Sampleanzahl und Startwert zu bearbeiten.",
"render.children.radius": "Radius",
"render.children.reflect_depth": "Reflexionstiefe",
"render.children.reflect_samples": "Reflexionssamples",
"render.children.regrade": "Neu graden",
"render.children.relative_error": "Relativer Fehler",
"render.children.render": "Rendern",
"render.children.render_shot": "Aufnahme rendern",
"render.children.renderer": "Renderer",
"render.children.renderers": "Renderer",
"render.children.request": "Diese Anfrage",
"render.children.reset_finishing": "Nachbearbeitung zurücksetzen",
"render.children.review_quality": "Qualitätsspezifikation prüfen…",
"render.children.rgb_gain": "RGB-Verstärkung",
"render.children.samples": "Samples",
"render.children.sampling": "Abtastung",
"render.children.saturation": "Sättigung",
"render.children.scene_summary": "{bodies} Körper · {triangles} Dreiecke",
"render.children.seed": "Startwert",
"render.children.sharpening": "Schärfen",
"render.children.single_image": "Einzelbild",
"render.children.soft_focus": "Weichzeichnung",
"render.children.streak": "Streifen",
"render.children.strength": "Stärke",
"render.children.studio": "Studio",
"render.children.threshold": "Schwelle",
"render.children.tone": "Tonwert",
"render.children.under_hood": "Technische Details",
"render.children.vignette": "Vignette",
"render.children.workstation": "Workstation",
"render.choose_look": "Zuerst einen Look in der Bibliothek wählen",
"render.clear_stage": "Remove saved stage",
"render.cpu_budget": "CPU-Ressourcenprofil",
"render.cpu_budget_bodies": "Körperobergrenze",
@@ -1828,7 +2012,88 @@
"render.cpu_budget_studio": "Studio (große Bilder)",
"render.cpu_budget_triangles": "Dreiecksobergrenze",
"render.cpu_budget_workstation": "Workstation (komplexe Szenen)",
"render.effects_gpu_only": "Diese Effekte erfordern GPU-Pfadverfolgung. Ein Seitenwechsel schaltet den Renderer niemals automatisch um.",
"render.emitted_axis": "Abstrahlachse",
"render.env_advanced": "Erweitert",
"render.env_backdrop": "Hintergrund",
"render.env_backdrop_pending": "Umgebungssichtbarkeit und Hintergrundunschärfe werden noch nicht unterstützt.",
"render.env_blur": "Unschärfe",
"render.env_change": "Ändern",
"render.env_choose_source": "Vor dem Bearbeiten eine Umgebung unter Studios und Umgebungen wählen.",
"render.env_clear": "Transparent",
"render.env_colour": "Farbe",
"render.env_environments": "Umgebungen",
"render.env_ground": "Boden",
"render.env_ground_pending": "Der endliche diffuse Boden empfängt Schatten. Reiner Schattenfang und Bodenspiegelungen werden noch nicht unterstützt.",
"render.env_intensity": "Intensität",
"render.env_invalid_edit": "Ungültige Umgebungsänderung.",
"render.env_physical_ground": "Physischer Boden",
"render.env_preview_help": "Illustrative Kugel, keine Vorschau der gewählten Umgebung.",
"render.env_reflection": "Spiegelung",
"render.env_ring_help": "Den Ring ziehen, um die Beleuchtung zu drehen. Mit Umschalt in 15°-Schritten einrasten.",
"render.env_rotate": "Drehen",
"render.env_set": "Renderumgebung einstellen",
"render.env_shadow_catcher": "Schattenfänger",
"render.env_show_environment": "Umgebung anzeigen",
"render.env_source": "Quelle",
"render.env_stage_details": "Bodenänderungen erfordern Raytracing und eine einzelne Bodenfläche. Andere Bühnenflächen unter Szene bearbeiten.",
"render.env_studios": "Studios",
"render.environment.albedo": "Albedo",
"render.environment.atmosphere": "Atmosphäre",
"render.environment.backdrop_note": "Ein Hintergrund ist nur für die Kamera sichtbar. Er beleuchtet nicht, wirft keine Schatten, reflektiert nicht und ist bei transparenter Ausgabe unzulässig.",
"render.environment.blur_pending": "Unschärfe nicht verfügbar: Der Renderer hat keine Hintergrund-Unschärfeeinstellung.",
"render.environment.builtin": "Integriertes HDR",
"render.environment.check": "Datei prüfen",
"render.environment.checked": "HDR-Datei geprüft. Beim Speichern werden diese Bytes eingebettet.",
"render.environment.choose": "HDR wählen…",
"render.environment.constant": "Konstant",
"render.environment.cyclorama": "Hohlkehle",
"render.environment.embedded": "In diesem Design gespeichert",
"render.environment.end": "Ende",
"render.environment.extinction": "Extinktion",
"render.environment.file": "Datei",
"render.environment.fit": "Boden anpassen und speichern",
"render.environment.floor_wall": "Boden und Wand",
"render.environment.gap": "Abstand",
"render.environment.gradient": "Verlauf",
"render.environment.gradient_gpu": "Ein Verlaufshintergrund benötigt GPU-Pfadverfolgung.",
"render.environment.ground": "Boden und Bühne",
"render.environment.hdr": "HDR",
"render.environment.hdr_file": "HDR-Datei",
"render.environment.horizon": "Horizont",
"render.environment.horizontal": "Horizontal",
"render.environment.keep": "Behalten",
"render.environment.lighting_samples": "Beleuchtungssamples",
"render.environment.margin": "Ausdehnungsrand",
"render.environment.max": "Max. Grenzen",
"render.environment.medium": "Teilnehmendes Medium",
"render.environment.min": "Min. Grenzen",
"render.environment.mode": "Modus",
"render.environment.needs_gpu": "Benötigt GPU-Pfadverfolgung.",
"render.environment.none": "Keine",
"render.environment.orientation": "Ausrichtung und Stärke",
"render.environment.phase": "Phase",
"render.environment.primaries": "Nicht angegebene Primärfarben als lineares sRGB behandeln",
"render.environment.primaries_gpu": "Die Interpretation nicht angegebener Primärfarben benötigt GPU-Pfadverfolgung.",
"render.environment.radial": "Radial",
"render.environment.radial_only": "Mittelpunkt und Radius gelten für den radialen Modus.",
"render.environment.reflectance": "Reflexionsgrad",
"render.environment.remove": "Bühne entfernen",
"render.environment.remove_confirm": "Gespeicherte Bühne entfernen?",
"render.environment.remove_note": "Entfernt die {count} passiven Flächen aus dieser Aufnahme. Der Kamerahintergrund bleibt erhalten.",
"render.environment.replace": "Ersetzen der vorhandenen Bühne bestätigen",
"render.environment.rotation_hdr": "Die Drehung benötigt beim CPU-Raytracing eine HDR-Quelle.",
"render.environment.samples_cpu": "GPU-Samples bestimmt das Pfadbudget; diese Einstellung benötigt CPU-Raytracing.",
"render.environment.saved_panels": "Gespeicherte Flächen {count}",
"render.environment.sky_ground": "Boden",
"render.environment.sky_note": "Originaler Himmelsverlauf für die Beleuchtung; keine kalibrierte Atmosphäre.",
"render.environment.source_raytrace": "Umgebungsquellen benötigen CPU- oder GPU-Raytracing.",
"render.environment.stage_raytrace": "Physische Bühnen benötigen CPU- oder GPU-Raytracing.",
"render.environment.start": "Anfang",
"render.environment.vertical": "Vertikal",
"render.environment.world": "Welt",
"render.environment.world_pending": "Welt-Hintergrund nicht verfügbar: Die Kamerasichtbarkeit der Umgebung ist noch nicht speicherbar.",
"render.environment.zenith": "Zenit",
"render.environment_tiles_require_raytrace": "Umgebungen benötigen CPU- oder GPU-Raytracing. Im Ausgabeeditor wählen.",
"render.error_area_samples": "area_samples muss 1, 4, 16 oder 64 sein",
"render.error_binding_allocation": "Materialzuordnung konnte nicht reserviert werden",
@@ -1893,14 +2158,40 @@
"render.fixed_camera": "Kamera",
"render.fixed_world": "Welt",
"render.fold_browser": "Browser einklappen",
"render.frame_aspect": "Seitenverhältnis",
"render.frame_centre_mark": "Mittelpunkt",
"render.frame_copy_limit": "Kein freier Name für eine Aufnahme-Kopie",
"render.frame_copy_name": "{name} Kopie {number}",
"render.frame_custom": "Benutzerdefiniert",
"render.frame_distance_unit": " × Größe",
"render.frame_duplicate": "Duplizieren",
"render.frame_exposure": "Belichtung",
"render.frame_fov": "Bildwinkel",
"render.frame_guides": "Hilfslinien",
"render.frame_invalid_aspect": "Ungültige Seitenverhältnis-Vorgabe",
"render.frame_lens": "Bildwinkel {fov}° · ≈ {mm} mm",
"render.frame_name": "Name",
"render.frame_output_size": "Ausgabegröße",
"render.frame_photo": "3:2 · Foto",
"render.frame_portrait": "4:5 · Hochformat",
"render.frame_presets": "Bildvorlagen",
"render.frame_presets_pending": "Kommt mit dem Aufnahmeeditor",
"render.frame_projection": "Projektion",
"render.frame_render_shot": "Diese Aufnahme rendern",
"render.frame_rule_thirds": "Drittelregel",
"render.frame_safe_area": "Sicherer Bereich",
"render.frame_shot_title": "Aufnahme · {name}",
"render.frame_square": "1:1 · Quadrat",
"render.frame_tall": "9:16 · Vertikal",
"render.frame_thirds": "Drittellinien",
"render.frame_wide": "16:9 · Breitbild",
"render.heading_batch": "Stapel",
"render.heading_frame": "Bildrahmen",
"render.heading_lens": "Objektiv",
"render.heading_results": "Ergebnisse",
"render.heading_shots": "Aufnahmen",
"render.hide_shots_label": "Aufnahmenleiste ausblenden",
"render.hover_look": "{object} · {look} · Zum Auswählen klicken",
"render.image_cancelled": "Rendering abgebrochen",
"render.image_cancelling": "Wird abgebrochen",
"render.image_completed": "Bild bereit zum Export",
@@ -1926,6 +2217,36 @@
"render.include_rig_cards": "Include passive cards and flags",
"render.inner_half_angle": "Innerer Halbwinkel",
"render.inspector": "Inspektor",
"render.inspector_advanced": "Erweitert",
"render.inspector_all_users": "Alle {count} Nutzer",
"render.inspector_applies_to": "Anwenden auf",
"render.inspector_both_users": "Beide Nutzer",
"render.inspector_chain": "Herkunft dieses Aussehens",
"render.inspector_colour": "Farbe",
"render.inspector_edit": "Bearbeiten",
"render.inspector_finish": "Oberfläche",
"render.inspector_from_material": "Vom Material",
"render.inspector_gloss": "Glanz",
"render.inspector_material": "Material",
"render.inspector_matte": "Matt",
"render.inspector_metal": "Metall",
"render.inspector_opacity": "Deckkraft",
"render.inspector_opaque_help": "Oberfläche und optische Felder verwenden opakes PBR (Deckkraft 1). Geringere Deckkraft verwendet skalare Schattierung.",
"render.inspector_pick_target": "Ein Ziel dieses Typs wählen, um sein Aussehen zu prüfen.",
"render.inspector_remove": "Überschreibung entfernen",
"render.inspector_replace": "Ersetzen…",
"render.inspector_reset": "Zurücksetzen",
"render.inspector_satin": "Seidenmatt",
"render.inspector_save_library": "In Bibliothek speichern…",
"render.inspector_set_all": "Gemischtes Aussehen. Eine Bearbeitung weist das Aussehen allen gewählten Zielen zu.",
"render.inspector_soon": "Demnächst",
"render.inspector_target_limit": "Zum Prüfen des Aussehens höchstens 10000 Ziele auswählen.",
"render.inspector_textures": "Texturen",
"render.inspector_this_body": "Dieser Körper",
"render.inspector_this_component": "Diese Komponente",
"render.inspector_this_face": "Diese Fläche",
"render.inspector_this_target": "Dieses Ziel",
"render.inspector_used_by": "Verwendet von {count}",
"render.layer_off_suffix": " (aus)",
"render.library_appearance_available": "Verfügbares Erscheinungsbild",
"render.library_applicable": "Passende Ressourcen",
@@ -1977,8 +2298,86 @@
"render.library_title": "Render-Ressourcenbibliothek",
"render.library_uniform_ack": "Einheitliche Näherung ohne räumliche oder erweiterte Effekte verwenden",
"render.library_users": "Verwendungen",
"render.light_aim": "Ausrichten auf",
"render.light_anchor_pending": "Das Koordinatensystem der Lichter kann noch nicht geändert werden.",
"render.light_azimuth": "Azimut",
"render.light_backend_limit": "Zum Bearbeiten CPU-Raytracing oder ein explizites GPU-Studio wählen. Alte GPU-Studiolichter sind schreibgeschützt.",
"render.light_behaviour": "VERHALTEN",
"render.light_default_fill": "Fülllicht",
"render.light_default_key": "Führungslicht",
"render.light_default_number": "Licht {number}",
"render.light_default_rim": "Kantenlicht",
"render.light_delete": "Löschen",
"render.light_distance": "Abstand",
"render.light_duplicate": "Duplizieren",
"render.light_elevation": "Höhenwinkel",
"render.light_gpu_punctual": "Punkt- und Spotlichter sind mit CPU-Raytracing verfügbar.",
"render.light_hard_shadow": "Dieses Licht wirft harte Schatten; Lichtquellenweichheit ist nicht verfügbar.",
"render.light_intensity": "Intensität",
"render.light_missing": "Dieses Licht existiert nicht mehr. Ein Licht im Browser auswählen.",
"render.light_place_highlight": "Nach Glanzlicht platzieren",
"render.light_place_pending": "Die Platzierung nach Glanzlicht benötigt Lichtauswahl im Ansichtsfenster und wird noch nicht unterstützt.",
"render.light_position": "POSITION",
"render.light_preview_help": "Die Live-Ansicht ist schattenfrei; Flächenlichter werden mit einer Mittelpunktprobe angenähert. Rendern nutzt das vollständige Lichtmodell.",
"render.light_product_centre": "Produktmitte",
"render.light_size": "Größe",
"render.light_softness": "Weichheit",
"render.light_temperature": "Farbtemperatur",
"render.light_temperature_help": "Angenäherte Schwarzkörperfarbe; als lineares RGB gespeichert.",
"render.light_type": "Typ",
"render.light_type_area": "Fläche",
"render.light_type_point": "Punkt",
"render.light_type_spot": "Spot",
"render.light_type_sun": "Sonne",
"render.light_view_only": "Solo und Stumm gelten für diese Ansicht und ihre Renderbilder; sie werden nie im Design gespeichert.",
"render.light_world_origin": "Weltursprung",
"render.lighting_aim_point": "Zielpunkt",
"render.lighting_apply": "Vorgabe anwenden",
"render.lighting_area_samples": "Flächenlicht-Samples",
"render.lighting_budget": "Budget",
"render.lighting_budget_help": "Die Anzahl ist schreibgeschützt. Lichter hinzufügen, duplizieren oder löschen; die Methode bestimmt die Grenzen.",
"render.lighting_colour": "Farbe",
"render.lighting_consent": "Richtungslichter durch diese Vorgabe ersetzen",
"render.lighting_custom": "Eigene Lichter",
"render.lighting_custom_help": "Eigene Lichter wandelt die Vorgabe in bearbeitbare Lichter mit je einer Zeile im Baum um.",
"render.lighting_direction": "Richtung X Y Z",
"render.lighting_direction_help": "Oder eine Richtung zum Licht eingeben (X Y Z).",
"render.lighting_distance_unit": " × Größe",
"render.lighting_edge_u": "Seitenvektor U",
"render.lighting_edge_v": "Seitenvektor V",
"render.lighting_falloff": "Abschwächung",
"render.lighting_falloff_help": "Die Intensität gilt im Referenzabstand.",
"render.lighting_height": "Höhe V",
"render.lighting_minimum": "Minimum",
"render.lighting_mute": "Dieses Licht stummschalten",
"render.lighting_point": "Punkt",
"render.lighting_preset": "Studiovorgabe",
"render.lighting_preset_cpu": "Richtungslicht-Vorgaben benötigen CPU-Raytracing. GPU-Beleuchtung verwendet explizite Sonnen- und Flächenlichter.",
"render.lighting_preset_row": "Vorgabe",
"render.lighting_radiance": "Strahldichte",
"render.lighting_reference": "Referenz",
"render.lighting_review_help": "Ersetzt die Richtungslichter. Punkt- und Flächenlichter, Umgebung, Schatten, Kamera und alle anderen Einstellungen bleiben erhalten.",
"render.lighting_review_title": "Beleuchtungsvorgabe prüfen",
"render.lighting_samples_cpu": "Flächenlicht-Samples gelten für CPU-Raytracing.",
"render.lighting_samples_need_area": "Ein CPU-Flächenlicht hinzufügen, um Samples einzustellen.",
"render.lighting_samples_reason": "Flächenlicht-Samples müssen 1, 4, 16 oder 64 sein.",
"render.lighting_shadow_cpu": "Der Schattenschalter benötigt CPU-Raytracing. GPU-Pfadverfolgung wirft immer Schatten.",
"render.lighting_shadows": "Schatten werfen",
"render.lighting_shadows_section": "Schatten und Sampling",
"render.lighting_shape": "Form",
"render.lighting_solo": "Nur dieses Licht",
"render.lighting_source": "Quelle",
"render.lighting_source_section": "Lichtquelle",
"render.lighting_spot_preserved": "Dieses Punktlicht behält seinen gespeicherten Lichtkegel bis zur Typänderung.",
"render.lighting_sun_distance": "Die Sonnenrichtung ist unabhängig von Abstand und Zielpunkt.",
"render.lighting_unsupported": "nicht unterstützt",
"render.lighting_used": "{used} von {limit}",
"render.lighting_width": "Breite U",
"render.lighting_world_position": "Welt X Y Z",
"render.lights_fixed_to": "Lichter gebunden an",
"render.look_applied": "{name} angewendet",
"render.look_material": "Material",
"render.look_pasted": "Look eingefügt",
"render.material_color_replace": "Basismap ersetzt Körperfarbe",
"render.material_limits": "Höchstens 128 Körperüberschreibungen, 32 getrennte Glaskörper, 64 Beschichtungen und 128 Texturbindungen. Identische Maps teilen Speicher; Geräte- und Gesamtspeichergrenzen bleiben aktiv.",
"render.material_metallic_map": "Metallanteil-Map (linear)",
@@ -1988,9 +2387,37 @@
"render.opaque_image_summary": "Vorschau-PNG · opakes PBR · Transparenz durch Blending",
"render.opaque_preview_help": "Opakes PBR und einfache Farben; Transparenz durch Blending. Brechung, HDRI und finales Rendering sind noch nicht verfügbar.",
"render.outer_half_angle": "Äußerer Halbwinkel",
"render.output_advanced": "Erweitert",
"render.output_backend_ready": "Bereit",
"render.output_check": "Prüfen",
"render.output_check_failed": "Prüfung · Fehler",
"render.output_check_help": "Prüfen bewertet diese Anfrage, ohne einen Renderauftrag zu starten.",
"render.output_check_summary": "Prüfen · Hinweise: {count}",
"render.output_copy": "Kopieren",
"render.output_copy_report": "Bericht kopieren",
"render.output_destination": "Ziel",
"render.output_destination_help": "Die Zieldatei wird beim Exportieren des fertigen Bildes gewählt.",
"render.output_dimensions": "Größe",
"render.output_effects": "Effekte",
"render.output_export": "PNG exportieren…",
"render.output_exr_unavailable": "EXR-Ausgabeeinstellungen sind hier nicht verfügbar. Linearer EXR-Export erfordert ein fertiges GPU-Bild mit gespeichertem linearem Original.",
"render.output_fit": "Einpassen",
"render.output_format": "Format",
"render.output_format_status": "PNG enthält das exakte fertige Anzeigebild. Optionales GPU-EXR bewahrt rohe lineare FLOAT32-Strahldichte vor Filtern. Export ersetzt nie durch Vorschaucache oder anderen Auftrag.",
"render.output_grading": "Farbkorrektur",
"render.output_image": "Bild",
"render.output_largest": "{width} × {height} max.",
"render.output_presets_help": "Format, Qualität und Prüfliste befinden sich im Ausgabeeditor.",
"render.output_quality": "Qualität",
"render.output_quality_waiting": "Qualitätsdefinition steht noch aus",
"render.output_ready": "Bereit zum Rendern",
"render.output_run_check": "Prüfung starten",
"render.output_size_limit": "{method}: bis zu {dimension} px pro Seite und {pixels} Pixel. Größte passende Größe: {width} × {height}.",
"render.output_size_ok": "Größe OK · {width} × {height} px",
"render.output_tools_inspector": "Größe und Format im Ausgabe-Inspektor bearbeiten.",
"render.output_view_image": "Bild anzeigen",
"render.paint_label": "Aufmalen",
"render.painting_with": "Malen mit {name}",
"render.passive_stage": "Render-only stage",
"render.passive_stage_help": "Finite passive panels belong only to rendered images. They do not add CAD bodies or mass. Placement is fixed after applying; intersecting product bounds refuse. CPU does not provide diffuse bounce lighting.",
"render.perspective": "Perspektivische Kamera",
@@ -2009,6 +2436,7 @@
"render.pick_help": "Körper, Fläche oder Komponente wählen. Ein Klick ins Leere löscht die Auswahl; Umschalt oder Strg fügt hinzu oder schaltet um. Hervorhebungen erscheinen nur in der Live-Produktansicht.",
"render.pick_label": "Auswahl",
"render.pick_up_label": "Aufnehmen",
"render.pick_up_prompt": "Ein Objekt anklicken, um seinen Look aufzunehmen",
"render.pick_waiting": "Die Produktauswahl wird noch nicht unterstützt.",
"render.preview": "Integrierte Vorschau",
"render.preview_help": "Rasterdarstellung mit gemischter Transparenz. Brechung, HDRI und finales Rendering sind noch nicht verfügbar.",
@@ -2019,11 +2447,24 @@
"render.property_source": "Quelle: {id} - {locator}",
"render.property_uncertainty": "Unsicherheit: {value}",
"render.property_unknown": "unbekannt",
"render.quality_balanced": "Ausgewogen",
"render.quality_custom": "Benutzerdefiniert",
"render.quality_draft": "Entwurf",
"render.quality_high": "Hoch",
"render.radial_assign": "Erscheinungsbild zuweisen",
"render.radial_compare": "Vergleichen",
"render.radial_fit": "Produkt einpassen",
"render.radial_save": "Aufnahme speichern",
"render.recent_looks": "Letzte Looks",
"render.regrade_label": "Neu abstimmen",
"render.reload_settings": "Gespeicherte Einstellungen laden",
"render.remove_override": "Überschreibung entfernen",
"render.replace_all": "Alle ersetzen",
"render.replace_label": "Ersetzen",
"render.replace_saved_surface": "Replace an existing saved binding for this target",
"render.replace_with": "Ersetzen durch",
"render.restore_camera": "Gespeicherte Kamera laden",
"render.result_actual": "100%",
"render.result_actual_size": "100%",
"render.result_reduced_display": "Anzeigevorschau auf die Geräte-/Cachegrenze reduziert. PNG und Export behalten die volle Auflösung; native 100%-Ansicht ist hier nicht verfügbar.",
"render.return_design": "Zurück zu Design",
@@ -2054,11 +2495,43 @@
"render.saved_surface_remove": "Remove saved binding",
"render.saved_surfaces": "Saved surface bindings",
"render.saved_surfaces_help": "Pinned built-in maps follow the selected occurrence in local millimeters. A replaced or missing target is an error, never an automatic reassignment.",
"render.scene_all_shots": "Alle Aufnahmen ({count})",
"render.scene_batch_reason": "Alle Aufnahmen benötigen die noch nicht verfügbare Renderwarteschlange.",
"render.scene_check_now": "Jetzt prüfen",
"render.scene_check_passed": "Prüfung bestanden · {notes} Hinweise",
"render.scene_check_stale": "Prüfung veraltet · erneut prüfen",
"render.scene_check_unchecked": "Noch nicht geprüft · 0 Hinweise",
"render.scene_light_summary": "{environment} · {lights} Lichter",
"render.scene_look_summary": "{looks} Looks · {overrides} Überschreibungen",
"render.scene_open_check": "Prüfung öffnen",
"render.scene_ready": "Bereit zum Rendern",
"render.scene_reminder": "Die Szene bewahrt den Entwurf. Geometrie, technische Eigenschaften und CAD werden in Render nie verändert.",
"render.scene_reminders": "Hinweise",
"render.scene_renderer_ready": "{renderer} bereit",
"render.scene_stages": "Phasen",
"render.search_appearances": "{count} Erscheinungsbilder durchsuchen",
"render.setup_name": "Name des Setups",
"render.shell_tab_appearance": "Aussehen",
"render.shell_tab_camera": "Kamera",
"render.shell_tab_scene": "SZENE",
"render.shot_aperture": "Blende",
"render.shot_distance": "Abstand",
"render.shot_dof": "Schärfentiefe",
"render.shot_edit_output": "In Ausgabe bearbeiten",
"render.shot_exposure_reason": "Belichtung benötigt CPU-Strahlverfolgung oder GPU-Pfadverfolgung.",
"render.shot_exposure_section": "Belichtung",
"render.shot_focus_distance": "Fokusabstand",
"render.shot_fov_reason": "Das Sichtfeld benötigt perspektivische Projektion.",
"render.shot_frame_subject": "Motiv einpassen",
"render.shot_invalid_camera": "Kamerawerte müssen endlich und im gültigen Bereich sein.",
"render.shot_lens": "Objektiv",
"render.shot_lens_enable_reason": "Schärfentiefe aktivieren, um Blende und Fokusabstand zu bearbeiten.",
"render.shot_lens_gpu_reason": "Schärfentiefe benötigt GPU-Pfadverfolgung.",
"render.shot_lens_perspective_reason": "Schärfentiefe benötigt perspektivische Projektion.",
"render.shot_look_selection": "Auswahl anvisieren",
"render.shot_selection_reason": "Einen Körper oder eine Fläche als Ziel auswählen.",
"render.shot_size": "Größe",
"render.shot_target": "Ziel",
"render.shots_camera_changed": "Die Kamera wurde seit dem Speichern dieser Aufnahme geändert",
"render.shots_name_help": "Geben Sie einen eindeutigen Namen für die aktuelle Aufnahme ein.",
"render.shots_no_result": "Noch kein Renderbild",
@@ -2067,19 +2540,114 @@
"render.shots_save": "Aufnahme speichern",
"render.shots_update": "Aufnahme aktualisieren",
"render.show_shots_label": "Aufnahmenleiste einblenden",
"render.size_4k": "4K",
"render.size_4k_uhd": "4K UHD",
"render.size_custom": "Benutzerdefiniert…",
"render.size_full_hd": "Full HD",
"render.size_hd": "HD",
"render.size_presets": "Größenvorlagen",
"render.size_presets_pending": "Kommt mit dem Ausgabeeditor",
"render.size_preview": "Vorschau",
"render.size_square": "Quadrat",
"render.spot_cone": "Spotkegel",
"render.stage_frame": "Bildausschnitt",
"render.stage_layout.appearance_note": "Zum Anwenden auf die Auswahl klicken.",
"render.stage_layout.studio_note": "Vor dem Anwenden zur Prüfung klicken.",
"render.stage_light": "Licht",
"render.stage_look": "Aussehen",
"render.stage_orthographic": "Orthografisch",
"render.stage_output": "Ausgabe",
"render.stage_panel_count": "Saved panels",
"render.stage_panels.acknowledge": "Ich bestätige den Ersatz und die Einschränkungen",
"render.stage_panels.appearance_note": "Zum Anwenden auf die Auswahl klicken. Auf das Modell ziehen. Ohne Auswahl aktiviert ein Klick Malen.",
"render.stage_panels.apply": "Anwenden",
"render.stage_panels.apply_studio": "Studio anwenden",
"render.stage_panels.badge_blocked": "gesperrt",
"render.stage_panels.badge_native": "nativ",
"render.stage_panels.badge_projection": "Projektion",
"render.stage_panels.badge_reference": "Referenz",
"render.stage_panels.badge_specification": "nur Spez.",
"render.stage_panels.candidate_summary": "Kandidaten: {count} belegte Werte. Güte und Oberfläche müssen geprüft werden.",
"render.stage_panels.captured_bounds": "Erfasste Szenengrenzen verwenden",
"render.stage_panels.centre": "Mitte",
"render.stage_panels.depth": "Tiefe",
"render.stage_panels.environments": "Umgebungen",
"render.stage_panels.extent": "Ausdehnung",
"render.stage_panels.fit_save": "Einpassen und speichern",
"render.stage_panels.gpu_required": "Benötigt GPU-Pfadverfolgung",
"render.stage_panels.keep": "Behalten",
"render.stage_panels.kept": "Beibehalten",
"render.stage_panels.kept_fields": "Kamera, Abtastung, Abmessungen, optische Bindungen, CAD-Geometrie und technische Eigenschaften.",
"render.stage_panels.kept_quality": "Methode, Kamera, Beleuchtung, Umgebung, Bühne, Optik, Belichtung und Tonwertabbildung.",
"render.stage_panels.mine": "Meine",
"render.stage_panels.mine_pending": "Eigene Studios können noch nicht gespeichert werden.",
"render.stage_panels.omits": "Ausgelassen",
"render.stage_panels.paint_pending": "Malen und Zuweisen per Ziehen werden noch nicht unterstützt. Zum Anwenden ein Ziel wählen.",
"render.stage_panels.partial_reference": "Kandidaten: nur belegte Werte; Güte, Zustand und Quellen prüfen. Unbekannte Werte bleiben unbekannt.",
"render.stage_panels.plane": "Ebene",
"render.stage_panels.prepare_plan": "Erstellungsplan vorbereiten",
"render.stage_panels.projects": "Projiziert",
"render.stage_panels.quality_ack": "Ich bestätige das feste Budget und seine Auslassungen",
"render.stage_panels.quality_omissions": "Adaptives Stoppen und Fehlerziele, separate Transmissionstiefe, Russian-Roulette-Regeln, lineare Rohausgabe, EXR-Master und Konvergenznachweis.",
"render.stage_panels.reference": "Referenz",
"render.stage_panels.references": "Referenzen",
"render.stage_panels.remove_optics": "Optik entfernen",
"render.stage_panels.remove_optics_help": "Entfernt die gespeicherte Optik aus dieser Aufnahme. Die Quellgeometrie bleibt erhalten.",
"render.stage_panels.remove_optics_title": "Gespeicherte Optik entfernen?",
"render.stage_panels.remove_shot": "Aufnahme entfernen",
"render.stage_panels.remove_stage": "Bühne entfernen",
"render.stage_panels.remove_stage_help": "Entfernt die gespeicherten passiven Flächen dieser Aufnahme. Der Kamerahintergrund bleibt erhalten.",
"render.stage_panels.remove_stage_title": "Gespeicherte Bühne entfernen?",
"render.stage_panels.repeat": "Wiederholung",
"render.stage_panels.replaces": "Ersetzt",
"render.stage_panels.replaces_environment": "Umgebung",
"render.stage_panels.replaces_maps": "Temporäre Texturen am gewählten Körper; gespeicherte Optik kann im Konflikt stehen.",
"render.stage_panels.replaces_physical": "Nichts. Dieser Plan ist schreibgeschützt.",
"render.stage_panels.replaces_quality": "Bildabmessungen, feste Abtastungen, Pfadtiefe, Startwert und Entrauschen.",
"render.stage_panels.replaces_rig": "Beleuchtung, Umgebung und Bühne",
"render.stage_panels.replaces_saved_maps": "Gespeicherte Oberflächentexturen am gewählten Körper; temporäre Einstellungen können kollidieren.",
"render.stage_panels.replaces_stage": "Gespeicherter Boden und passive Bühnenflächen",
"render.stage_panels.replaces_studio": "Beleuchtung, Umgebung, Belichtung und Bühne",
"render.stage_panels.replaces_uniform": "Deckendes Aussehen des gewählten Körpers. Räumliche Texturen werden durch einheitliche Werte angenähert.",
"render.stage_panels.review_environment": "Umgebung prüfen",
"render.stage_panels.review_maps": "GPU-Texturen prüfen",
"render.stage_panels.review_physical": "Physikalischer Referenzplan",
"render.stage_panels.review_quality": "Festes Abtastbudget verwenden",
"render.stage_panels.review_rig": "Lichtaufbau einpassen",
"render.stage_panels.review_saved_maps": "Gespeicherte Texturen prüfen",
"render.stage_panels.review_stage": "Boden und Bühne prüfen",
"render.stage_panels.review_studio": "Natives Studio prüfen",
"render.stage_panels.review_uniform": "Einheitliches Aussehen prüfen",
"render.stage_panels.rig_summary": "Erstellter Lichtaufbau · {emitters} Lichtquellen, {cards} passive Flächen",
"render.stage_panels.rigs": "Lichtaufbauten",
"render.stage_panels.save_maps": "Texturen in dieser Aufnahme speichern",
"render.stage_panels.scope": "Bereich",
"render.stage_panels.search_studios": "Studios suchen",
"render.stage_panels.search_surfaces": "Oberflächen und Referenzen suchen",
"render.stage_panels.source_note": "Erstellte Grundfarbentextur. Kein gemessenes Material.",
"render.stage_panels.specifications": "Spezifikationen · schreibgeschützt",
"render.stage_panels.studio_ack": "Ersatz von Beleuchtung, Umgebung, Belichtung und Bühne bestätigen",
"render.stage_panels.studio_note": "Zum Prüfen anklicken. Beleuchtung, Umgebung und Bühne werden erst nach Bestätigung ersetzt. Lichter bleiben bearbeitbar.",
"render.stage_panels.studios": "Studios",
"render.stage_panels.subtitle_environment": "Originale HDR-Umgebung · gesamte Szene",
"render.stage_panels.subtitle_maps": "Erstellte räumliche Texturen · temporäre Vorschau",
"render.stage_panels.subtitle_physical": "Schreibgeschützter Plan · kein Material erstellt oder zugewiesen",
"render.stage_panels.subtitle_quality": "Festes GPU-Budget · zukünftige Anforderungen ausgelassen",
"render.stage_panels.subtitle_rig": "Erstellter Lichtaufbau · Lichtquellen und passive Flächen",
"render.stage_panels.subtitle_saved_maps": "Erstellte Texturen · mit dieser Aufnahme gespeichert",
"render.stage_panels.subtitle_stage": "Physischer Boden und Bühne · an das Produkt angepasst",
"render.stage_panels.subtitle_studio": "Natives Studio · für die gesamte Szene",
"render.stage_panels.subtitle_uniform": "Einheitliche Näherung · kein gemessenes Material",
"render.stage_panels.surfaces": "Oberflächen",
"render.stage_panels.surfaces_references": "Oberflächen und Referenzen",
"render.stage_panels.target": "Ziel",
"render.stage_panels.use_budget": "Dieses Budget verwenden",
"render.stage_panels.use_maps": "GPU-Texturen verwenden",
"render.stage_panels.use_uniform": "Einheitlich verwenden",
"render.stage_preview_note": "Integrierte Vorschau · direktes Licht",
"render.state_completed": "Fertiges Bild",
"render.state_in_progress": "Bild in Bearbeitung",
"render.state_model": "Modellvorschau",
"render.strip_label": "Leiste",
"render.studio_tiles_require_gpu": "Studios benötigen GPU-Pfadverfolgung. Im Ausgabeeditor GPU wählen.",
"render.studios_environments": "Studios und Umgebungen",
@@ -2122,12 +2690,20 @@
"render.unavailable_preview": "Dieses Setup verlangt ein nicht verfügbares Vorschauprofil.",
"render.unsaved": "Ungespeicherte Vorschauänderungen",
"render.use_preview": "Integrierte Vorschau verwenden",
"render.wait_add_light": "Noch nicht unterstützt: benannte Lichtquellen erstellen",
"render.wait_batch": "Noch nicht unterstützt: Renderwarteschlange gespeicherter Aufnahmen",
"render.wait_compare": "Noch nicht unterstützt: Vergleich gespeicherter Bilder",
"render.wait_paint": "Noch nicht unterstützt: Produktauswahl und Auftragen von Erscheinungsbildern",
"render.wait_pick_up": "Noch nicht unterstützt: Produktauswahl und Übernehmen von Erscheinungsbildern",
"render.wait_replace": "Noch nicht unterstützt: Ersetzen aller Verwendungen eines Erscheinungsbilds",
"render.wait_solo": "Noch nicht unterstützt: Lichtsichtbarkeit und Solo-Steuerung",
"render.wear_applies_to": "Anwenden auf",
"render.wear_layer_count": "{count} Ebenen",
"render.wear_layer_one": "{count} Ebene",
"render.wear_layers": "Ebenen",
"render.wear_no_layers": "Keine Ebenen",
"render.wear_selected_layer": "Ausgewählte Ebene",
"render.wear_title": "Abnutzung",
"sample.bracket.about": "Grundflansch mit Kantenflanschen und einer Umkantung nach einer 2-mm-Blechregel",
"sample.bracket.name": "Blechwinkel",
"sample.enclosure.about": "Ausgehöhlter Block mit Lippe, Schraubenerhöhungen, Auflage und Rastverbindung",
@@ -2224,6 +2800,10 @@
"sketch_text.path_hint": "Eine Skizzenkurve, der der Text folgt: hier klicken, dann die Kurve",
"sketch_text.use_font_file": "Schriftdatei {path} verwenden",
"solid": "Volumenkörper",
"status.editing": "{name} wird bearbeitet",
"status.under_constrained": "Unterbestimmt ({count} Freiheitsgrade)",
"status.under_constrained_one": "Unterbestimmt ({count} Freiheitsgrad)",
"status.units_tip": "Die Einheiten der Konstruktion. Zum Ändern klicken",
"the angle must be a number": "der Winkel muss eine Zahl sein",
"the curves must be in one sketch": "die Kurven müssen in einer Skizze liegen",
"the direction must be an axis, a sketch line or a straight edge": "die Richtung muss eine Achse, eine Skizzenlinie oder eine gerade Kante sein",
@@ -2253,8 +2833,10 @@
"timeline.move_to_group": "Merkmale in Ordner verschieben",
"timeline.rename_group": "Merkmalsordner umbenennen",
"timeline.reorder_many": "Merkmale neu ordnen",
"timeline.suppress_features": "Merkmale unterdrücken",
"timeline.suppress_folders_tip": "Unterdrückt alle Features in den Ordnern und ihren Unterordnern oder hebt die Unterdrückung auf",
"timeline.ungroup": "Merkmalsordner entfernen",
"timeline.unsuppress_features": "Unterdrückung der Merkmale aufheben",
"to the face": "bis zur Fläche",
"to the next face": "bis zur nächsten Fläche",
"toolbar.customize_note": "Registerkarte {tab}. Markieren Sie einen Befehl, um ihm eine Schaltfläche in der Werkzeugleiste zu geben. Sie können auch eine Zeile aus dem Aufklappmenü eines Panels auf die Werkzeugleiste ziehen, eine Schaltfläche zum Entfernen aus der Werkzeugleiste ziehen oder die Stecknadel einer Menüzeile verwenden.",
@@ -2603,6 +3185,9 @@
"ui.blocked": "Verdeckt",
"ui.bodies": "Körper",
"ui.bodies_all_if_none": "Körper (alle, wenn keine)",
"ui.body_kind_mesh": "Netzkörper",
"ui.body_kind_solid": "Volumenkörper",
"ui.body_kind_surface": "Flächenkörper",
"ui.bottom": "Unten",
"ui.box": "Block",
"ui.break": "Unterbrechen",
@@ -2615,6 +3200,8 @@
"ui.cancel": "Abbrechen",
"ui.canvases": "Kanvas",
"ui.center": "Mittelpunkt",
"ui.center_arc_follows_cursor": "Mittelpunkt-Kreisbogen folgt der Richtung des Mauszeigers",
"ui.center_arc_follows_cursor_tip": "Ein Mittelpunkt-Kreisbogen läuft im oder gegen den Uhrzeigersinn, je nachdem, wie der Mauszeiger um seinen Mittelpunkt geführt wird. Aus: immer gegen den Uhrzeigersinn vom Start aus.",
"ui.centerline": "Mittellinie",
"ui.chain": "Kette",
"ui.chamfer": "Abschrägung",
@@ -2695,6 +3282,7 @@
"ui.design_properties.part_number": "Teilenummer",
"ui.design_properties.project": "Projekt",
"ui.design_properties.revision": "Revision",
"ui.design_saved": "Gespeichert unter {path}",
"ui.diameter": "Durchmesser",
"ui.dimension": "Maß",
"ui.direct_interaction": "Direkte Bearbeitung",
@@ -2873,6 +3461,10 @@
"ui.history_first": "Zum Anfang",
"ui.history_forward": "Einen Schritt vor",
"ui.history_last": "Zum Ende",
"ui.history_play_button_hide": "Wiedergabe-Schaltfläche ausblenden",
"ui.history_play_button_show": "Wiedergabe-Schaltfläche einblenden",
"ui.history_play_finish_action": "Die aktuelle Aktion abschließen, bevor der Verlauf abgespielt wird",
"ui.history_play_roll_back": "Die Verlaufsmarkierung vor dem Abspielen zurücksetzen",
"ui.history_title": "Verlauf",
"ui.hole": "Bohrung",
"ui.hole_tap_type": "Gewindetyp",
@@ -2997,6 +3589,15 @@
"ui.plugins_skipped": "{count} Ordner konnte(n) nicht gelesen werden.",
"ui.plugins_version": "{version}",
"ui.point": "Punkt",
"ui.point_cloud_auto_range": "Bereich automatisch",
"ui.point_cloud_color_by": "Färben nach",
"ui.point_cloud_file_colors": "Farben der Datei",
"ui.point_cloud_height_high": "Oberste Höhe",
"ui.point_cloud_height_low": "Unterste Höhe",
"ui.point_cloud_no_file_colors": "Die Datei hat keine Farben",
"ui.point_cloud_single_color": "Einheitliche Farbe",
"ui.point_cloud_size": "Punktgröße",
"ui.point_cloud_units": "Einheit der Datei",
"ui.point_under_the_cursor": "Punkt unter dem Cursor",
"ui.points": "Punkte",
"ui.polygon": "Polygon",
@@ -3041,6 +3642,8 @@
"ui.restore_defaults": "Standardeinstellungen wiederherstellen",
"ui.reverse_horizontal_pan_direction": "Horizontale Schwenkrichtung umkehren",
"ui.reverse_horizontal_pan_tip": "Horizontales Zwei-Finger-Scrollen und das Daumenrad schwenken in die andere Richtung",
"ui.reverse_trackpad_orbit_direction": "Drehrichtung am Touchpad umkehren",
"ui.reverse_trackpad_orbit_tip": "Umschalt mit Zwei-Finger-Scrollen dreht die Ansicht in die andere Richtung",
"ui.reverse_vertical_pan_direction": "Vertikale Schwenkrichtung umkehren",
"ui.reverse_vertical_pan_tip": "Vertikales Zwei-Finger-Scrollen schwenkt in die andere Richtung",
"ui.reverse_zoom_direction": "Zoomrichtung umkehren",
@@ -3180,6 +3783,12 @@
"ui.view_angles_roll": "Rollen",
"ui.view_angles_yaw": "Gieren",
"ui.view_centre": "Ansichtszentrum",
"ui.viewport_status_clear": "{name} ausschalten",
"ui.viewport_status_clear_hint": "{name} ausschalten · Esc",
"ui.viewport_status_key": "Legende für {name} anzeigen",
"ui.viewport_status_minimum_radius": "Mindestradius",
"ui.viewport_status_pairs": "{count} Paare",
"ui.viewport_status_stripes": "{count} Streifen",
"ui.viewport_theme_follow": "Dem Design folgen",
"ui.visual_shaded_hidden_edges": "Schattiert mit verdeckten Kanten",
"ui.visual_shaded_with_edges": "Schattiert mit Kanten",
@@ -3245,6 +3854,7 @@
"use a positive nominal diameter and a pitch smaller than it": "einen positiven Nenndurchmesser und eine kleinere Steigung verwenden",
"values must be finite numbers": "Werte müssen endliche Zahlen sein",
"values must be numbers or expressions": "Werte müssen Zahlen oder Ausdrücke sein",
"view.render_inspector": "Render-Inspektor",
"↑ ↓ choose · Enter / Tab complete · Esc dismiss": "↑ ↓ auswählen · Eingabe / Tab vervollständigen · Esc schließen",
"⌘Enter continues on GitHub.": "⌘Enter geht weiter zu GitHub."
}
+59
View File
@@ -3,11 +3,18 @@
"Center X": "Centre X",
"Center Y": "Centre Y",
"Center of mass": "Centre of mass",
"Circle center": "Circle centre",
"Customize Toolbar": "Customise Toolbar",
"Customize…": "Customise…",
"Face center": "Face centre",
"Favorites": "Favourites",
"Mass Center": "Mass Centre",
"Modeled": "Modelled",
"cmd.component_cycle_color": "Cycle Component Colour",
"cmd.construct_point_center": "Point At Centre Of Circle/Sphere/Torus",
"cmd.inspect_center_of_mass": "Centre of Mass",
"cmd.inspect_colored_components": "Enable Component Colours",
"cmd.inspect_colored_components_disable": "Disable Component Colours",
"cmd.render_aging_describe": "Layered Surface Aging",
"cmd.render_effects_describe": "Lens and Creative Effects",
"cmd.sketch_arc_center_point": "Centre Point Arc",
@@ -16,15 +23,34 @@
"cmd.sketch_slot_arc_center": "Centre Point Arc Slot",
"cmd.sketch_slot_center_point": "Centre Point Slot",
"cmd.sketch_slot_center_to_center": "Centre to Centre Slot",
"color.copy": "Click to copy colour values",
"color.edit": "Click to edit colour",
"color.gamma": "Showing colour values in 0-255 gamma space",
"color.linear": "Showing colour values in 0-1 linear space",
"color.selected": "Selected colour",
"pattern.alignment_hint": "Counts include the original. Centre balances copies; Flip chooses the extra side for even totals.",
"prefs.logo_theme": "Theme's colours",
"prefs.max_file_size": "Largest file to open",
"prefs.max_file_size_design": "Design files",
"prefs.max_file_size_flag": "This run started with --max-file-size {size}, which applies until SolidCraft closes. These settings apply when it starts without it.",
"prefs.max_file_size_note": "Defaults: 512 MB and 256 MB; at most 16 GB. Opening a file takes several times its size in memory. A design that keeps a large import may need a higher design file limit to save and reopen.",
"prefs.max_file_size_step": "STEP and import files",
"prefs.max_file_size_web": "The web app opens STEP and import files up to 512 MB and designs up to 256 MB: a browser tab can't hold larger files. The desktop app can raise these limits.",
"prefs.megabytes": "MB",
"prefs.sketch_conflict_colour": "Conflicting geometry in the conflict colour",
"prefs.sketch_conflict_colour_note": "While a sketch's constraints conflict, the curves and points a failing constraint holds are drawn in the conflict colour too, not only its glyph or dimension. Off: they keep their usual colours.",
"prefs.sketch_state_icons": "Sketch icons in the colour of their state",
"prefs.sketch_state_icons_note": "In History and the browser, a sketch's icon takes the colour of its state (under constrained, fully constrained or conflicting) and its tooltip names the state. Off: every sketch has the same icon.",
"prefs.sketch_tracking_guides": "Centre and midpoint alignment guides",
"prefs.sketch_tracking_guides_note": "Hover over a circle centre or straight-edge midpoint, then move horizontally or vertically to show a temporary dotted guide.",
"prefs.status_bar_note": "A thin bar along the window's bottom edge shows what is being edited, the open sketch's state in its colour and the design's units; a click on the units changes them. The sketch's state then no longer shows in the view's corner.",
"prefs.theme_follow": "Follow a theme file",
"prefs.theme_follow_error": "Not applied: {error}. The last good theme stays on.",
"prefs.theme_follow_launch": "Followed for this run only (--theme-file); reloaded whenever another tool rewrites it.",
"prefs.theme_follow_note": "Reloaded whenever another tool rewrites it. Choosing a theme stops following it.",
"prefs.theme_follow_off": "Off",
"prefs.theme_follow_stop": "Stop following",
"prefs.view": "View behaviour",
"render.aging_add": "Add aging layer",
"render.aging_airborne": "Airborne dust / participating medium",
"render.aging_airborne_help": "Airborne dust is a separate finite homogeneous scattering volume. It changes transport and raw EXR, not the surface-aging stack. Existing volume/glass/denoising restrictions remain explicit; no atmosphere is added automatically.",
@@ -52,6 +78,8 @@
"render.aging_target_help": "A named target must still match its captured index and name. Global masks are world-anchored; they do not follow moving parts. This is neither cavity detection nor true edge wear. Filter the list to reach additional bodies.",
"render.aging_target_search": "Filter body names",
"render.aging_upward": "Upward-facing deposition",
"render.backdrop_first": "Start / centre colour",
"render.backdrop_second": "End / edge colour",
"render.backdrop_x": "Centre X",
"render.backdrop_y": "Centre Y",
"render.background_camera_section": "Camera background · PNG presentation",
@@ -59,10 +87,15 @@
"render.background_hdr_separate": "The current HDR resources illuminate and reflect on surfaces; they are not automatically displayed as a panorama behind the subject. Changing a gradient does not rotate or recolour the lighting.",
"render.background_lighting_section": "HDR illumination · separate from camera background",
"render.background_no_alpha_override": "A camera background is not added to transparent output silently. Raw-master regrading uses captured coverage and does not reapply denoising; the source EXR remains unchanged.",
"render.background_not_light": "Background colour is presentation, not an additional lighting source.",
"render.background_regrade": "Apply to retained raw master",
"render.background_stage_occlusion": "This shot includes physical stage geometry. A large floor or wall can fill the frame and hide a camera-only background. Clear or resize the stage deliberately, or change its physical reflectance. Regrading cannot remove captured geometry.",
"render.background_workflow": "Choose the background you intend: a camera-only colour/gradient, a physical stage that receives light, or HDR illumination. They are independent. Live Preview is a modelling view; render a new image or regrade a retained master to see camera finishing.",
"render.base_color": "Base colour · sRGB",
"render.bloom_help": "Creative output-only glow from positive linear highlights, spread with three normalised box passes. Radius is in output pixels. Added in linear display light before sRGB; not a lens, volumetric effect or convergence improvement. The raw EXR is unchanged.",
"render.chromatic_offset": "Chromatic edge offset",
"render.cpu_light_help": "Up to eight directional lights. An empty custom list turns them off; selecting a preset restores its lights. Colours are linear RGB and intensity is relative, not watts.",
"render.cpu_linear_color": "Linear colour (R, G, B)",
"render.effects_gpu_only": "These effects require GPU path tracing. Changing the page never switches the renderer automatically.",
"render.effects_help": "Combine ordered colour looks and image-space lens effects. Rendering and raw-master regrading use the same saved settings. Raw EXR stays unchanged. These are original artistic controls, not calibrated lens or branded-film emulations.",
"render.effects_reset_lens": "Reset lens effects",
@@ -73,6 +106,9 @@
"render.flare_streak": "Anamorphic-style streak",
"render.flare_strength": "Highlight flare strength",
"render.flare_threshold": "Scene-linear flare threshold",
"render.hdr_primaries_declared": "The source declares its colour primaries.",
"render.hdr_primaries_srgb": "Colour primaries: sRGB/D65",
"render.hdr_primaries_undeclared": "The source does not declare primaries; review the renderer colour requirements.",
"render.layer_down": "Move down",
"render.layer_enabled": "Layer enabled",
"render.layer_remove": "Remove layer",
@@ -80,6 +116,13 @@
"render.layer_up": "Move up",
"render.lens_effects_help": "Flare uses up to four separated bright sources in the actual linear image. Ghosts, halo, streaks, chromatic offsets and radial distortion are artistic image-space approximations. Spatial effects need opaque output; outside samples extend the image edge. Grain is deterministic. No physics, EXR or geometry is altered.",
"render.lens_effects_title": "Lens-inspired & photographic",
"render.library_center": "Rig centre",
"render.library_favorite": "Add favourite",
"render.library_favorites": "Favourites",
"render.library_inspect_only": "Select to inspect; nothing is applied automatically. Favourites and recent history belong to this open document session.",
"render.library_rig_help": "Fit once at an explicit centre and physical extent. Complete rigs include passive cards; calibration blockers still refuse. Conservative emitter/card clearance is checked before saving.",
"render.library_source_preview_help": "Authored base-colour source map. This is not a rendered or measured material preview.",
"render.library_unfavorite": "Remove favourite",
"render.look_add": "Add colour look",
"render.look_bleach": "Bleach-bypass-inspired",
"render.look_cool": "Cool",
@@ -91,6 +134,11 @@
"render.look_teal_orange": "Teal / orange",
"render.look_title": "Creative look stack",
"render.look_warm": "Warm",
"render.material_color_map": "Base colour image (sRGB)",
"render.material_color_replace": "Base map replaces body colour",
"render.material_map_required": "Choose a colour image or a normal image before using maps.",
"render.material_maps": "Planar colour and normal maps",
"render.material_maps_help": "PNG/JPEG up to 1024×1024; 16 MiB encoded total. U and V are orthogonal world-mm repeat vectors (maximum 128 repeats). Colour is sRGB; normal data uses OpenGL +Y. Files are captured at Check/Start.",
"render.opaque_preview_help": "Opaque PBR and simple colours; blended transparency. Refraction, HDRI and final rendering are not available yet.",
"render.page_aging": "Aging & contamination",
"render.page_background": "Backgrounds",
@@ -100,15 +148,26 @@
"render.ribbon_effects": "Effects",
"render.sharpening": "Detail sharpening",
"render.soft_focus": "Soft focus",
"render.studio_center": "Centre X, Y, Z (mm)",
"render.studio_hdr_help": "Radiance .hdr, 2:1 panorama, up to 2048 × 1024. EXR is unavailable. The colour assumption applies only when primaries are unspecified.",
"sketch_text.align_center": "Centre",
"ui.3d_mouse_kind_cap": "Return to Centre",
"ui.3d_mouse_looks_like_cap": "The reading stays put while you hold it, the way a Return to Centre device does.",
"ui.3d_mouse_step_pull": "Pull the cap towards you, hold it, then let go.",
"ui.3d_mouse_switch_cap": "Calibrate as Return to Centre",
"ui.center": "Centre",
"ui.center_arc_follows_cursor": "Centre point arc follows the cursor's direction",
"ui.center_arc_follows_cursor_tip": "A centre point arc runs clockwise or counter-clockwise the way the cursor goes round its centre. Off: always counter-clockwise from the start.",
"ui.centerline": "Centreline",
"ui.customizeToolbar": "Customise Toolbar…",
"ui.design_properties.license": "Licence",
"ui.design_properties.organization": "Organisation",
"ui.layout_compact": "Compact",
"ui.layout_floating": "Floating",
"ui.point_cloud_color_by": "Colour By",
"ui.point_cloud_file_colors": "File Colours",
"ui.point_cloud_no_file_colors": "The file has no colours",
"ui.point_cloud_single_color": "Single Colour",
"ui.ribbon_labels": "Show text under ribbon icons",
"ui.workspace_layout": "Workspace layout",
"ui.zoom_to_cursor_tip": "The wheel zooms towards the point under the cursor (off: towards the view's centre)",
+627 -4
View File
File diff suppressed because it is too large Load Diff
+783 -41
View File
File diff suppressed because it is too large Load Diff
+847 -1
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+565
View File
@@ -258,6 +258,8 @@
"Flanges": "Flange",
"Flat Pattern": "Sviluppo",
"Flat size": "Dimensioni dello sviluppo",
"Flat size X": "Dimensioni dello sviluppo X",
"Flat size Y": "Dimensioni dello sviluppo Y",
"Follow camera (Look At sketches)": "Segui la camera (Vista normale agli schizzi)",
"Follow the camera (Look At sketches)": "Segui la camera (Vista normale agli schizzi)",
"Font": "Carattere",
@@ -289,6 +291,7 @@
"Horiz./Vert.": "Oriz./Vert.",
"I-Beam": "Trave a I",
"IMAGES": "IMMAGINI",
"If you are offline or GitHub does not open, use Copy report and keep the text to submit later.": "Se sei offline o GitHub non si apre, usa Copia segnalazione e conserva il testo per inviarlo più tardi.",
"Import material into design": "Importa il materiale nel progetto",
"Import…": "Importa…",
"In This Design": "In questo progetto",
@@ -399,13 +402,16 @@
"Of": "Di",
"On your computer": "Sul tuo computer",
"Opacity": "Opacità",
"Open GitHub": "Apri GitHub",
"Open GitHub draft": "Apri bozza su GitHub",
"Open GitHub issue form": "Apri il modulo di segnalazione su GitHub",
"Open bodies (no volume)": "Corpi aperti (senza volume)",
"Open library...": "Apri libreria...",
"Open local libraries in the desktop app. You can export this design's library here.": "Apri le librerie locali nell’applicazione desktop. Qui puoi esportare la libreria di questo progetto.",
"Open surface — no volume": "Superficie aperta — senza volume",
"Open-source parametric 3D CAD in Rust. Licensed MIT OR Apache-2.0.": "CAD 3D parametrico open source in Rust. Licenza MIT OR Apache-2.0.",
"Opens your browser and copies the report text for you to paste into GitHub.": "Apre il browser e copia il testo della segnalazione, da incollare in GitHub.",
"Opens your browser and copies the report text. Review and submit your report on GitHub.": "Apre il browser e copia il testo della segnalazione. Controlla e invia la segnalazione su GitHub.",
"Opens your browser. Review and submit your report on GitHub.": "Apre il browser. Controlla e invia la segnalazione su GitHub.",
"Operator": "Operatore",
"Orbit (right drag)": "Orbita (trascina con il tasto destro)",
@@ -486,6 +492,7 @@
"Reopen the designs that were open when SolidCraft was last closed": "Riapri i progetti che erano aperti quando SolidCraft è stato chiuso l'ultima volta",
"Replace existing library file": "Sostituisci il file di libreria esistente",
"Report a bug — review a screenshot and open a GitHub draft": "Segnala un errore — controlla la schermata e apri una bozza su GitHub",
"Report copied. Keep this text to submit on GitHub when you are online.": "Segnalazione copiata. Conserva questo testo per inviarlo su GitHub quando sei online.",
"Report text copied. Paste it into GitHub and submit your report there.": "Testo della segnalazione copiato. Incollalo su GitHub e invia lì la segnalazione.",
"Reports are public. A GitHub account is required.": "Le segnalazioni sono pubbliche. Serve un account GitHub.",
"Reset Toolbar": "Reimposta barra degli strumenti",
@@ -547,6 +554,7 @@
"Sections (one sketch each)": "Sezioni (uno schizzo ciascuna)",
"Select Other": "Seleziona altro",
"Select Other: hold the left button still on the model (or right-click › Select Other…) to list everything under the cursor; click again on the same spot to select the next thing there. Double-click the middle button to go Home (Preferences › Navigation).": "Seleziona altro: tieni premuto il pulsante sinistro senza muovere il puntatore sul modello (o fai clic destro › Seleziona altro…) per elencare gli oggetti sotto il cursore; fai di nuovo clic nello stesso punto per selezionare l'oggetto successivo. Fai doppio clic con il pulsante centrale per tornare alla vista iniziale (Preferenze › Navigazione).",
"Select Same Look": "Seleziona stesso aspetto",
"Select bodies (a face picks its body)": "Seleziona corpi (una faccia seleziona il corpo a cui appartiene)",
"Select bodies or faces instead": "Seleziona invece corpi o facce",
"Select edges": "Seleziona spigoli",
@@ -581,6 +589,7 @@
"Slider": "Prismatico",
"Slot width": "Larghezza dell'asola",
"Snap to face and edge centres": "Aggancia ai centri di facce e spigoli",
"SolidCraft cannot submit reports directly. Submit on GitHub; no token is needed in the app.": "SolidCraft non può inviare direttamente le segnalazioni. Inviale su GitHub; nell'app non serve alcun token.",
"SolidCraft closed before these designs were saved. Their last autosave can be opened.": "SolidCraft si è chiuso prima del salvataggio di questi progetti. È possibile aprire il loro ultimo salvataggio automatico.",
"Spacing 2 must be a non-zero number": "La spaziatura 2 deve essere un numero diverso da zero",
"Spacing must be a non-zero number": "La spaziatura deve essere un numero diverso da zero",
@@ -757,6 +766,7 @@
"appearance.pbr_opaque": "PBR opaco",
"appearance.roughness": "Rugosità",
"appearance.surface_response": "Risposta della superficie",
"at the face": "sulla faccia",
"bom.group_children": "Sottoparti nella riga della loro parte",
"browser.body_name": "Corpo{number}",
"browser.calibrate_title": "Calibra: {name}",
@@ -765,6 +775,7 @@
"browser.capture_one": "Un componente è stato spostato, ma la sua posizione non è stata acquisita.",
"browser.component_name": "Componente{number}",
"browser.edit_canvas_title": "Modifica tela: {name}",
"browser.edit_point_cloud_title": "Modifica nuvola di punti: {name}",
"browser.move_title": "Sposta: {name}",
"browser.parameters": "Parametri ({count})",
"browser.precision": "Precisione: {precision}",
@@ -785,6 +796,7 @@
"click a plane or planar face": "fare clic su un piano o una faccia piana",
"click sketch curves": "fare clic sulle curve dello schizzo",
"cmd.appearance_assign": "Aspetto",
"cmd.appearance_chain": "Catena degli aspetti",
"cmd.appearance_library": "Libreria degli aspetti",
"cmd.appearance_list": "Elenca aspetti",
"cmd.appearance_paint": "Applica aspetto",
@@ -814,7 +826,9 @@
"cmd.component_create": "Nuovo componente",
"cmd.component_cycle_color": "Alterna colore del componente",
"cmd.component_delete": "Elimina componente",
"cmd.component_edit_in_place": "Modifica sul posto",
"cmd.component_extract": "Estrai in file",
"cmd.component_finish_edit": "Termina modifica",
"cmd.component_from_bodies": "Crea componenti da corpi",
"cmd.component_insert_design": "Inserisci progetto",
"cmd.component_links": "Elenca collegamenti",
@@ -989,14 +1003,57 @@
"cmd.plastic_rest": "Appoggio",
"cmd.plastic_rules": "Elenca regole per plastica",
"cmd.plastic_snap_fit": "Aggancio a scatto",
"cmd.pointcloud_delete": "Elimina nuvola di punti",
"cmd.pointcloud_edit": "Modifica nuvola di punti",
"cmd.pointcloud_insert": "Inserisci nuvola di punti",
"cmd.pointcloud_list": "Nuvole di punti",
"cmd.render_aging_describe": "Invecchiamento a strati delle superfici",
"cmd.render_backends": "Motori di rendering",
"cmd.render_batch": "Renderizza tutte le inquadrature",
"cmd.render_camera_fit": "Inquadra il soggetto del rendering",
"cmd.render_camera_get": "Esamina camera di rendering",
"cmd.render_cancel": "Annulla rendering",
"cmd.render_compare": "Confronta immagini",
"cmd.render_effects_describe": "Obiettivo ed effetti creativi",
"cmd.render_export": "Esporta immagine renderizzata",
"cmd.render_hdr_inspect": "Esamina sorgente HDR",
"cmd.render_library_appearance_apply": "Applica aspetto opaco della libreria",
"cmd.render_library_describe": "Esamina risorsa della libreria di rendering",
"cmd.render_library_environment_apply": "Applica ambiente HDR integrato",
"cmd.render_library_list": "Sfoglia libreria di rendering",
"cmd.render_library_physical_prepare": "Prepara riferimento fisico",
"cmd.render_library_preview": "Esamina mappa originale della superficie",
"cmd.render_library_studio_apply": "Applica luci dello studio predisposte",
"cmd.render_library_studio_prepare": "Prepara luci dello studio predisposte",
"cmd.render_library_surface_bind": "Salva associazione della superficie",
"cmd.render_library_surface_prepare": "Prepara mappe di superficie predisposte",
"cmd.render_library_surface_unbind": "Rimuovi associazione della superficie",
"cmd.render_library_targets": "Trova destinazioni della libreria di rendering",
"cmd.render_lights_add": "Aggiungi luce",
"cmd.render_lights_solo": "Isola luce",
"cmd.render_optics_bind": "Salva associazione ottica",
"cmd.render_optics_unbind": "Rimuovi associazione ottica",
"cmd.render_output_size": "Imposta dimensioni di uscita del rendering",
"cmd.render_preflight": "Verifica richiesta di rendering",
"cmd.render_preset_apply": "Applica studio nativo",
"cmd.render_preset_resolve": "Verifica studio nativo",
"cmd.render_quality_prepare": "Verifica budget di campionamento fisso",
"cmd.render_result_close": "Chiudi immagine renderizzata",
"cmd.render_result_copy": "Copia immagine renderizzata",
"cmd.render_result_pin": "Conserva risultato di rendering mostrato",
"cmd.render_result_regrade": "Correggi il colore del master lineare",
"cmd.render_result_view": "Visualizza immagine renderizzata",
"cmd.render_scene": "Esamina scena di rendering",
"cmd.render_settings_apply": "Applica camera di rendering",
"cmd.render_settings_capture_hdr": "Salva impostazioni di rendering con HDR",
"cmd.render_settings_get": "Impostazioni di rendering",
"cmd.render_settings_set": "Salva impostazioni di rendering",
"cmd.render_shot_duplicate": "Duplica inquadratura di rendering",
"cmd.render_shot_remove": "Rimuovi inquadratura di rendering",
"cmd.render_shot_rename": "Rinomina inquadratura di rendering",
"cmd.render_stage_backdrop": "Salva sfondo fisico del rendering",
"cmd.render_stage_clear": "Rimuovi scenografia di rendering",
"cmd.render_stage_ground": "Salva piano d'appoggio del rendering",
"cmd.render_start": "Renderizza immagine",
"cmd.render_status": "Avanzamento del rendering",
"cmd.select_clear": "Deseleziona tutto",
@@ -1088,6 +1145,7 @@
"cmd.sketch_spline_control_point_5": "Spline per punti di controllo (grado 5)",
"cmd.sketch_spline_fit_point": "Spline interpolante",
"cmd.sketch_spline_insert_point": "Aggiungi punto alla spline",
"cmd.sketch_spline_reverse": "Inverti direzione della spline",
"cmd.sketch_spun_profile": "Profilo di tornitura",
"cmd.sketch_toggle_diameter": "Alterna raggio / diametro",
"cmd.sketch_toggle_driven": "Attiva/Disattiva quota di riferimento",
@@ -1129,13 +1187,19 @@
"cmd.timeline_export_script": "Esporta script dei comandi",
"cmd.timeline_inspect": "Esamina lavorazione",
"cmd.timeline_paste": "Incolla lavorazioni",
"cmd.timeline_play": "Riproduci cronologia",
"cmd.timeline_redefine": "Modifica lavorazione",
"cmd.timeline_rename": "Rinomina",
"cmd.timeline_reorder": "Riordina lavorazione",
"cmd.timeline_roll_to": "Sposta marcatore della cronologia",
"cmd.timeline_rollback": "Sposta marcatore della sequenza temporale",
"cmd.timeline_stop": "Arresta riproduzione cronologia",
"cmd.timeline_suppress": "Sospendi lavorazione",
"cmd.view.render_browser": "Struttura del rendering",
"cmd.view.render_dock": "Sposta pannello di rendering",
"cmd.view.render_focus": "Vista focalizzata sul rendering",
"cmd.view_ambient_occlusion": "Occlusione ambientale",
"cmd.view_angle_readout": "Angoli della vista",
"cmd.view_apply": "Ripristina vista con nome",
"cmd.view_back": "Vista posteriore",
"cmd.view_bottom": "Vista dal basso",
@@ -1151,7 +1215,9 @@
"cmd.view_list": "Elenca viste con nome",
"cmd.view_navigate": "Naviga nella vista",
"cmd.view_navigation_bar": "Barra di navigazione",
"cmd.view_next_tab": "Scheda successiva",
"cmd.view_normal_to": "Normale alla selezione",
"cmd.view_previous_tab": "Scheda precedente",
"cmd.view_rename": "Rinomina vista con nome",
"cmd.view_right": "Vista destra",
"cmd.view_save": "Nuova vista con nome",
@@ -1270,6 +1336,7 @@
"help.appearance.assign": "Dà ai corpi, alle facce o ai componenti selezionati un colore o un aspetto di materiale, senza cambiarne il peso. Usalo per distinguere le parti o per vedere in anteprima una finitura.",
"help.attributions": "Attribuzioni (ATTRIBUTION.md)",
"help.build": "Versione {version} · commit {commit} · compilata il {date}",
"help.component.finish_edit": "Salva la parte che stai modificando sul posto, torna al suo assieme e lo aggiorna con le modifiche. Usalo quando hai finito di modificare la parte collegata.",
"help.connect_note": "Riavvia ogni assistente per caricare il server SolidCraft. Ogni file è stato salvato come .bak prima della modifica.",
"help.connect_title": "Collega assistenti AI",
"help.face.delete": "Rimuove le facce selezionate e lascia che le facce vicine chiudano il vuoto, oppure lascia il vuoto aperto come superficie. Usalo per togliere uno spigolo arrotondato, un foro o una sporgenza che è d'intralcio.",
@@ -1280,6 +1347,7 @@
"help.mit": "Licenza MIT",
"help.notice": "NOTICE",
"help.parameters.change": "Apre la tabella dei valori con nome e delle espressioni che guidano le quote della progettazione. Usala per cambiare una misura in un solo punto e far seguire tutte le lavorazioni che la usano.",
"help.pointcloud.insert": "Inserisci una scansione PLY, XYZ o PTS come nuvola di punti accanto al modello. Usala come riferimento quando costruisci un modello a partire da dati misurati.",
"help.solid.align": "Sposta i corpi selezionati in modo che un punto, una faccia o un piano su di essi coincida con un punto, una faccia o un piano altrove. Usalo per posizionare un pezzo contro un altro senza misurare lo scostamento.",
"help.solid.chamfer": "Taglia gli spigoli selezionati con uno smusso piano della distanza impostata. Usalo per eliminare gli spigoli vivi o per facilitare l'ingresso di un perno o di una vite.",
"help.solid.combine": "Unisce i corpi, li sottrae da un corpo di destinazione oppure tiene solo il volume che hanno in comune, e può conservare i corpi utensile. Usalo per fondere parti, per tagliare una forma con un'altra o per trovare dove due corpi si sovrappongono.",
@@ -1305,6 +1373,7 @@
"help.third_party": "Licenze di terze parti",
"help.timeline.compute_all": "Ricostruisce ogni lavorazione della cronologia dall'inizio. Usalo per aggiornare il modello e vedere quali lavorazioni falliscono.",
"help.timeline.delete": "Elimina le lavorazioni selezionate dalla cronologia; eliminando uno schizzo si eliminano anche le lavorazioni costruite su di esso. Usalo per togliere un passaggio che non serve più.",
"help.timeline.play": "Riproduce le lavorazioni rimanenti una alla volta, con una pausa di mezzo secondo dopo ogni ricostruzione. Esegui di nuovo questo comando o premi Escape per arrestare; Vai alla fine salta subito alla fine.",
"hole_presets.confirm_delete": "Conferma eliminazione",
"hole_presets.delete": "Elimina",
"hole_presets.delete_prompt": "Eliminare questo preset personale? I fori esistenti restano invariati.",
@@ -1408,6 +1477,8 @@
"keymap.command_id": "ID comando",
"keymap.empty": "Nessun comando corrispondente",
"keymap.use_anyway": "Usa comunque {key} qui",
"label.move_to_left_side": "Sposta sul lato sinistro",
"label.move_to_right_side": "Sposta sul lato destro",
"manage.appearance_hint": "Scegli un aspetto per la selezione o trascina un campione su un corpo o una faccia.",
"manage.assign_hint": "Seleziona i corpi e scegli la loro regola di progettazione per parti in plastica.",
"manage.config_hint": "Modifica righe, colonne e regole di configurazione, poi attiva una riga o visualizzane l’anteprima.",
@@ -1492,7 +1563,9 @@
"nav.free_orbit_upright.help": "Il trascinamento laterale del mouse fa girare il modello attorno all'asse verticale del mondo; il trascinamento in alto e in basso lo inclina oltre la sommità senza limiti.",
"nav.free_orbit_upright.label": "Ruota attorno all'asse verticale",
"nav.fusion.help": "Il trascinamento centrale fa la panoramica, Shift+centrale orbita, il trascinamento destro orbita",
"nav.hfss.help": "Alt+trascinamento con il pulsante sinistro esegue la panoramica, Shift+Alt+pulsante sinistro lo zoom, Ctrl+trascinamento con il pulsante sinistro su uno spazio vuoto orbita",
"nav.inventor.help": "Il trascinamento centrale fa la panoramica, Shift+centrale orbita, Ctrl+centrale fa lo zoom, il trascinamento destro orbita",
"nav.maya.help": "Alt+trascinamento con il pulsante sinistro orbita, Alt+pulsante centrale esegue la panoramica, Alt+pulsante destro lo zoom; anche il trascinamento con il pulsante centrale esegue la panoramica",
"nav.openscad.help": "Il trascinamento sinistro nello spazio vuoto orbita, Shift+trascinamento sinistro seleziona con un riquadro, il trascinamento sulla geometria dello schizzo la modifica; il trascinamento destro o centrale fa la panoramica, Shift+destro o Shift+centrale fa lo zoom",
"nav.perspective.sketch": "La modifica dello schizzo usa la vista ortogonale. Termina lo schizzo per passare alla prospettiva.",
"nav.solidworks.help": "Trascina con il tasto centrale per orbitare, Ctrl+centrale per la panoramica, Shift+centrale per lo zoom, trascina con il destro per orbitare",
@@ -1503,6 +1576,93 @@
"nav.touchpad.pan": "Panoramica (tieni premuto Shift e muovi il puntatore; senza pulsanti del mouse)",
"nav.touchpad.scroll": "Il touchpad usa lo scorrimento verticale per lo zoom. L'impostazione di panoramica a due dita viene conservata per le altre preimpostazioni.",
"nav.touchpad.zoom": "Zoom (scorrimento verticale o gesto di pizzicamento)",
"navbar.agent_chat": "Pannello chat dell'assistente",
"navbar.agent_cursor": "Mostra cursore dell'agente",
"navbar.ambient_occlusion": "Occlusione ambientale",
"navbar.assistant": "Assistente",
"navbar.custom.add_slot": "Aggiungi {slot}",
"navbar.custom.always": "Sempre visibile",
"navbar.custom.available": "{available} · trascina sulla barra o premi Aggiungi",
"navbar.custom.buttons": "Pulsanti",
"navbar.custom.compact": "Compatta",
"navbar.custom.count": "{count} di 16 elementi",
"navbar.custom.customise": "Personalizza barra di navigazione…",
"navbar.custom.design": "Progettazione",
"navbar.custom.duplicate": "Questo elemento è già sulla barra.",
"navbar.custom.fade": "Attenua",
"navbar.custom.full": "Rimuovi un elemento per aggiungerne un altro.",
"navbar.custom.hidden_design": "Nascosto in Progettazione",
"navbar.custom.hidden_render": "Nascosto in Rendering",
"navbar.custom.hide": "Nascondi barra di navigazione",
"navbar.custom.hide_idle": "Nascondi finché non ci passi sopra",
"navbar.custom.icon_only": "Solo icona",
"navbar.custom.icon_value": "Icona e valore",
"navbar.custom.icons": "Icone",
"navbar.custom.idle": "Quando inattiva",
"navbar.custom.intro": "Scegli i comandi della barra nella parte inferiore della vista 3D e il loro ordine. Trascina un elemento per spostarlo, oppure trascinalo fuori dalla barra per rimuoverlo.",
"navbar.custom.labels": "Icone ed etichette",
"navbar.custom.left": "Sposta a sinistra",
"navbar.custom.position": "Posizione",
"navbar.custom.position_centre": "Centro",
"navbar.custom.position_left": "Sinistra",
"navbar.custom.position_right": "Destra",
"navbar.custom.preview_as": "Anteprima come",
"navbar.custom.regular": "Normale",
"navbar.custom.remove": "Rimuovi",
"navbar.custom.remove_bar": "Rimuovi dalla barra",
"navbar.custom.render": "Rendering",
"navbar.custom.reset": "Reimposta barra di navigazione",
"navbar.custom.reset_default": "Reimposta ai valori predefiniti",
"navbar.custom.right": "Sposta a destra",
"navbar.custom.select": "Nessun elemento selezionato. Seleziona un elemento sulla barra per spostarlo, rimuoverlo o cambiarne l'aspetto.",
"navbar.custom.separators_full": "La barra ha già quattro separatori.",
"navbar.custom.show": "Mostra barra di navigazione",
"navbar.custom.shows": "Mostra",
"navbar.custom.size": "Dimensioni",
"navbar.custom.stale": "La barra è cambiata. Seleziona di nuovo l'elemento.",
"navbar.custom.title": "Barra di navigazione",
"navbar.custom.unknown": "Questo elemento non è disponibile.",
"navbar.description.ambient_occlusion": "Scurisce incavi e angoli per dare profondità.",
"navbar.description.display": "Raccoglie le impostazioni della vista: preimpostazione grafica, griglia, ombra sul piano di appoggio, occlusione ambientale e proiezione.",
"navbar.description.fit": "Inquadra la selezione o l'intero modello se non è selezionato nulla.",
"navbar.description.grid": "Mostra o nasconde la griglia di base.",
"navbar.description.ground_shadow": "Mostra o nasconde l'ombra sotto il modello.",
"navbar.description.home": "Torna alla vista isometrica dell'intero modello.",
"navbar.description.look_at": "Orienta la vista verso la faccia, il piano o lo schizzo aperto selezionato.",
"navbar.description.orbit": "Ruota la vista attorno al modello.",
"navbar.description.pan": "Sposta la vista lateralmente, in alto o in basso.",
"navbar.description.projection": "Passa dalla vista ortografica a quella prospettica.",
"navbar.description.separator": "Una linea sottile che raggruppa gli elementi vicini.",
"navbar.description.spin": "Mantiene la vista in rotazione finché non fai clic o premi un tasto.",
"navbar.description.visual_style": "Cambia il modo in cui è disegnato il modello: ombreggiato, reticolo o con spigoli nascosti.",
"navbar.description.zoom": "Avvicina o allontana la vista dal modello.",
"navbar.display": "Visualizzazione",
"navbar.fit": "Adatta",
"navbar.graphics": "Grafica",
"navbar.grid": "Griglia",
"navbar.ground_shadow": "Ombra sul piano di appoggio",
"navbar.home": "Inizio",
"navbar.later": "Più tardi",
"navbar.look_at": "Vista normale",
"navbar.more": "Altro",
"navbar.orbit": "Orbita",
"navbar.orthographic": "Ortografica",
"navbar.pan": "Panoramica",
"navbar.perspective": "Prospettica",
"navbar.preset": "Preimpostazione",
"navbar.projection": "Proiezione",
"navbar.projection_heading": "Proiezione",
"navbar.separator": "Separatore",
"navbar.show": "Mostra",
"navbar.spin": "Rotazione continua",
"navbar.style.shaded": "Ombreggiato",
"navbar.style.shaded_with_edges": "Ombreggiato con spigoli",
"navbar.style.shaded_with_hidden_edges": "Ombreggiato con spigoli nascosti",
"navbar.style.wireframe": "Reticolo",
"navbar.translucent": "Traslucido",
"navbar.value_tip": "{name} · {value}",
"navbar.visual_style": "Stile visualizzazione",
"navbar.zoom": "Zoom",
"needs two joints": "richiede due giunti",
"network.allow_once": "Consenti una volta",
"network.always_allow": "Consenti sempre questo server",
@@ -1588,6 +1748,8 @@
"prefs.bodies_folders_never": "Mai",
"prefs.bodies_folders_several": "Solo con più corpi",
"prefs.bottom": "In basso",
"prefs.bottom_centre": "In basso al centro",
"prefs.bottom_right": "In basso a destra",
"prefs.browser": "Struttura",
"prefs.built_in": "Integrato",
"prefs.button_left": "Trascinamento sinistro",
@@ -1639,6 +1801,8 @@
"prefs.history": "Cronologia",
"prefs.history_origin_bodies": "Mostra origine e corpi in alto",
"prefs.history_origin_bodies_note": "La Cronologia a sinistra o sotto la Struttura inizia con la cartella Corpi del componente attivo e con l'Origine, con occhi e menu come nella Struttura. La Cronologia in basso non cambia.",
"prefs.history_play_button": "Pulsante Riproduci cronologia nei controlli della cronologia",
"prefs.history_play_button_note": "Inserisce Riproduci cronologia tra Indietro di un passaggio e Avanti di un passaggio nei controlli della cronologia. Puoi anche fare clic con il pulsante destro sui controlli per mostrarlo o nasconderlo.",
"prefs.history_sketches": "Schizzi",
"prefs.history_sketches_in_order": "In ordine",
"prefs.history_sketches_note": "Con Schizzi impostato su Sotto la lavorazione, la Cronologia a sinistra elenca ogni schizzo rientrato di un livello, sotto la prima lavorazione creata a partire da esso, quando è abbastanza larga da mostrare i nomi. La cronologia in basso mantiene sempre l'ordine di creazione.",
@@ -1646,6 +1810,7 @@
"prefs.hold_stop_snapping": "Tieni premuto per disattivare l'aggancio",
"prefs.icons_only": "Solo icone",
"prefs.imported_file": "File importato",
"prefs.in_browser": "Nella Struttura",
"prefs.input": "Input",
"prefs.interface": "Interfaccia",
"prefs.interface_language": "Lingua dell'interfaccia",
@@ -1656,8 +1821,19 @@
"prefs.layout_note": "Compatta: pannelli ancorati ai bordi della finestra. La trasparenza della Struttura è disponibile in Flottante. Cambia il lato dell'Assistente nella pagina Assistente.",
"prefs.left": "Sinistra",
"prefs.left_click": "Clic sinistro",
"prefs.linked_designs": "Progetti collegati",
"prefs.live_input": "Input in tempo reale",
"prefs.live_preview": "Anteprima dal vivo",
"prefs.logo": "Logo",
"prefs.logo_accent": "Accento",
"prefs.logo_theme": "Colori del tema",
"prefs.max_file_size": "Dimensione massima dei file da aprire",
"prefs.max_file_size_design": "File di progettazione",
"prefs.max_file_size_flag": "Questo avvio usa --max-file-size {size}, valido fino alla chiusura di SolidCraft. Queste impostazioni si applicano all’avvio senza tale opzione.",
"prefs.max_file_size_note": "Valori predefiniti: 512 MB e 256 MB; massimo 16 GB. Aprire un file richiede memoria pari a più volte la sua dimensione. Un progetto che conserva un’importazione grande può richiedere un limite maggiore per essere salvato e riaperto.",
"prefs.max_file_size_step": "File STEP e di importazione",
"prefs.max_file_size_web": "L’app web apre file STEP e di importazione fino a 512 MB e progetti fino a 256 MB: una scheda del browser non può contenere file più grandi. L’app desktop permette di aumentare questi limiti.",
"prefs.megabytes": "MB",
"prefs.minutes": "minuti",
"prefs.minutes_suffix": " min",
"prefs.mouse": "Mouse e trackpad",
@@ -1698,6 +1874,8 @@
"prefs.shift_add_ctrl_toggle": "Shift solo aggiunge; Ctrl / Cmd alterna",
"prefs.shift_add_note": "Attivo: Shift aggiunge, Ctrl / Cmd alterna. Disattivo (predefinito): entrambi alternano.",
"prefs.shortcuts": "Scorciatoie",
"prefs.sketch_conflict_colour": "Geometria in conflitto nel colore di conflitto",
"prefs.sketch_conflict_colour_note": "Quando i vincoli di uno schizzo sono in conflitto, anche le curve e i punti interessati da un vincolo in errore vengono disegnati con il colore di conflitto, non solo il suo simbolo o la sua quota. Disattivato: mantengono i colori abituali.",
"prefs.sketch_exit_view": "Al termine di uno schizzo",
"prefs.sketch_exit_view.keep": "Mantieni la vista attuale",
"prefs.sketch_exit_view.previous": "Torna alla vista precedente",
@@ -1706,11 +1884,17 @@
"prefs.sketch_selection": "Schizzo e selezione",
"prefs.sketch_selection_heading": "Schizzo e selezione",
"prefs.sketch_selection_note": "Come si agganciano gli schizzi e come selezionano i clic.",
"prefs.sketch_tab_always": "Mantieni visibile la scheda Schizzo",
"prefs.sketch_tab_always_note": "La scheda Schizzo resta nella barra multifunzione, subito dopo Modella, finché nessuno schizzo è aperto. I suoi strumenti di disegno avviano allora uno schizzo sul piano o sulla faccia selezionati, oppure sul piano che selezioni subito dopo, con lo strumento già attivo.",
"prefs.sketch_tracking_guides": "Guide di allineamento di centro e punto medio",
"prefs.sketch_tracking_guides_note": "Passa il puntatore sul centro di un cerchio o sul punto medio di un segmento, poi spostati in orizzontale o in verticale per mostrare una guida punteggiata temporanea.",
"prefs.sketching": "Schizzi",
"prefs.snap_drawing_note": "Mentre disegni o trascini un punto dello schizzo.",
"prefs.source": "Fonte",
"prefs.speed": "Velocità",
"prefs.stand_up_note": "Dopo l'apertura di un file STEP o IGES con Z verso l'alto, proponi un quarto di giro attorno a X.",
"prefs.status_bar": "Barra di stato",
"prefs.status_bar_note": "Una barra sottile lungo il bordo inferiore della finestra mostra cosa si sta modificando, lo stato dello schizzo aperto nel suo colore e le unità del progetto; un clic sulle unità le cambia. Lo stato dello schizzo non compare più nell'angolo della vista.",
"prefs.status_done": "Fatto",
"prefs.status_error": "Errore",
"prefs.status_selected": "Selezionato",
@@ -1718,15 +1902,20 @@
"prefs.supersampling_brief": "Disegna la vista più grande e poi la riduce con un filtro: molto nitida, ma più pesante.",
"prefs.tab_accent_note": "L'accento segue la scheda attiva",
"prefs.theme_file": "file del tema",
"prefs.theme_file_or_paste": "file o incolla",
"prefs.theme_follow": "Segui un file di tema",
"prefs.theme_follow_error": "Non applicato: {error}. Resta attivo l’ultimo tema valido.",
"prefs.theme_follow_launch": "Seguito solo per questa sessione (--theme-file); ricaricato quando un altro strumento riscrive il file.",
"prefs.theme_follow_note": "Ricaricato quando un altro strumento riscrive il file. Scegliere un tema interrompe il monitoraggio.",
"prefs.theme_follow_off": "Disattivato",
"prefs.theme_follow_stop": "Smetti di seguire",
"prefs.theme_import_hint": "Fai clic per scegliere un file di tema, trascinane uno qui oppure premi Ctrl+V (Cmd+V su Mac) con un tema copiato",
"prefs.theme_paste": "Incolla tema",
"prefs.theme_paste_none": "Negli appunti non c'è nessun tema SolidCraft",
"prefs.timeline_half_hour": "−30 min",
"prefs.timeline_now": "ora",
"prefs.timeline_quarter_hour": "−15",
"prefs.toast_place": "Avvisi",
"prefs.toggle_item": "Aggiungi l'elemento o toglilo di nuovo",
"prefs.toolbar": "Barra degli strumenti",
"prefs.top": "In alto",
@@ -1789,7 +1978,47 @@
"render.aging_upward": "Deposito sulle superfici rivolte verso l'alto",
"render.all_controls_help": "Ispezione compatta di tutti i controlli attuali. Le pagine delle sezioni consentono una modifica mirata senza cambiare la richiesta sottostante.",
"render.all_shots_label": "Tutte le inquadrature",
"render.appearance_editor.absorption": "Assorbimento",
"render.appearance_editor.base_colour": "Colore di base",
"render.appearance_editor.body_reason": "Le associazioni ottiche riguardano un intero corpo. Seleziona Corpo per modificare questi controlli.",
"render.appearance_editor.boundary": "Contorno",
"render.appearance_editor.box": "Parallelepipedo",
"render.appearance_editor.choose_image": "Scegli immagine…",
"render.appearance_editor.closed": "Solido chiuso",
"render.appearance_editor.coat": "Vernice trasparente",
"render.appearance_editor.cpu_reason": "Richiede il ray tracing su CPU.",
"render.appearance_editor.glass": "Vetro e assorbimento",
"render.appearance_editor.glass_enable": "Usa vetro fisico su questo corpo",
"render.appearance_editor.glass_note": "Il vetro chiuso usa la distanza geometrica. Non può coesistere sullo stesso corpo con vernice trasparente o mappe.",
"render.appearance_editor.gpu_reason": "Richiede il path tracing su GPU.",
"render.appearance_editor.ior": "IOR",
"render.appearance_editor.maps": "Mappe",
"render.appearance_editor.normal": "Normale",
"render.appearance_editor.normal_strength": "Intensità della normale",
"render.appearance_editor.origin": "Origine",
"render.appearance_editor.recipe": "Ricetta",
"render.appearance_editor.reflection_sampling": "Campionamento per tutti i corpi riflettenti",
"render.appearance_editor.reflections": "Riflessi",
"render.appearance_editor.remove": "Rimuovi proprietà salvate",
"render.appearance_editor.remove_note": "Rimuove le proprietà ottiche salvate da questa inquadratura. La geometria e gli aspetti assegnati vengono mantenuti.",
"render.appearance_editor.remove_title": "Rimuovere le proprietà ottiche salvate?",
"render.appearance_editor.replace": "Sostituisci le proprietà ottiche salvate di questo corpo",
"render.appearance_editor.revalidate": "Riconvalida questo corpo",
"render.appearance_editor.save": "Salva queste proprietà ottiche",
"render.appearance_editor.save_reason": "Per salvare queste proprietà ottiche serve vetro fisico su un corpo GPU corrente. La vernice trasparente e le mappe immagine locali restano temporanee.",
"render.appearance_editor.saved": "Salvato con questa inquadratura",
"render.appearance_editor.saved_state": "Queste proprietà ottiche sono salvate con questa inquadratura.",
"render.appearance_editor.scatter_reason": "La diffusione interna richiede un contorno solido chiuso.",
"render.appearance_editor.temporary": "Queste proprietà ottiche sono temporanee in questa scheda. Salvale per conservarle con l'inquadratura.",
"render.appearance_editor.thickness": "Spessore",
"render.appearance_editor.thickness_reason": "Lo spessore si applica ai fogli sottili; il vetro chiuso usa la distanza geometrica.",
"render.appearance_editor.thin": "Foglio sottile",
"render.appearance_editor.u_repeat": "Ripetizione U",
"render.appearance_editor.v_repeat": "Ripetizione V",
"render.appearance_editor.v_up": "La V della texture punta verso l'alto",
"render.appearance_editor.weight": "Peso",
"render.appearance_physics_separate": "L'aspetto visivo non assegna densità, dati termici o altre proprietà ingegneristiche.",
"render.appearances": "Aspetti",
"render.availability_native": "Composizione nativa; verifica prima di applicare",
"render.availability_projection": "Proiezione supportata; vedi ambito e omissioni",
"render.availability_reference": "Dati di riferimento; non è un'assegnazione automatica",
@@ -1844,6 +2073,13 @@
"render.camera_set": "Imposta camera di rendering",
"render.camera_target": "Posizione del punto di mira · mm",
"render.camera_yaw": "Imbardata",
"render.category_metal": "Metallo",
"render.category_paint": "Vernice",
"render.category_plastic": "Plastica",
"render.category_wood": "Legno",
"render.check_opaque": "Trasparenza: solo superfici opache; l'alfa dello sfondo è supportato.",
"render.check_sorted_alpha": "Trasparenza: approssimazione alfa ordinata.",
"render.check_transmission": "Trasparenza: trasmissione fisica.",
"render.chromatic_offset": "Scostamento cromatico dei bordi",
"render.clear_stage": "Rimuovi la scenografia salvata",
"render.copy_request": "Copia JSON",
@@ -1943,6 +2179,87 @@
"render.effects_reset_lens": "Reimposta effetti obiettivo",
"render.effects_seed": "Seme del motivo",
"render.emitted_axis": "Asse di emissione",
"render.env_advanced": "Avanzate",
"render.env_backdrop": "Sfondo",
"render.env_backdrop_pending": "La visibilità dell'ambiente e la sfocatura dello sfondo non sono ancora supportate dal motore di rendering.",
"render.env_blur": "Sfocatura",
"render.env_change": "Cambia",
"render.env_choose_source": "Scegli un ambiente in Studi e ambienti prima di modificare l'illuminazione.",
"render.env_clear": "Cancella",
"render.env_colour": "Colore",
"render.env_environments": "Ambienti",
"render.env_ground": "Piano d'appoggio",
"render.env_ground_pending": "Il piano d'appoggio fisico riceve le ombre come superficie diffusa finita. La ricezione delle sole ombre e i riflessi del piano non sono ancora supportati.",
"render.env_intensity": "Intensità",
"render.env_invalid_edit": "Modifica dell'ambiente non valida.",
"render.env_physical_ground": "Piano d'appoggio fisico",
"render.env_preview_help": "Esempio illustrativo con una sfera; non è un'anteprima dell'ambiente selezionato.",
"render.env_reflection": "Riflesso",
"render.env_ring_help": "Trascina l'anello per ruotare l'illuminazione. Tieni premuto Shift per agganciare a 15°.",
"render.env_rotate": "Ruota",
"render.env_set": "Imposta ambiente di rendering",
"render.env_shadow_catcher": "Ricevitore di ombre",
"render.env_show_environment": "Mostra ambiente",
"render.env_source": "Fonte",
"render.env_stage_details": "Le modifiche al piano d'appoggio richiedono il ray tracing e un solo pannello di appoggio. Usa Scena per modificare gli altri pannelli del set fotografico.",
"render.env_studios": "Studi",
"render.environment.albedo": "Albedo",
"render.environment.atmosphere": "Atmosfera",
"render.environment.backdrop_note": "Uno sfondo è visibile solo alla camera. Non illumina, non proietta ombre né riflette ed è rifiutato con l'uscita trasparente.",
"render.environment.blur_pending": "La sfocatura non è disponibile: il motore di rendering non ha un'impostazione di sfocatura dello sfondo.",
"render.environment.builtin": "HDR integrato",
"render.environment.check": "Verifica file",
"render.environment.checked": "File HDR verificato. Il salvataggio incorpora questi byte.",
"render.environment.choose": "Scegli HDR…",
"render.environment.constant": "Costante",
"render.environment.cyclorama": "Ciclorama",
"render.environment.embedded": "Salvato in questo progetto",
"render.environment.end": "Fine",
"render.environment.extinction": "Estinzione",
"render.environment.file": "File",
"render.environment.fit": "Adatta e salva il piano d'appoggio",
"render.environment.floor_wall": "Pavimento e parete",
"render.environment.gap": "Distanza libera",
"render.environment.gradient": "Sfumatura",
"render.environment.gradient_gpu": "Lo sfondo sfumato richiede il path tracing su GPU.",
"render.environment.ground": "Piano d'appoggio e set fotografico",
"render.environment.hdr": "HDR",
"render.environment.hdr_file": "File HDR",
"render.environment.horizon": "Orizzonte",
"render.environment.horizontal": "Orizzontale",
"render.environment.keep": "Mantieni",
"render.environment.lighting_samples": "Campioni di illuminazione",
"render.environment.margin": "Margine di estensione",
"render.environment.max": "Limiti massimi",
"render.environment.medium": "Mezzo partecipante",
"render.environment.min": "Limiti minimi",
"render.environment.mode": "Modalità",
"render.environment.needs_gpu": "Richiede il path tracing su GPU.",
"render.environment.none": "Nessuno",
"render.environment.orientation": "Orientamento e intensità",
"render.environment.phase": "Fase",
"render.environment.primaries": "Tratta i primari non specificati come sRGB lineare",
"render.environment.primaries_gpu": "L'interpretazione dei primari non specificati richiede il path tracing su GPU.",
"render.environment.radial": "Radiale",
"render.environment.radial_only": "Centro e raggio si applicano alla modalità Radiale.",
"render.environment.reflectance": "Riflettanza",
"render.environment.remove": "Rimuovi set fotografico",
"render.environment.remove_confirm": "Rimuovere il set fotografico salvato?",
"render.environment.remove_note": "Rimuove i {count} pannelli passivi da questa inquadratura. Lo sfondo della camera resta.",
"render.environment.replace": "Conferma la sostituzione del set fotografico esistente",
"render.environment.rotation_hdr": "La rotazione richiede una sorgente HDR per il ray tracing su CPU.",
"render.environment.samples_cpu": "I campioni di illuminazione sono definiti dal budget del path tracing su GPU; questa impostazione richiede il ray tracing su CPU.",
"render.environment.saved_panels": "Pannelli salvati {count}",
"render.environment.sky_ground": "Suolo",
"render.environment.sky_note": "Gradiente di cielo originale per l'illuminazione; non è un'atmosfera calibrata.",
"render.environment.source_raytrace": "Le sorgenti dell'ambiente richiedono il ray tracing su CPU o GPU.",
"render.environment.stage_raytrace": "I set fotografici fisici richiedono il ray tracing su CPU o GPU.",
"render.environment.start": "Inizio",
"render.environment.vertical": "Verticale",
"render.environment.world": "Mondo",
"render.environment.world_pending": "Lo sfondo Mondo non è disponibile: la visibilità dell'ambiente per la camera non ha ancora un'impostazione salvata.",
"render.environment.zenith": "Zenit",
"render.environment_tiles_require_raytrace": "Gli ambienti richiedono il ray tracing su CPU o GPU. Selezionalo nell'editor Uscita.",
"render.error_area_samples": "area_samples deve essere 1, 4, 16 o 64",
"render.error_binding_allocation": "impossibile riservare l'associazione del materiale",
"render.error_body_bound": "l'anteprima del prodotto supera il limite dei corpi acquisiti",
@@ -2014,6 +2331,8 @@
"render.flare_strength": "Intensità del flare sulle alte luci",
"render.flare_threshold": "Soglia del flare lineare della scena",
"render.fold_browser": "Comprimi struttura",
"render.frame_presets": "Preimpostazioni del fotogramma",
"render.frame_presets_pending": "In arrivo con l'editor delle inquadrature",
"render.gpu_depth": "Profondità massima del percorso",
"render.gpu_options_help": "Campioni, profondità, seed ed esposizione vengono salvati con questa impostazione. Viene salvato solo il metodo di generazione attivo.",
"render.gpu_path_failed": "Path tracer GPU non disponibile",
@@ -2074,6 +2393,36 @@
"render.inner_half_angle": "Semiangolo interno",
"render.inspect_scene": "Aggiorna il riepilogo della scena acquisita",
"render.inspector": "Ispettore",
"render.inspector_advanced": "Avanzate",
"render.inspector_all_users": "Tutti i {count} corpi",
"render.inspector_applies_to": "Si applica a",
"render.inspector_both_users": "Entrambi i corpi",
"render.inspector_chain": "Da dove deriva questo aspetto",
"render.inspector_colour": "Colore",
"render.inspector_edit": "Modifica",
"render.inspector_finish": "Finitura",
"render.inspector_from_material": "Dal materiale",
"render.inspector_gloss": "Lucido",
"render.inspector_material": "Materiale",
"render.inspector_matte": "Opaco",
"render.inspector_metal": "Metallo",
"render.inspector_opacity": "Opacità",
"render.inspector_opaque_help": "I campi di finitura e ottici usano PBR opaco (opacità 1). Un'opacità inferiore usa l'ombreggiatura scalare.",
"render.inspector_pick_target": "Seleziona un oggetto di questo tipo per esaminarne l'aspetto.",
"render.inspector_remove": "Rimuovi sostituzione",
"render.inspector_replace": "Sostituisci…",
"render.inspector_reset": "Reimposta",
"render.inspector_satin": "Satinato",
"render.inspector_save_library": "Salva nella libreria…",
"render.inspector_set_all": "Aspetti misti. La modifica imposta l'aspetto di tutti gli oggetti selezionati.",
"render.inspector_soon": "Prossimamente",
"render.inspector_target_limit": "Seleziona al massimo 10000 oggetti per esaminarne gli aspetti.",
"render.inspector_textures": "Texture",
"render.inspector_this_body": "Questo corpo",
"render.inspector_this_component": "Questo componente",
"render.inspector_this_face": "Questa faccia",
"render.inspector_this_target": "Questo oggetto",
"render.inspector_used_by": "Usato da {count}",
"render.keep_editing": "Continua a modificare",
"render.layer_down": "Sposta giù",
"render.layer_enabled": "Livello abilitato",
@@ -2085,8 +2434,12 @@
"render.lens_effects_title": "Effetti d'obiettivo e fotografici",
"render.library_all": "Catalogo",
"render.library_all_states": "Tutti gli stati di disponibilità",
"render.library_appearance_available": "Aspetto disponibile",
"render.library_applicable": "Risorse applicabili",
"render.library_applied": "Proiezione della risorsa applicata. Verifica la richiesta di rendering completa prima di avviare.",
"render.library_apply_appearance": "Applica aspetto",
"render.library_apply_hdr": "Salva con questo ambiente HDR",
"render.library_apply_hint": "Fai clic per applicare · trascina sul modello",
"render.library_apply_maps": "Usa le mappe di superficie GPU predisposte",
"render.library_apply_studio": "Salva la proiezione dello studio predisposta",
"render.library_apply_uniform": "Applica aspetto opaco uniforme",
@@ -2102,15 +2455,23 @@
"render.library_extent": "Estensione del soggetto",
"render.library_favorite": "Aggiungi ai preferiti",
"render.library_favorites": "Preferiti",
"render.library_filters": "Catalogo e disponibilità",
"render.library_grid": "Griglia",
"render.library_hdr": "Ambienti HDR integrati",
"render.library_hdr_help": "Incorpora l'HDR originale nell'impostazione salvata. L'origine della longitudine predisposta viene convertita esplicitamente; dopo il salvataggio non serve alcun file esterno.",
"render.library_in_design": "Nel progetto",
"render.library_inspect_only": "Seleziona per esaminare; non viene applicato nulla automaticamente. I preferiti e la cronologia recente appartengono a questa sessione del documento aperto.",
"render.library_ior": "IOR",
"render.library_light_concepts": "Concetti di illuminazione",
"render.library_list": "Elenco",
"render.library_maps_help": "Le mappe integrate possono essere salvate con sorgenti fissate e mappatura locale delle occorrenze. Le sostituzioni ottiche temporanee restano una modalità separata.",
"render.library_material_concepts": "Concetti di materiale",
"render.library_metallic": "Metallicità",
"render.library_native_scenes": "Studi nativi",
"render.library_next": "Pagina successiva",
"render.library_omitted": "Non incluso",
"render.library_opacity": "Opacità",
"render.library_other": "Altri aspetti",
"render.library_physical_profiles": "Profili fisici di riferimento",
"render.library_previous": "Pagina precedente",
"render.library_quality_concepts": "Specifiche di qualità",
@@ -2120,6 +2481,7 @@
"render.library_results": "Risorse corrispondenti",
"render.library_rig_help": "Adatta una sola volta a un centro e a un'estensione fisica espliciti. I rig completi includono pannelli passivi; i blocchi di calibrazione continuano a rifiutare l'operazione. Prima del salvataggio viene verificata una distanza libera prudenziale tra emettitori e pannelli.",
"render.library_rigs": "Rig di illuminazione predisposti",
"render.library_roughness": "Rugosità",
"render.library_save_maps": "Salva le mappe in questa impostazione",
"render.library_scene_bounds": "Usa i limiti della scena acquisita",
"render.library_scenes": "Specifiche della scena",
@@ -2143,6 +2505,7 @@
"render.library_unfavorite": "Rimuovi dai preferiti",
"render.library_uniform_ack": "Usa l'approssimazione uniforme senza effetti spaziali o avanzati",
"render.library_usable": "Proiezioni eseguibili",
"render.library_users": "Usato da",
"render.light_anchor_pending": "La modifica del sistema di coordinate delle luci non è ancora supportata.",
"render.lights_fixed_to": "Luci fissate a",
"render.linear_help": "Mantiene un master RGBA float a 32 bit prima di riduzione del rumore, esposizione, tone mapping, filtri e sfondo. sRGB lineare/D65; con alfa premoltiplicato dalla copertura. La memoria aggiuntiva viene ammessa esplicitamente. Nessuna compressione né passate aggiuntive.",
@@ -2226,12 +2589,34 @@
"render.optics_saved": "Destinazioni ottiche salvate",
"render.optics_saved_help": "L'identità esatta di definizione, lavorazione e occorrenza sopravvive alla riapertura offline. Le destinazioni mancanti, sostituite o nascoste vengono rifiutate; i materiali tecnici restano invariati. Salva o scarta le modifiche numeriche prima di rimuovere una destinazione salvata.",
"render.outer_half_angle": "Semiangolo esterno",
"render.output_advanced": "Avanzate",
"render.output_backend_ready": "Pronto",
"render.output_check": "Verifica",
"render.output_check_help": "Esegui Verifica per esaminare questa richiesta senza avviare un rendering.",
"render.output_check_summary": "Verifica · Note: {count}",
"render.output_copy": "Copia",
"render.output_destination": "Destinazione",
"render.output_destination_help": "Scegli il file di destinazione quando esporti l'immagine completata.",
"render.output_dimensions": "Dimensioni",
"render.output_effects": "Effetti",
"render.output_export": "Esporta PNG…",
"render.output_exr_unavailable": "La configurazione dell'uscita EXR non è disponibile qui. L'esportazione EXR lineare richiede un'immagine GPU completata con un master lineare conservato.",
"render.output_fit": "Adatta",
"render.output_format": "Formato",
"render.output_format_status": "Il PNG è l'immagine visualizzata completata, esattamente com'è. L'EXR GPU facoltativo conserva la radianza FLOAT32 lineare della scena, grezza, prima dei filtri di visualizzazione. L'esportazione non sostituisce mai la cache dell'anteprima né un lavoro diverso.",
"render.output_image": "Immagine",
"render.output_largest": "max {width} × {height}",
"render.output_lock_ratio": "Blocca proporzioni",
"render.output_over_budget": "L'immagine richiesta supera i limiti di risorse selezionati. Scegli esplicitamente una dimensione o un profilo compatibile; non avviene alcun declassamento automatico.",
"render.output_presets_help": "Formato, qualità e l'elenco di Verifica si trovano nell'editor Uscita.",
"render.output_quality": "Qualità",
"render.output_quality_waiting": "in attesa del contratto di qualità",
"render.output_ratio_refused": "La dimensione collegata supera il limite di dimensioni di questo metodo. Viene mantenuta la dimensione precedente; sblocca le proporzioni o scegli un valore più piccolo.",
"render.output_ready": "Pronto per il rendering",
"render.output_size_ok": "Dimensioni OK · {width} × {height} px",
"render.output_swap_orientation": "Scambia larghezza e altezza",
"render.output_tools_inspector": "Modifica dimensioni e formato nell'ispettore Uscita.",
"render.output_view_image": "Visualizza immagine",
"render.page_aging": "Invecchiamento e contaminazione",
"render.page_all": "Tutti i comandi",
"render.page_appearance": "Aspetto",
@@ -2292,10 +2677,18 @@
"render.property_unknown": "sconosciuto",
"render.quality_ack": "Conferma la proiezione a budget fisso e le omissioni",
"render.quality_apply": "Usa questo budget di campionamento fisso",
"render.quality_balanced": "Bilanciata",
"render.quality_custom": "Personalizzata",
"render.quality_draft": "Bozza",
"render.quality_high": "Alta",
"render.quality_projection_help": "Le preimpostazioni Q includono requisiti futuri. Questa azione proietta solo un budget PNG a campioni fissi supportato e omette esplicitamente l'arresto adattivo, l'output lineare grezzo e i limiti di trasmissione indipendenti.",
"render.quality_review": "Esamina il budget di campionamento",
"render.queue_pending": "In questa interfaccia non esiste una coda di produzione automatica né un renderer di animazioni. Le immagini fisse completate restano esportabili separatamente.",
"render.radial_assign": "Assegna aspetto",
"render.radial_compare": "Confronta",
"render.radial_distortion": "Distorsione radiale",
"render.radial_fit": "Inquadra prodotto",
"render.radial_save": "Salva inquadratura",
"render.regrade_action": "Correggi il colore del master grezzo (senza riduzione del rumore)",
"render.regrade_help": "Crea un PNG separato dal master grezzo completato selezionato, usando questi controlli di presentazione. Non traccia raggi, non modifica dimensioni, camera o luci acquisite e non sovrascrive l'EXR. La riduzione del rumore non viene riapplicata: i master grezzi non conservano le sue guide. Il derivato resta esportabile con gli stessi controlli del lavoro.",
"render.regrade_label": "Correzione colore",
@@ -2304,6 +2697,7 @@
"render.replace_label": "Sostituisci",
"render.replace_saved_surface": "Sostituisci un'associazione salvata esistente per questa destinazione",
"render.restore_camera": "Ripristina camera salvata",
"render.result_actual": "100%",
"render.result_actual_help": "Un pixel dell'immagine per ogni pixel dello schermo.",
"render.result_actual_size": "100%",
"render.result_capture": "Revisione acquisita",
@@ -2361,6 +2755,7 @@
"render.scene_review": "Risolvi ed esamina",
"render.scene_review_help": "Esamina la composizione nativa completa prima di applicarla. Le specifiche SCENE avanzate non associate non vengono sostituite.",
"render.scene_scope_details": "Ambito della composizione",
"render.search_appearances": "Cerca tra {count} aspetti",
"render.setup_legacy_environment": "Questa impostazione precedente usa la rotazione o l'intensità dell'ambiente nel formato obsoleto. Questi valori vengono conservati; convertili esplicitamente prima di salvare un lavoro immagine completo.",
"render.setup_name": "Nome dell'impostazione",
"render.setup_numeric_help": "Salva registra il metodo immagine attivo e tutte le sue impostazioni numeriche. Ricaricare o scegliere un'altra impostazione sostituisce questa bozza; ripristina la camera separatamente.",
@@ -2370,6 +2765,7 @@
"render.sharpening": "Nitidezza dei dettagli",
"render.shell_tab_appearance": "ASPETTO RENDERING",
"render.shell_tab_camera": "CAMERA RENDERING",
"render.shell_tab_lighting": "ILLUMINAZIONE",
"render.shell_tab_scene": "SCENA RENDERING",
"render.shot_duplicate": "Duplica l'inquadratura salvata",
"render.shot_manager": "Inquadrature salvate",
@@ -2379,22 +2775,126 @@
"render.shot_remove_title": "Rimuovere l'inquadratura salvata?",
"render.shot_rename": "Rinomina l'inquadratura salvata",
"render.shot_saved_only": "Salva prima la bozza attuale. Duplica e Rinomina conservano esattamente le opzioni salvate e i riferimenti alle risorse.",
"render.shots_camera_changed": "La camera è cambiata da quando l'inquadratura è stata salvata",
"render.shots_name_help": "Inserisci un nome univoco per l'inquadratura corrente.",
"render.shots_no_result": "Ancora nessun rendering",
"render.shots_result": "Rendering {number} · {width} × {height}",
"render.shots_revert": "Ripristina",
"render.shots_save": "Salva inquadratura",
"render.shots_update": "Aggiorna inquadratura",
"render.show_shots_label": "Mostra la barra delle inquadrature",
"render.size_4k": "4K",
"render.size_4k_uhd": "4K UHD",
"render.size_custom": "Personalizzato…",
"render.size_full_hd": "Full HD",
"render.size_hd": "HD",
"render.size_presets": "Preimpostazioni delle dimensioni",
"render.size_presets_pending": "In arrivo con l'editor Uscita",
"render.size_preview": "Anteprima",
"render.size_square": "Quadrata",
"render.sky_ground": "Suolo · RGB lineare",
"render.sky_horizon": "Orizzonte · RGB lineare",
"render.sky_zenith": "Zenit · RGB lineare",
"render.soft_focus": "Messa a fuoco morbida",
"render.spot_cone": "Cono dello spot",
"render.stage_frame": "Fotogramma",
"render.stage_layout.appearance_note": "Fai clic per applicare alla selezione.",
"render.stage_layout.studio_note": "Fai clic per esaminare prima di applicare.",
"render.stage_light": "Luce",
"render.stage_look": "Aspetto",
"render.stage_orthographic": "Ortografica",
"render.stage_output": "Uscita",
"render.stage_panel_count": "Pannelli salvati",
"render.stage_panels.acknowledge": "Prendo atto della sostituzione e delle limitazioni",
"render.stage_panels.appearance_note": "Fai clic per applicare alla selezione. Trascina sul modello. Se non è selezionato nulla, un clic attiva Vernice.",
"render.stage_panels.apply": "Applica",
"render.stage_panels.apply_studio": "Applica studio",
"render.stage_panels.badge_blocked": "bloccato",
"render.stage_panels.badge_native": "nativo",
"render.stage_panels.badge_projection": "proiezione",
"render.stage_panels.badge_reference": "riferimento",
"render.stage_panels.badge_specification": "solo specifica",
"render.stage_panels.candidate_summary": "Candidati: {count} valori documentati. Grado e finitura richiedono verifica.",
"render.stage_panels.captured_bounds": "Usa i limiti della scena acquisita",
"render.stage_panels.centre": "Centro",
"render.stage_panels.depth": "profondità",
"render.stage_panels.environments": "Ambienti",
"render.stage_panels.extent": "Estensione",
"render.stage_panels.fit_save": "Adatta e salva",
"render.stage_panels.gpu_required": "Richiede il path tracing su GPU",
"render.stage_panels.keep": "Mantieni",
"render.stage_panels.kept": "Mantiene",
"render.stage_panels.kept_fields": "Camera, campionamento, dimensioni, associazioni ottiche, geometria CAD e proprietà ingegneristiche.",
"render.stage_panels.kept_quality": "Metodo, camera, illuminazione, ambiente, set fotografico, ottica, esposizione e mappatura tonale.",
"render.stage_panels.mine": "Miei",
"render.stage_panels.mine_pending": "Il salvataggio di studi personali non è ancora supportato.",
"render.stage_panels.omits": "Omette",
"render.stage_panels.paint_pending": "L'assegnazione con Vernice e trascinamento non è ancora supportata. Seleziona una destinazione per applicare un aspetto.",
"render.stage_panels.partial_reference": "Candidati: solo valori documentati; verifica grado, condizione e fonti. I valori sconosciuti restano sconosciuti.",
"render.stage_panels.plane": "Piano",
"render.stage_panels.prepare_plan": "Prepara piano di creazione",
"render.stage_panels.projects": "Progetti",
"render.stage_panels.quality_ack": "Prendo atto del budget fisso e delle sue omissioni",
"render.stage_panels.quality_omissions": "Arresto adattivo e obiettivi di errore, profondità di trasmissione separata, regole di roulette russa, uscita lineare grezza, master EXR e certificazione della convergenza.",
"render.stage_panels.reference": "Riferimento",
"render.stage_panels.references": "Riferimenti",
"render.stage_panels.remove_optics": "Rimuovi ottica",
"render.stage_panels.remove_optics_help": "Rimuove l'ottica salvata da questa inquadratura. La geometria di origine viene mantenuta.",
"render.stage_panels.remove_optics_title": "Rimuovere l'ottica salvata?",
"render.stage_panels.remove_shot": "Rimuovi inquadratura",
"render.stage_panels.remove_stage": "Rimuovi set fotografico",
"render.stage_panels.remove_stage_help": "Rimuove i pannelli passivi salvati da questa inquadratura. Lo sfondo della camera resta.",
"render.stage_panels.remove_stage_title": "Rimuovere il set fotografico salvato?",
"render.stage_panels.repeat": "Ripeti",
"render.stage_panels.replaces": "Sostituisce",
"render.stage_panels.replaces_environment": "Ambiente",
"render.stage_panels.replaces_maps": "Mappe temporanee sul corpo selezionato; l'ottica salvata può essere in conflitto.",
"render.stage_panels.replaces_physical": "Niente. Questo piano è di sola lettura.",
"render.stage_panels.replaces_quality": "Dimensioni dell'immagine, campioni fissi, profondità dei percorsi, seed e riduzione del rumore.",
"render.stage_panels.replaces_rig": "Illuminazione, ambiente e set fotografico",
"render.stage_panels.replaces_saved_maps": "Mappe di superficie salvate sul corpo selezionato; le sostituzioni temporanee possono essere in conflitto.",
"render.stage_panels.replaces_stage": "Piano d'appoggio salvato e pannelli passivi del set fotografico",
"render.stage_panels.replaces_studio": "Illuminazione, ambiente, esposizione e set fotografico",
"render.stage_panels.replaces_uniform": "Aspetto opaco sul corpo selezionato. Le mappe spaziali sono approssimate da valori uniformi.",
"render.stage_panels.review_environment": "Esamina ambiente",
"render.stage_panels.review_maps": "Esamina mappe GPU",
"render.stage_panels.review_physical": "Piano di riferimento fisico",
"render.stage_panels.review_quality": "Usa un budget di campionamento fisso",
"render.stage_panels.review_rig": "Adatta rig di luci",
"render.stage_panels.review_saved_maps": "Esamina mappe salvate",
"render.stage_panels.review_stage": "Esamina piano d'appoggio e set fotografico",
"render.stage_panels.review_studio": "Esamina studio nativo",
"render.stage_panels.review_uniform": "Esamina aspetto uniforme",
"render.stage_panels.rig_summary": "Rig di luci predisposto · {emitters} emettitori, {cards} pannelli",
"render.stage_panels.rigs": "Rig",
"render.stage_panels.save_maps": "Salva le mappe in questa inquadratura",
"render.stage_panels.scope": "Ambito",
"render.stage_panels.search_studios": "Cerca studi",
"render.stage_panels.search_surfaces": "Cerca superfici e riferimenti",
"render.stage_panels.source_note": "Mappa di origine del colore di base predisposta. Non è un materiale misurato.",
"render.stage_panels.specifications": "Specifiche · sola lettura",
"render.stage_panels.studio_ack": "Conferma la sostituzione di illuminazione, ambiente, esposizione e set fotografico",
"render.stage_panels.studio_note": "Fai clic per esaminare. L'applicazione sostituisce illuminazione, ambiente e set fotografico solo dopo la tua conferma. Le luci restano modificabili.",
"render.stage_panels.studios": "Studi",
"render.stage_panels.subtitle_environment": "Ambiente HDR originale · intera scena",
"render.stage_panels.subtitle_maps": "Mappe spaziali predisposte · anteprima temporanea",
"render.stage_panels.subtitle_physical": "Piano di sola lettura · nessun materiale creato o assegnato",
"render.stage_panels.subtitle_quality": "Budget GPU fisso · requisiti futuri omessi",
"render.stage_panels.subtitle_rig": "Rig di luci predisposto · emettitori e pannelli passivi",
"render.stage_panels.subtitle_saved_maps": "Mappe predisposte · salvate con questa inquadratura",
"render.stage_panels.subtitle_stage": "Piano d'appoggio e set fotografico fisici · adattati al prodotto",
"render.stage_panels.subtitle_studio": "Studio nativo · si applica all'intera scena",
"render.stage_panels.subtitle_uniform": "Approssimazione uniforme · non è un materiale misurato",
"render.stage_panels.surfaces": "Superfici",
"render.stage_panels.surfaces_references": "Superfici e riferimenti",
"render.stage_panels.target": "Destinazione",
"render.stage_panels.use_budget": "Usa questo budget",
"render.stage_panels.use_maps": "Usa mappe GPU",
"render.stage_panels.use_uniform": "Usa uniforme",
"render.stage_preview_note": "Anteprima integrata · luce diretta",
"render.state_completed": "Immagine completata",
"render.state_in_progress": "Immagine in corso",
"render.state_model": "Anteprima del modello",
"render.strip_label": "Barra",
"render.studio_add_area": "Aggiungi luce ad area",
"render.studio_ambient": "Radianza costante dell'ambiente",
@@ -2433,8 +2933,10 @@
"render.studio_sky_help": "Gradiente di cielo originale per l'illuminazione; non è un modello atmosferico calibrato.",
"render.studio_sun": "Sole",
"render.studio_sun_radius": "Raggio angolare",
"render.studio_tiles_require_gpu": "Gli studi richiedono il path tracing su GPU. Seleziona GPU nell'editor Uscita.",
"render.studio_title": "Studio di rendering",
"render.studio_tone_map": "Mappatura tonale",
"render.studios_environments": "Studi e ambienti",
"render.subsurface_enable": "Random walk di diffusione interna",
"render.subsurface_help": "Solo dielettrici chiusi. Lo scattering e l'assorbimento RGB sono coefficienti separati per mm. I percorsi si diffondono all'interno della geometria effettiva, poi si rifrangono o si riflettono sul contorno. Richiede di disattivare la trasmissione diretta delle ombre, la riduzione del rumore sulle superfici e il volume esterno, e di usare uno strato di Fresnel. Non è uno shader a diffusione, una griglia di densità né un materiale misurato. I mezzi densi possono richiedere più campioni e una maggiore profondità dei percorsi.",
"render.subsurface_rate": "Frequenza di collisione dello scattering",
@@ -2488,6 +2990,7 @@
"render.volume_max": "Limiti massimi · mm globali",
"render.volume_min": "Limiti minimi · mm globali",
"render.volume_title": "Volume omogeneo delimitato",
"render.wait_add_light": "non ancora supportato: creazione di luci con nome",
"render.wait_batch": "non ancora supportato: la coda di rendering delle inquadrature salvate",
"render.wait_compare": "non ancora supportato: il confronto delle immagini conservate",
"render.wait_paint": "non ancora supportato: la selezione del prodotto e l'applicazione degli aspetti con il pennello",
@@ -2542,6 +3045,7 @@
"select two components": "seleziona due componenti",
"set by the sketch's lines": "impostato dalle linee dello schizzo",
"settings.display_quality_note": "I livelli più fini rendono più uniformi le facce curve e gli spigoli e richiedono più tempo per la mesh. Cambia solo la vista, mai il progetto o le esportazioni.",
"settings.double_click_components": "Doppio clic su un componente per attivarlo o, se è collegato, per modificarlo sul posto",
"settings.frame_rate_details_note": "Aggiunge un grafico dei tempi degli ultimi fotogrammi con i triangoli disegnati sopra, un istogramma dei tempi dei fotogrammi e ciò che la GPU ha disegnato. Fai clic sulla frequenza nella vista per mostrarli o nasconderli.",
"settings.frame_rate_note": "Mostra i fotogrammi al secondo nell'angolo inferiore destro della vista.",
"settings.measure_axis_distances": "Mostra distanze X/Y/Z",
@@ -2554,6 +3058,7 @@
"settings.reset_intro": "Queste impostazioni non funzionano su questo computer e impedirebbero l'avvio di SolidCraft, quindi sono state modificate:",
"settings.reset_title": "Le impostazioni sono state modificate",
"settings.supersampling_note": "Disegna la vista a una risoluzione maggiore e la riduce tramite filtro: spigoli, linee e griglia più uniformi sugli schermi sotto il 4K. Richiede tempo GPU: circa 2.25× i pixel a 1.5× e 4× a 2×.",
"settings.update_changed_links": "Aggiorna i progetti collegati modificati quando una scheda torna in primo piano",
"settings.window_system_details": "Dettagli",
"settings.window_system_note_now": "Si applica dopo un riavvio. Ora: {now}.",
"settings.window_system_wayland_limited": "Alcune funzioni sono limitate su Wayland nativo.",
@@ -2600,6 +3105,10 @@
"sketch_text.path_hint": "Una curva dello schizzo seguita dal testo: fai clic qui, poi sulla curva",
"sketch_text.use_font_file": "Usa il file di carattere {path}",
"solid": "solido",
"status.editing": "Modifica di {name}",
"status.under_constrained": "Sottovincolato ({count} gradi di libertà)",
"status.under_constrained_one": "Sottovincolato ({count} grado di libertà)",
"status.units_tip": "Le unità del progetto. Fai clic per cambiarle",
"the angle must be a number": "l'angolo deve essere un numero",
"the curves must be in one sketch": "le curve devono stare in un solo schizzo",
"the direction must be an axis, a sketch line or a straight edge": "la direzione deve essere un asse, una linea dello schizzo o uno spigolo retto",
@@ -3038,6 +3547,9 @@
"ui.blocked": "Bloccato",
"ui.bodies": "Corpi",
"ui.bodies_all_if_none": "Corpi (tutti se nessuno)",
"ui.body_kind_mesh": "Corpo a mesh",
"ui.body_kind_solid": "Corpo solido",
"ui.body_kind_surface": "Corpo di superficie",
"ui.bottom": "Inferiore",
"ui.box": "Parallelepipedo",
"ui.break": "Spezza",
@@ -3132,6 +3644,7 @@
"ui.design_properties.part_number": "Codice parte",
"ui.design_properties.project": "Progetto",
"ui.design_properties.revision": "Revisione",
"ui.design_saved": "Salvato in {path}",
"ui.diameter": "Diametro",
"ui.dimension": "Quota",
"ui.direct_interaction": "Interazione diretta",
@@ -3157,6 +3670,24 @@
"ui.easyprint_uploading": "Caricamento su Printables…",
"ui.edit": "Modifica",
"ui.editJointLimits": "Modifica limiti del giunto",
"ui.edit_in_place": "Modifica sul posto",
"ui.edit_in_place_after_turn": "La modifica termina alla fine del turno dell'agente",
"ui.edit_in_place_agent_busy": "L'agente sta ancora lavorando in questo progetto; riprova quando il suo turno è terminato",
"ui.edit_in_place_already_queued": "Una modifica è già in attesa della fine del turno dell'agente",
"ui.edit_in_place_assembly_closed": "{name} non è più aperto",
"ui.edit_in_place_banner": "Modifica in {name}",
"ui.edit_in_place_busy": "Termina o annulla prima ciò che è aperto",
"ui.edit_in_place_none": "Nessun progetto collegato è in modifica sul posto",
"ui.edit_in_place_not_saved": "La parte ha modifiche non salvate; salvala per terminare la modifica",
"ui.edit_in_place_open_elsewhere": "{name} è aperto in un'altra istanza di SolidCraft",
"ui.edit_in_place_opens_after_turn": "La parte si apre alla fine del turno dell'agente",
"ui.edit_in_place_refresh_dropped": "L'assieme è cambiato durante l'esecuzione di Aggiorna collegamenti; eseguilo di nuovo",
"ui.edit_in_place_refresh_stopped": "Aggiorna collegamenti si è interrotto prima del completamento",
"ui.edit_in_place_refreshing": "Aggiornamento dei collegamenti in {name}…",
"ui.edit_in_place_save_first": "Salva prima l'assieme: i suoi progetti collegati vengono trovati a partire dal suo file",
"ui.edit_in_place_save_waits": "Aggiorna collegamenti è in esecuzione in {name}; salvalo al termine",
"ui.edit_in_place_saved_elsewhere": "La parte è stata salvata in un altro file; l'assieme è ancora collegato a {name}",
"ui.edit_in_place_wait": "Attendi il termine di ciò che è in esecuzione nel progetto",
"ui.edit_section_analysis": "Modifica analisi in sezione",
"ui.ellipse": "Ellisse",
"ui.emboss_wrap_note": "I profili di linee ortogonali tangenti a un cilindro supportato si avvolgono automaticamente. Scegliere una parete per definire la destinazione.",
@@ -3231,6 +3762,7 @@
"ui.heading_edit": "MODIFICA",
"ui.heading_extrude": "ESTRUSIONE",
"ui.heading_fillet": "RACCORDO",
"ui.heading_finish_editing": "TERMINA MODIFICA",
"ui.heading_finish_sketch": "TERMINA SCHIZZO",
"ui.heading_form": "FORMA",
"ui.heading_front": "FRONTALE",
@@ -3301,6 +3833,10 @@
"ui.history_marker_tip": "Marcatore della cronologia: trascinalo per far tornare indietro il modello; le nuove lavorazioni vanno qui",
"ui.history_names": "Nomi",
"ui.history_play": "Riproduci fino alla fine",
"ui.history_play_button_hide": "Nascondi pulsante Riproduci",
"ui.history_play_button_show": "Mostra pulsante Riproduci",
"ui.history_play_finish_action": "Termina l'azione corrente prima di riprodurre la cronologia",
"ui.history_play_roll_back": "Sposta indietro il marcatore della cronologia prima di riprodurre",
"ui.history_show_names": "Mostra nomi",
"ui.history_sketch_listed_under": "Elencato sotto {feature}",
"ui.history_title": "Cronologia",
@@ -3443,6 +3979,15 @@
"ui.plugins_skipped": "Impossibile leggere {count} cartelle.",
"ui.plugins_version": "{version}",
"ui.point": "Punto",
"ui.point_cloud_auto_range": "Intervallo automatico",
"ui.point_cloud_color_by": "Colora per",
"ui.point_cloud_file_colors": "Colori del file",
"ui.point_cloud_height_high": "Più alto",
"ui.point_cloud_height_low": "Più basso",
"ui.point_cloud_no_file_colors": "Il file non contiene colori",
"ui.point_cloud_single_color": "Colore singolo",
"ui.point_cloud_size": "Dimensione dei punti",
"ui.point_cloud_units": "Unità del file",
"ui.point_under_the_cursor": "Punto sotto il cursore",
"ui.points": "Punti",
"ui.polygon": "Poligono",
@@ -3490,6 +4035,10 @@
"ui.restore_defaults": "Ripristina valori predefiniti",
"ui.reverse_horizontal_pan_direction": "Inverti direzione della panoramica orizzontale",
"ui.reverse_horizontal_pan_tip": "Lo scorrimento orizzontale a due dita e la rotella del pollice eseguono la panoramica nella direzione opposta",
"ui.reverse_trackpad_orbit_direction": "Inverti la direzione dell'orbita con il trackpad",
"ui.reverse_trackpad_orbit_tip": "Shift con lo scorrimento a due dita orbita nel verso opposto",
"ui.reverse_vertical_pan_direction": "Inverti la direzione della panoramica verticale",
"ui.reverse_vertical_pan_tip": "Lo scorrimento verticale con due dita sposta la vista nel verso opposto",
"ui.reverse_zoom_direction": "Inverti direzione dello zoom",
"ui.revolutions": "Giri",
"ui.revolve": "Rivoluzione",
@@ -3635,7 +4184,22 @@
"ui.updateToCurrentView": "Aggiorna alla vista corrente",
"ui.upload": "Carica",
"ui.vertical_constraint": "Vincolo verticale",
"ui.view_angles": "Angoli della vista",
"ui.view_angles_convention": "Gradi attorno all'asse verticale. Imbardata 0° è la vista frontale, 90° sinistra, −90° destra, 180° posteriore; beccheggio 90° è la vista dall'alto; un rollio positivo ruota il modello in senso orario.",
"ui.view_angles_help": "Mostra il beccheggio, l'imbardata e il rollio della vista in gradi e la sua proiezione sotto il gizmo di orientamento. Fai clic sull'indicatore per digitare angoli esatti.",
"ui.view_angles_ortho": "Ortogonale",
"ui.view_angles_persp": "Prospettica",
"ui.view_angles_pitch": "Beccheggio",
"ui.view_angles_readout": "Beccheggio {pitch} · Imbardata {yaw} · Rollio {roll}",
"ui.view_angles_roll": "Rollio",
"ui.view_angles_yaw": "Imbardata",
"ui.view_centre": "Centro della vista",
"ui.viewport_status_clear": "Disattiva {name}",
"ui.viewport_status_clear_hint": "Disattiva {name} · Esc",
"ui.viewport_status_key": "Mostra la legenda di {name}",
"ui.viewport_status_minimum_radius": "Raggio minimo",
"ui.viewport_status_pairs": "{count} coppie",
"ui.viewport_status_stripes": "{count} strisce",
"ui.viewport_theme_follow": "Segui il tema",
"ui.visual_shaded_hidden_edges": "Ombreggiato con spigoli nascosti",
"ui.visual_shaded_with_edges": "Ombreggiato con spigoli",
@@ -3706,6 +4270,7 @@
"values must be finite numbers": "i valori devono essere numeri finiti",
"values must be numbers or expressions": "i valori devono essere numeri o espressioni",
"view.auto_ortho_faces": "Prospettiva durante l'orbita, ortografica sulle facce",
"view.render_inspector": "Ispettore di rendering",
"web.files.insert_drawings_hint": "File CAD, mesh, DXF o SVG nel progetto aperto",
"web.files.insert_stored_drawings_hint": "Nel progetto aperto (file CAD, mesh, DXF, SVG)",
"web.open_full": "Apri in SolidCraft",
+652 -29
View File
File diff suppressed because it is too large Load Diff
+593
View File
@@ -668,6 +668,7 @@
"appearance.pbr_opaque": "불투명 PBR",
"appearance.roughness": "거칠기",
"appearance.surface_response": "표면 반응",
"at the face": "면에서",
"bom.group_children": "하위 부품을 상위 부품 행에 표시",
"browser.body_name": "바디{number}",
"browser.calibrate_title": "보정: {name}",
@@ -676,6 +677,7 @@
"browser.capture_one": "구성요소가 이동되었지만 위치가 캡처되지 않았습니다.",
"browser.component_name": "컴포넌트{number}",
"browser.edit_canvas_title": "캔버스 편집: {name}",
"browser.edit_point_cloud_title": "포인트 클라우드 편집: {name}",
"browser.move_title": "이동: {name}",
"browser.parameters": "매개변수 ({count})",
"browser.precision": "정밀도: {precision}",
@@ -690,6 +692,9 @@
"cam.roller": "롤러",
"cam.roller_pick": "롤러 (선택 사항)",
"cam.tip_pick": "끝점 (선택 사항)",
"camera.shot_pitch": "피치",
"camera.shot_roll": "롤",
"camera.shot_yaw": "요",
"choose a profile": "프로파일을 선택하세요",
"choose the cam's and the follower's joints": "캠과 종동절의 관절을 선택하세요",
"choose the joints to couple": "연결할 관절을 선택하세요",
@@ -697,9 +702,12 @@
"click sketch curves": "스케치 곡선 클릭",
"cmd.appearance_assign": "외관",
"cmd.appearance_chain": "외관 출처",
"cmd.appearance_copy": "외관 복사",
"cmd.appearance_favorite": "외관 즐겨찾기",
"cmd.appearance_library": "외관 라이브러리",
"cmd.appearance_list": "외관 목록",
"cmd.appearance_paint": "모양 칠하기",
"cmd.appearance_paste": "외관 붙여넣기",
"cmd.appearance_pick_up": "모양 가져오기",
"cmd.appearance_replace": "모양 바꾸기",
"cmd.assembly_bom": "자재 명세서",
@@ -888,6 +896,10 @@
"cmd.plastic_rest": "레스트",
"cmd.plastic_rules": "플라스틱 규칙 목록",
"cmd.plastic_snap_fit": "스냅핏",
"cmd.pointcloud_delete": "포인트 클라우드 삭제",
"cmd.pointcloud_edit": "포인트 클라우드 편집",
"cmd.pointcloud_insert": "포인트 클라우드 삽입",
"cmd.pointcloud_list": "포인트 클라우드",
"cmd.render_backends": "렌더링 백엔드",
"cmd.render_batch": "모든 샷 렌더링",
"cmd.render_camera_fit": "렌더 대상 화면 맞춤",
@@ -907,9 +919,20 @@
"cmd.render_library_surface_prepare": "제작된 표면 맵 준비",
"cmd.render_library_surface_unbind": "Remove Surface Binding",
"cmd.render_library_targets": "렌더 리소스 대상 찾기",
"cmd.render_lights_add": "조명 추가",
"cmd.render_lights_duplicate": "렌더 조명 복제",
"cmd.render_lights_list": "렌더 조명 목록",
"cmd.render_lights_mute": "조명 음소거",
"cmd.render_lights_remove": "렌더 조명 제거",
"cmd.render_lights_set": "렌더 조명 설정",
"cmd.render_lights_solo": "광원 단독 표시",
"cmd.render_output_size": "렌더 출력 크기 설정",
"cmd.render_preflight": "렌더 요청 확인",
"cmd.render_preflight_copy": "렌더 검사 보고서 복사",
"cmd.render_result_close": "렌더 이미지 닫기",
"cmd.render_result_copy": "렌더 이미지 복사",
"cmd.render_result_pin": "표시된 렌더 결과 유지",
"cmd.render_result_view": "렌더 이미지 보기",
"cmd.render_scene": "렌더링 장면 검사",
"cmd.render_settings_apply": "렌더링 카메라 적용",
"cmd.render_settings_capture_hdr": "HDR과 렌더 설정 저장",
@@ -1004,6 +1027,7 @@
"cmd.sketch_spline_control_point": "제어점 스플라인",
"cmd.sketch_spline_control_point_5": "제어점 스플라인(5차)",
"cmd.sketch_spline_fit_point": "맞춤점 스플라인",
"cmd.sketch_spline_reverse": "스플라인 방향 반전",
"cmd.sketch_spun_profile": "회전 프로파일",
"cmd.sketch_toggle_driven": "종속 치수 전환",
"cmd.sketch_transform": "변환",
@@ -1044,11 +1068,13 @@
"cmd.timeline_export_script": "명령 스크립트 내보내기",
"cmd.timeline_inspect": "특성 검사",
"cmd.timeline_paste": "특성 붙여넣기",
"cmd.timeline_play": "기록 재생",
"cmd.timeline_redefine": "특성 편집",
"cmd.timeline_rename": "이름 변경",
"cmd.timeline_reorder": "특성 순서 변경",
"cmd.timeline_roll_to": "이력 마커 이동",
"cmd.timeline_rollback": "타임라인 마커 이동",
"cmd.timeline_stop": "기록 재생 중지",
"cmd.timeline_suppress": "특성 비활성화",
"cmd.view.render_browser": "렌더 브라우저",
"cmd.view.render_dock": "렌더 도크 이동",
@@ -1062,15 +1088,20 @@
"cmd.view_navigate": "보기 탐색",
"cmd.view_normal_to": "선택 항목에 수직",
"cmd.view_rename": "이름 있는 보기 이름 변경",
"cmd.view_render_frame": "렌더 프레임 가이드",
"cmd.view_save": "새 이름 있는 보기",
"cmd.view_shots_strip": "샷 스트립",
"color.copy": "클릭하여 색상 값 복사",
"color.edit": "클릭하여 색상 편집",
"color.gamma": "색상 값을 0-255 감마 공간으로 표시 중",
"color.hex": "Hex",
"color.hex_help": "#rrggbb 또는 #rrggbbaa 입력. 6자리 값은 불투명도 유지",
"color.hex_hint": "#rrggbb",
"color.hue": "색조",
"color.linear": "색상 값을 0-1 선형 공간으로 표시 중",
"color.saturation_value": "채도 및 명도",
"color.selected": "선택한 색상",
"config.column_filter_empty": "일치하는 열이 없습니다",
"contact.components_count": "구성요소 {count}개",
"contact.enabled_label": "활성화됨",
"coupling.gear_1": "기어 1",
@@ -1162,6 +1193,7 @@
"help.licences": "라이선스",
"help.mit": "MIT 라이선스",
"help.notice": "NOTICE",
"help.pointcloud.insert": "PLY, XYZ 또는 PTS 스캔을 모델 옆에 포인트 클라우드로 삽입합니다. 측정 데이터를 참고하여 모델링할 때 사용합니다.",
"help.solid.chamfer": "선택한 모서리를 지정한 거리만큼 평평하게 깎습니다. 날카로운 모서리를 다듬거나 핀 또는 나사가 쉽게 들어가도록 할 때 사용합니다.",
"help.solid.extrude": "스케치 프로파일을 지정한 거리만큼 3D로 밀어내 재료를 더하거나 제거합니다. 평면 윤곽을 블록, 보스 또는 포켓으로 만들 때 사용합니다.",
"help.solid.fillet": "선택한 모서리를 지정한 반지름의 매끄러운 원호로 둥글게 만듭니다. 강도, 편의성 또는 외관을 위해 날카로운 모서리를 부드럽게 할 때 사용합니다.",
@@ -1169,6 +1201,9 @@
"help.solid.revolve": "스케치 프로파일을 축을 중심으로 회전시켜 둥근 솔리드를 만듭니다. 샤프트, 손잡이, 그릇 및 중심선을 기준으로 둥근 모든 부품에 사용합니다.",
"help.solid.shell": "솔리드의 속을 비우고 지정한 두께의 벽을 남기며, 선택한 면을 열 수도 있습니다. 상자, 커버 및 기타 얇은 벽 부품에 사용합니다.",
"help.third_party": "타사 라이선스",
"help.timeline.play": "남은 피처를 하나씩 재생하고 각 재생성 후 0.5초 동안 멈춥니다. 이 명령을 다시 실행하거나 Escape 키를 누르면 중지됩니다. 끝으로 이동은 즉시 마지막 단계로 이동합니다.",
"history.sketch_under_constrained": "구속 부족 (자유도 {count}개)",
"history.sketch_under_constrained_one": "구속 부족 (자유도 {count}개)",
"home.back": "{name}(으)로 돌아가기",
"home.crashes": "충돌 보고서",
"home.design_workspace": "설계",
@@ -1459,6 +1494,8 @@
"prefs.bodies_folders_never": "표시 안 함",
"prefs.bodies_folders_several": "바디가 여러 개일 때만",
"prefs.bottom": "아래쪽",
"prefs.bottom_centre": "하단 가운데",
"prefs.bottom_right": "오른쪽 아래",
"prefs.browser": "브라우저",
"prefs.built_in": "기본 제공",
"prefs.button_left": "왼쪽 드래그",
@@ -1506,6 +1543,8 @@
"prefs.history": "이력",
"prefs.history_origin_bodies": "원점과 바디를 맨 위에 표시",
"prefs.history_origin_bodies_note": "왼쪽 또는 브라우저 아래의 히스토리가 활성 구성 요소의 바디 폴더와 원점으로 시작하며, 브라우저처럼 표시 아이콘과 메뉴가 있습니다. 아래쪽 히스토리는 바뀌지 않습니다.",
"prefs.history_play_button": "기록 컨트롤에 기록 재생 버튼 표시",
"prefs.history_play_button_note": "기록 컨트롤의 한 단계 뒤로와 한 단계 앞으로 사이에 기록 재생을 추가합니다. 컨트롤을 마우스 오른쪽 버튼으로 클릭해 표시하거나 숨길 수도 있습니다.",
"prefs.hold_stop_snapping": "누르고 있으면 스냅 중지",
"prefs.icons_only": "아이콘만",
"prefs.imported_file": "가져온 파일",
@@ -1521,6 +1560,13 @@
"prefs.left_click": "왼쪽 클릭",
"prefs.live_input": "실시간 입력",
"prefs.live_preview": "실시간 미리보기",
"prefs.max_file_size": "열 수 있는 최대 파일 크기",
"prefs.max_file_size_design": "디자인 파일",
"prefs.max_file_size_flag": "이번 실행은 --max-file-size {size}로 시작했으며 SolidCraft를 닫을 때까지 적용됩니다. 이 설정은 해당 옵션 없이 시작할 때 적용됩니다.",
"prefs.max_file_size_note": "기본값: 512 MB 및 256 MB, 최대 16 GB. 파일을 열려면 파일 크기의 몇 배에 달하는 메모리가 필요합니다. 큰 가져오기 데이터를 보관하는 디자인은 저장하고 다시 열기 위해 디자인 파일 한도를 높여야 할 수 있습니다.",
"prefs.max_file_size_step": "STEP 및 가져오기 파일",
"prefs.max_file_size_web": "웹 앱은 STEP 및 가져오기 파일을 512 MB까지, 디자인을 256 MB까지 엽니다. 브라우저 탭은 더 큰 파일을 담을 수 없습니다. 데스크톱 앱에서는 이 한도를 높일 수 있습니다.",
"prefs.megabytes": "MB",
"prefs.minutes": "분",
"prefs.minutes_suffix": " min",
"prefs.mouse": "마우스 및 트랙패드",
@@ -1555,9 +1601,13 @@
"prefs.shift_add_ctrl_toggle": "Shift는 추가만, Ctrl / Cmd는 토글",
"prefs.shift_add_note": "켬: Shift는 추가, Ctrl / Cmd는 토글. 끔(기본값): 둘 다 토글.",
"prefs.shortcuts": "단축키",
"prefs.sketch_conflict_colour": "충돌하는 기하를 충돌 색상으로 표시",
"prefs.sketch_conflict_colour_note": "스케치의 구속 조건이 충돌하는 동안 실패한 구속 조건의 글리프나 치수뿐 아니라 그 구속 조건이 잡고 있는 곡선과 점도 충돌 색상으로 그립니다. 끄기: 평소 색상을 유지합니다.",
"prefs.sketch_selection": "스케치 및 선택",
"prefs.sketch_selection_heading": "스케치 및 선택",
"prefs.sketch_selection_note": "스케치가 스냅되는 방식과 클릭으로 선택하는 방식입니다.",
"prefs.sketch_state_icons": "스케치 아이콘을 상태 색상으로 표시",
"prefs.sketch_state_icons_note": "이력과 브라우저에서 스케치 아이콘이 상태(구속 부족, 완전 구속, 충돌)의 색상을 띠고 도구 설명에 상태가 표시됩니다. 끄기: 모든 스케치가 같은 아이콘을 사용합니다.",
"prefs.sketch_tab_always": "스케치 탭 항상 표시",
"prefs.sketch_tab_always_note": "스케치가 열려 있지 않을 때도 스케치 탭이 리본에서 모델 바로 다음에 남아 있습니다. 그 그리기 도구는 선택한 평면이나 면, 또는 다음에 고르는 평면에서 스케치를 시작하고 그 안에서 도구를 바로 쓸 수 있게 합니다.",
"prefs.sketch_tracking_guides": "중심 및 중점 정렬 안내선",
@@ -1567,6 +1617,8 @@
"prefs.source": "소스",
"prefs.speed": "속도",
"prefs.stand_up_note": "STEP 또는 IGES 파일이 Z가 위쪽인 상태로 열린 후 X축 기준 90도 회전을 제안합니다.",
"prefs.status_bar": "상태 표시줄",
"prefs.status_bar_note": "창 아래쪽 가장자리의 얇은 표시줄에 편집 중인 항목, 열려 있는 스케치의 상태(해당 색상으로), 설계 단위가 표시됩니다. 단위를 클릭하면 변경할 수 있습니다. 스케치 상태는 더 이상 뷰 모서리에 표시되지 않습니다.",
"prefs.status_done": "완료",
"prefs.status_error": "오류",
"prefs.status_selected": "선택됨",
@@ -1583,6 +1635,7 @@
"prefs.timeline_half_hour": "−30분",
"prefs.timeline_now": "지금",
"prefs.timeline_quarter_hour": "−15",
"prefs.toast_place": "알림",
"prefs.toggle_item": "항목을 추가하거나 다시 제거",
"prefs.toolbar": "도구 모음",
"prefs.top": "위쪽",
@@ -1608,7 +1661,47 @@
"recovery.never_saved": "저장된 적 없음",
"render.add_ground": "Add fitted ground to setup",
"render.all_shots_label": "모든 샷",
"render.appearance_editor.absorption": "흡수",
"render.appearance_editor.base_colour": "기본 색상",
"render.appearance_editor.body_reason": "광학 바인딩은 하나의 전체 바디를 대상으로 합니다. 편집하려면 바디를 선택하세요.",
"render.appearance_editor.boundary": "경계",
"render.appearance_editor.box": "상자",
"render.appearance_editor.choose_image": "이미지 선택…",
"render.appearance_editor.closed": "닫힌 솔리드",
"render.appearance_editor.coat": "클리어 코트",
"render.appearance_editor.cpu_reason": "CPU 광선 추적이 필요합니다.",
"render.appearance_editor.glass": "유리와 흡수",
"render.appearance_editor.glass_enable": "이 바디에 물리 유리 사용",
"render.appearance_editor.glass_note": "닫힌 유리는 형상 거리를 사용합니다. 같은 바디에 클리어 코트나 맵을 함께 사용할 수 없습니다.",
"render.appearance_editor.gpu_reason": "GPU 경로 추적이 필요합니다.",
"render.appearance_editor.ior": "IOR",
"render.appearance_editor.maps": "맵",
"render.appearance_editor.normal": "노멀",
"render.appearance_editor.normal_strength": "노멀 강도",
"render.appearance_editor.origin": "원점",
"render.appearance_editor.recipe": "레시피",
"render.appearance_editor.reflection_sampling": "모든 반사 바디의 샘플링",
"render.appearance_editor.reflections": "반사",
"render.appearance_editor.remove": "저장된 설정 제거",
"render.appearance_editor.remove_note": "이 샷에서 저장된 광학 설정을 제거합니다. 형상과 지정된 외관은 유지됩니다.",
"render.appearance_editor.remove_title": "저장된 광학 설정을 제거할까요?",
"render.appearance_editor.replace": "이 바디의 저장된 광학 설정 교체",
"render.appearance_editor.revalidate": "이 바디 다시 검증",
"render.appearance_editor.save": "이 광학 설정 저장",
"render.appearance_editor.save_reason": "저장하려면 현재 GPU 바디에 물리 유리가 필요합니다. 코트와 로컬 이미지 맵은 임시로 유지됩니다.",
"render.appearance_editor.saved": "이 샷에 저장됨",
"render.appearance_editor.saved_state": "이 광학 설정은 이 샷과 함께 저장되어 있습니다.",
"render.appearance_editor.scatter_reason": "내부 산란에는 닫힌 솔리드 경계가 필요합니다.",
"render.appearance_editor.temporary": "이 광학 설정은 이 탭에서 임시로 사용됩니다. 샷과 함께 유지하려면 저장하세요.",
"render.appearance_editor.thickness": "두께",
"render.appearance_editor.thickness_reason": "두께는 얇은 시트에 적용됩니다. 닫힌 유리는 형상 거리를 사용합니다.",
"render.appearance_editor.thin": "얇은 시트",
"render.appearance_editor.u_repeat": "U 반복",
"render.appearance_editor.v_repeat": "V 반복",
"render.appearance_editor.v_up": "텍스처 V가 위쪽을 향함",
"render.appearance_editor.weight": "가중치",
"render.appearances": "외관",
"render.assign_help": "클릭하여 선택 항목에 적용하거나 드래그하여 미리 보고 놓으세요. 선택이 없으면 칠하기를 시작합니다.",
"render.background": "장면 배경",
"render.bloom_enable": "표시 블룸",
"render.bloom_help": "양의 선형 하이라이트를 세 번의 정규화 필터로 확산하는 출력 전용 효과입니다. 반경은 출력 픽셀 단위이며 sRGB 전에 더합니다. 렌즈·볼륨·수렴 개선이 아니며 원본 EXR은 변하지 않습니다.",
@@ -1616,10 +1709,90 @@
"render.bloom_radius": "블룸 반경",
"render.bloom_strength": "블룸 강도",
"render.bloom_threshold": "선형 하이라이트 임계값",
"render.browse_looks": "찾아보기…",
"render.category_metal": "금속",
"render.category_paint": "페인트",
"render.category_plastic": "플라스틱",
"render.category_wood": "목재",
"render.check_opaque": "투명도: 불투명 표면만 지원하며 배경 알파를 지원합니다.",
"render.check_sorted_alpha": "투명도: 정렬된 알파 근사.",
"render.check_transmission": "투명도: 물리적 투과.",
"render.children.absolute_floor": "절대 하한",
"render.children.adaptive": "적응형",
"render.children.add_look_reason": "활성 상태와 강도를 편집하려면 룩을 추가하세요.",
"render.children.all_shots": "모든 샷",
"render.children.bloom": "블룸",
"render.children.check": "검사",
"render.children.check_now": "지금 검사",
"render.children.chromatic": "색수차",
"render.children.compact": "소형",
"render.children.contrast": "대비",
"render.children.copy_image": "복사",
"render.children.copy_job": "작업 JSON 복사",
"render.children.copy_request": "요청 JSON 복사",
"render.children.coverage_error": "커버리지 오차",
"render.children.cpu": "CPU 레이 트레이싱",
"render.children.denoise": "완성 이미지의 노이즈 줄이기",
"render.children.depth": "경로 깊이",
"render.children.distortion": "왜곡",
"render.children.edge_samples": "모서리 샘플",
"render.children.effects_banner": "이 효과에는 GPU 경로 추적이 필요합니다. 열어도 방식은 바뀌지 않습니다.",
"render.children.enable_adaptive": "적응형 한도를 편집하려면 독립 파일럿을 활성화하세요.",
"render.children.enable_bloom": "강도, 임계값, 반경을 편집하려면 블룸을 활성화하세요.",
"render.children.finishing": "마무리",
"render.children.flare": "플레어",
"render.children.fresnel": "프레넬 계층",
"render.children.ghosts": "고스트 링",
"render.children.glass": "유리 광 전송",
"render.children.go_to": "{editor}(으)로 이동",
"render.children.grain": "입자",
"render.children.halo": "후광",
"render.children.hdr": "HDR",
"render.children.keep_master": "원시 선형 마스터 유지",
"render.children.last_result": "최근: {number} · {width} × {height} · {phase}",
"render.children.lens_effects": "렌즈 효과",
"render.children.look_summary": "{tone} · 룩 {count}개",
"render.children.looks": "크리에이티브 룩",
"render.children.memory": "메모리",
"render.children.method": "방식",
"render.children.minimum": "최소값",
"render.children.needs_cpu": "CPU 레이 트레이싱이 필요합니다. 열어도 방식은 바뀌지 않습니다.",
"render.children.nested": "인증된 중첩 유전체",
"render.children.not_checked": "검사 안 됨",
"render.children.path": "경로 추적",
"render.children.pilots": "파일럿 샘플",
"render.children.preview": "미리보기 데이터",
"render.children.progressive_reason": "샘플 수와 시드를 편집하려면 점진적 모드를 선택하세요.",
"render.children.radius": "반경",
"render.children.reflect_depth": "반사 깊이",
"render.children.reflect_samples": "반사 샘플",
"render.children.regrade": "다시 그레이딩",
"render.children.relative_error": "상대 오차",
"render.children.render": "렌더링",
"render.children.render_shot": "샷 렌더링",
"render.children.renderer": "렌더러",
"render.children.renderers": "렌더러",
"render.children.request": "이 요청",
"render.children.reset_finishing": "마무리 초기화",
"render.children.review_quality": "품질 사양 검토…",
"render.children.rgb_gain": "RGB 게인",
"render.children.samples": "샘플",
"render.children.sampling": "샘플링",
"render.children.saturation": "채도",
"render.children.scene_summary": "바디 {bodies}개 · 삼각형 {triangles}개",
"render.children.seed": "시드",
"render.children.sharpening": "선명도",
"render.children.single_image": "단일 이미지",
"render.children.soft_focus": "소프트 포커스",
"render.children.streak": "광선",
"render.children.strength": "강도",
"render.children.studio": "스튜디오",
"render.children.threshold": "임계값",
"render.children.tone": "톤",
"render.children.under_hood": "내부 정보",
"render.children.vignette": "비네트",
"render.children.workstation": "워크스테이션",
"render.choose_look": "먼저 외관 라이브러리에서 외관을 선택하세요",
"render.clear_stage": "Remove saved stage",
"render.cpu_budget": "CPU 리소스 프로필",
"render.cpu_budget_bodies": "바디 수 상한",
@@ -1632,7 +1805,88 @@
"render.cpu_budget_studio": "스튜디오 (큰 이미지)",
"render.cpu_budget_triangles": "삼각형 수 상한",
"render.cpu_budget_workstation": "워크스테이션 (대규모 장면)",
"render.effects_gpu_only": "이 효과를 사용하려면 GPU 경로 추적이 필요합니다. 페이지를 바꿔도 렌더러는 자동으로 전환되지 않습니다.",
"render.emitted_axis": "방출 축",
"render.env_advanced": "고급",
"render.env_backdrop": "배경",
"render.env_backdrop_pending": "렌더러가 환경 배경 표시와 흐림을 아직 지원하지 않습니다.",
"render.env_blur": "흐림",
"render.env_change": "변경",
"render.env_choose_source": "조명을 편집하기 전에 스튜디오 및 환경에서 환경을 선택하세요.",
"render.env_clear": "투명",
"render.env_colour": "색상",
"render.env_environments": "환경",
"render.env_ground": "지면",
"render.env_ground_pending": "물리적 지면은 유한한 확산 표면으로 그림자를 받습니다. 그림자만 포착하거나 지면에 반사하는 기능은 아직 지원하지 않습니다.",
"render.env_intensity": "강도",
"render.env_invalid_edit": "환경 편집 내용이 올바르지 않습니다.",
"render.env_physical_ground": "물리적 지면",
"render.env_preview_help": "구 예시이며 선택한 환경의 미리보기가 아닙니다.",
"render.env_reflection": "반사",
"render.env_ring_help": "링을 드래그하여 조명을 회전하세요. Shift를 누르면 15° 간격으로 스냅합니다.",
"render.env_rotate": "회전",
"render.env_set": "렌더 환경 설정",
"render.env_shadow_catcher": "그림자 포착",
"render.env_show_environment": "환경 표시",
"render.env_source": "소스",
"render.env_stage_details": "지면 편집에는 레이 트레이싱과 단일 지면 패널이 필요합니다. 다른 무대 패널은 장면에서 편집하세요.",
"render.env_studios": "스튜디오",
"render.environment.albedo": "알베도",
"render.environment.atmosphere": "대기",
"render.environment.backdrop_note": "배경은 카메라에만 보이며 조명, 그림자, 반사에 영향을 주지 않습니다. 투명 출력과 함께 사용할 수 없습니다.",
"render.environment.blur_pending": "흐림을 사용할 수 없습니다. 렌더러에 배경 흐림 설정이 없습니다.",
"render.environment.builtin": "내장 HDR",
"render.environment.check": "파일 확인",
"render.environment.checked": "HDR 파일을 확인했습니다. 저장하면 이 데이터가 포함됩니다.",
"render.environment.choose": "HDR 선택…",
"render.environment.constant": "상수",
"render.environment.cyclorama": "사이클로라마",
"render.environment.embedded": "이 디자인 안에 저장됨",
"render.environment.end": "끝",
"render.environment.extinction": "소광 계수",
"render.environment.file": "파일",
"render.environment.fit": "지면 맞춤 및 저장",
"render.environment.floor_wall": "바닥과 벽",
"render.environment.gap": "간격",
"render.environment.gradient": "그라데이션",
"render.environment.gradient_gpu": "그라데이션 배경에는 GPU 경로 추적이 필요합니다.",
"render.environment.ground": "지면과 스테이지",
"render.environment.hdr": "HDR",
"render.environment.hdr_file": "HDR 파일",
"render.environment.horizon": "수평선",
"render.environment.horizontal": "수평",
"render.environment.keep": "유지",
"render.environment.lighting_samples": "조명 샘플",
"render.environment.margin": "범위 여백",
"render.environment.max": "최대 경계",
"render.environment.medium": "참여 매질",
"render.environment.min": "최소 경계",
"render.environment.mode": "모드",
"render.environment.needs_gpu": "GPU 경로 추적이 필요합니다.",
"render.environment.none": "없음",
"render.environment.orientation": "방향과 강도",
"render.environment.phase": "위상",
"render.environment.primaries": "지정되지 않은 원색을 선형 sRGB로 처리",
"render.environment.primaries_gpu": "지정되지 않은 원색 해석에는 GPU 경로 추적이 필요합니다.",
"render.environment.radial": "방사형",
"render.environment.radial_only": "중심과 반경은 방사형 모드에 적용됩니다.",
"render.environment.reflectance": "반사율",
"render.environment.remove": "스테이지 제거",
"render.environment.remove_confirm": "저장된 스테이지를 제거할까요?",
"render.environment.remove_note": "이 샷에서 패시브 패널 {count}개를 제거합니다. 카메라 배경은 유지됩니다.",
"render.environment.replace": "기존 스테이지 교체 확인",
"render.environment.rotation_hdr": "CPU 광선 추적의 회전에는 HDR 광원이 필요합니다.",
"render.environment.samples_cpu": "GPU 조명 샘플은 경로 예산으로 정해집니다. 이 설정에는 CPU 광선 추적이 필요합니다.",
"render.environment.saved_panels": "저장된 패널 {count}",
"render.environment.sky_ground": "지면",
"render.environment.sky_note": "조명용 오리지널 하늘 그라데이션이며 보정된 대기 모델은 아닙니다.",
"render.environment.source_raytrace": "환경 광원에는 CPU 또는 GPU 광선 추적이 필요합니다.",
"render.environment.stage_raytrace": "물리 스테이지에는 CPU 또는 GPU 광선 추적이 필요합니다.",
"render.environment.start": "시작",
"render.environment.vertical": "수직",
"render.environment.world": "월드",
"render.environment.world_pending": "월드 배경을 사용할 수 없습니다. 환경의 카메라 표시를 저장하는 설정이 아직 없습니다.",
"render.environment.zenith": "천정",
"render.environment_tiles_require_raytrace": "환경에는 CPU 또는 GPU 광선 추적이 필요합니다. 출력 편집기에서 선택하세요.",
"render.error_area_samples": "area_samples는 1, 4, 16 또는 64여야 함",
"render.error_binding_allocation": "재질 연결을 할당할 수 없음",
@@ -1697,14 +1951,40 @@
"render.fixed_camera": "카메라",
"render.fixed_world": "월드",
"render.fold_browser": "브라우저 접기",
"render.frame_aspect": "화면 비율",
"render.frame_centre_mark": "중심 표시",
"render.frame_copy_limit": "사용 가능한 복제 샷 이름이 없습니다",
"render.frame_copy_name": "{name} 복사본 {number}",
"render.frame_custom": "사용자 지정",
"render.frame_distance_unit": " × 크기",
"render.frame_duplicate": "복제",
"render.frame_exposure": "노출",
"render.frame_fov": "시야각",
"render.frame_guides": "가이드",
"render.frame_invalid_aspect": "잘못된 화면 비율 프리셋",
"render.frame_lens": "시야각 {fov}° · 약 {mm} mm",
"render.frame_name": "이름",
"render.frame_output_size": "출력 크기",
"render.frame_photo": "3:2 · 사진",
"render.frame_portrait": "4:5 · 세로",
"render.frame_presets": "구도 프리셋",
"render.frame_presets_pending": "샷 편집기와 함께 제공 예정",
"render.frame_projection": "투영",
"render.frame_render_shot": "이 샷 렌더링",
"render.frame_rule_thirds": "삼분할 법칙",
"render.frame_safe_area": "안전 영역",
"render.frame_shot_title": "샷 · {name}",
"render.frame_square": "1:1 · 정사각형",
"render.frame_tall": "9:16 · 세로형",
"render.frame_thirds": "삼분할선",
"render.frame_wide": "16:9 · 와이드스크린",
"render.heading_batch": "일괄 처리",
"render.heading_frame": "프레임",
"render.heading_lens": "렌즈",
"render.heading_results": "결과",
"render.heading_shots": "샷",
"render.hide_shots_label": "샷 스트립 숨기기",
"render.hover_look": "{object} · {look} · 클릭하여 선택",
"render.image_cancelled": "렌더링 취소됨",
"render.image_cancelling": "취소 중",
"render.image_completed": "이미지 내보내기 준비됨",
@@ -1730,6 +2010,36 @@
"render.include_rig_cards": "Include passive cards and flags",
"render.inner_half_angle": "내부 반각",
"render.inspector": "속성 검사기",
"render.inspector_advanced": "고급",
"render.inspector_all_users": "사용 대상 {count}개 모두",
"render.inspector_applies_to": "적용 범위",
"render.inspector_both_users": "두 사용 대상",
"render.inspector_chain": "외관 출처",
"render.inspector_colour": "색상",
"render.inspector_edit": "편집",
"render.inspector_finish": "마감",
"render.inspector_from_material": "재질에서 상속",
"render.inspector_gloss": "유광",
"render.inspector_material": "재질",
"render.inspector_matte": "무광",
"render.inspector_metal": "금속",
"render.inspector_opacity": "불투명도",
"render.inspector_opaque_help": "마감 및 광학 필드는 불투명 PBR(불투명도 1)을 사용합니다. 불투명도를 낮추면 스칼라 음영을 사용합니다.",
"render.inspector_pick_target": "이 유형의 대상을 선택하여 외관을 확인하세요.",
"render.inspector_remove": "재정의 제거",
"render.inspector_replace": "바꾸기…",
"render.inspector_reset": "초기화",
"render.inspector_satin": "반광",
"render.inspector_save_library": "라이브러리에 저장…",
"render.inspector_set_all": "외관이 혼합되어 있습니다. 편집하면 선택한 모든 대상에 외관을 설정합니다.",
"render.inspector_soon": "출시 예정",
"render.inspector_target_limit": "외관을 확인할 대상을 10000개 이하로 선택하세요.",
"render.inspector_textures": "텍스처",
"render.inspector_this_body": "이 바디",
"render.inspector_this_component": "이 구성요소",
"render.inspector_this_face": "이 면",
"render.inspector_this_target": "이 대상",
"render.inspector_used_by": "사용 대상 {count}개",
"render.layer_off_suffix": " (꺼짐)",
"render.library_appearance_available": "사용 가능한 외관",
"render.library_applicable": "적용 가능한 리소스",
@@ -1781,8 +2091,86 @@
"render.library_title": "렌더 리소스 라이브러리",
"render.library_uniform_ack": "공간 변화나 고급 효과 없는 균일 근사 사용",
"render.library_users": "사용 위치",
"render.light_aim": "조준 대상",
"render.light_anchor_pending": "조명 좌표계 변경은 아직 지원되지 않습니다.",
"render.light_azimuth": "방위각",
"render.light_backend_limit": "조명을 편집하려면 CPU 레이 트레이싱이나 명시적인 GPU 스튜디오를 선택하세요. 기존 GPU 스튜디오 조명은 읽기 전용입니다.",
"render.light_behaviour": "동작",
"render.light_default_fill": "필 라이트",
"render.light_default_key": "키 라이트",
"render.light_default_number": "조명 {number}",
"render.light_default_rim": "림 라이트",
"render.light_delete": "삭제",
"render.light_distance": "거리",
"render.light_duplicate": "복제",
"render.light_elevation": "고도각",
"render.light_gpu_punctual": "포인트와 스폿 조명은 CPU 레이 트레이싱에서 사용할 수 있습니다.",
"render.light_hard_shadow": "이 조명은 단단한 그림자만 지원합니다.",
"render.light_intensity": "강도",
"render.light_missing": "이 조명이 더 이상 없습니다. 브라우저에서 조명을 선택하세요.",
"render.light_place_highlight": "하이라이트로 배치",
"render.light_place_pending": "하이라이트 배치는 뷰포트 조명 선택이 필요하며 아직 지원되지 않습니다.",
"render.light_position": "위치",
"render.light_preview_help": "라이브 뷰에는 그림자가 없으며 영역 조명은 중심 샘플로 근사됩니다. 렌더는 전체 조명 모델을 사용합니다.",
"render.light_product_centre": "제품 중심",
"render.light_size": "크기",
"render.light_softness": "부드러움",
"render.light_temperature": "색온도",
"render.light_temperature_help": "흑체 색상 근사값이며 선형 RGB로 저장됩니다.",
"render.light_type": "유형",
"render.light_type_area": "영역",
"render.light_type_point": "포인트",
"render.light_type_spot": "스폿",
"render.light_type_sun": "태양",
"render.light_view_only": "솔로와 음소거는 이 뷰와 렌더에만 적용되며 디자인에 저장되지 않습니다.",
"render.light_world_origin": "월드 원점",
"render.lighting_aim_point": "조준점",
"render.lighting_apply": "프리셋 적용",
"render.lighting_area_samples": "영역 샘플",
"render.lighting_budget": "한도",
"render.lighting_budget_help": "개수는 읽기 전용입니다. 조명을 추가, 복제 또는 삭제하세요. 한도는 방식에 따라 정해집니다.",
"render.lighting_colour": "색상",
"render.lighting_consent": "이 프리셋으로 방향 조명 교체",
"render.lighting_custom": "사용자 조명",
"render.lighting_custom_help": "사용자 조명을 선택하면 프리셋이 트리의 각 행에서 편집 가능한 조명으로 변환됩니다.",
"render.lighting_direction": "방향 X Y Z",
"render.lighting_direction_help": "또는 조명 방향을 입력하세요 (X Y Z).",
"render.lighting_distance_unit": " × 크기",
"render.lighting_edge_u": "변 U 벡터",
"render.lighting_edge_v": "변 V 벡터",
"render.lighting_falloff": "감쇠",
"render.lighting_falloff_help": "강도는 기준 거리에서의 값입니다.",
"render.lighting_height": "높이 V",
"render.lighting_minimum": "최솟값",
"render.lighting_mute": "이 조명 끄기",
"render.lighting_point": "점",
"render.lighting_preset": "스튜디오 프리셋",
"render.lighting_preset_cpu": "방향 조명 프리셋에는 CPU 레이 트레이싱이 필요합니다. GPU는 명시적 태양 및 영역 조명을 사용합니다.",
"render.lighting_preset_row": "프리셋",
"render.lighting_radiance": "복사휘도",
"render.lighting_reference": "기준",
"render.lighting_review_help": "방향 조명 목록을 교체합니다. 점 및 영역 조명, 환경, 그림자, 카메라와 다른 샷 설정은 유지합니다.",
"render.lighting_review_title": "조명 프리셋 검토",
"render.lighting_samples_cpu": "영역 조명 샘플은 CPU 레이 트레이싱에 적용됩니다.",
"render.lighting_samples_need_area": "영역 샘플을 설정하려면 CPU 영역 조명을 추가하세요.",
"render.lighting_samples_reason": "영역 샘플은 1, 4, 16 또는 64여야 합니다.",
"render.lighting_shadow_cpu": "그림자 스위치에는 CPU 레이 트레이싱이 필요합니다. GPU 경로 추적은 항상 그림자를 계산합니다.",
"render.lighting_shadows": "그림자 투사",
"render.lighting_shadows_section": "그림자 및 샘플링",
"render.lighting_shape": "모양",
"render.lighting_solo": "이 조명만 표시",
"render.lighting_source": "광원",
"render.lighting_source_section": "광원",
"render.lighting_spot_preserved": "이 점 조명은 유형을 변경할 때까지 저장된 스폿 원뿔을 유지합니다.",
"render.lighting_sun_distance": "태양 방향은 거리 및 조준점과 무관합니다.",
"render.lighting_unsupported": "지원되지 않음",
"render.lighting_used": "{used} / {limit}",
"render.lighting_width": "너비 U",
"render.lighting_world_position": "월드 X Y Z",
"render.lights_fixed_to": "조명 고정 기준",
"render.look_applied": "{name} 적용됨",
"render.look_material": "재질",
"render.look_pasted": "외관 붙여넣음",
"render.material_color_replace": "기본 맵으로 바디 색상 교체",
"render.material_limits": "최대 128개 바디 설정, 분리된 유리 32개, 코팅 64개, 텍스처 연결 128개. 같은 맵은 메모리를 공유하며 실제 장치 및 전체 메모리 제한은 유지됩니다.",
"render.material_metallic_map": "금속성 맵 (선형)",
@@ -1792,9 +2180,37 @@
"render.opaque_image_summary": "미리보기 PNG · 불투명 PBR · 블렌딩 투명도",
"render.opaque_preview_help": "불투명 PBR 및 단색 표시, 블렌딩 투명도를 지원합니다. 굴절, HDRI 및 최종 렌더링은 아직 지원하지 않습니다.",
"render.outer_half_angle": "외부 반각",
"render.output_advanced": "고급",
"render.output_backend_ready": "준비 완료",
"render.output_check": "확인",
"render.output_check_failed": "검사 · 오류",
"render.output_check_help": "확인을 실행하면 렌더링을 시작하지 않고 요청을 검토합니다.",
"render.output_check_summary": "검사 · 참고 {count}개",
"render.output_copy": "복사",
"render.output_copy_report": "보고서 복사",
"render.output_destination": "저장 위치",
"render.output_destination_help": "완성된 이미지를 내보낼 때 대상 파일을 선택합니다.",
"render.output_dimensions": "크기",
"render.output_effects": "효과",
"render.output_export": "PNG 내보내기…",
"render.output_exr_unavailable": "여기서는 EXR 출력을 설정할 수 없습니다. 선형 EXR 내보내기에는 선형 원본을 보관한 완료된 GPU 이미지가 필요합니다.",
"render.output_fit": "맞춤",
"render.output_format": "형식",
"render.output_format_status": "PNG는 완료된 표시 이미지 그대로입니다. 선택적 GPU EXR은 표시 필터 전 선형 FLOAT32 방사 휘도를 보존합니다. 미리보기 캐시나 다른 작업으로 바꾸어 내보내지 않습니다.",
"render.output_grading": "색 보정",
"render.output_image": "이미지",
"render.output_largest": "{width} × {height} 최대",
"render.output_presets_help": "형식, 품질 및 검사 목록은 출력 편집기에 있습니다.",
"render.output_quality": "품질",
"render.output_quality_waiting": "품질 규약 대기 중",
"render.output_ready": "렌더링 준비 완료",
"render.output_run_check": "검사 실행",
"render.output_size_limit": "{method}: 한 변 최대 {dimension} px, 총 {pixels} 픽셀. 가능한 최대 크기: {width} × {height}.",
"render.output_size_ok": "크기 정상 · {width} × {height} px",
"render.output_tools_inspector": "출력 검사기에서 크기와 형식을 편집하세요.",
"render.output_view_image": "이미지 보기",
"render.paint_label": "칠하기",
"render.painting_with": "{name}(으)로 칠하는 중",
"render.passive_stage": "Render-only stage",
"render.passive_stage_help": "Finite passive panels belong only to rendered images. They do not add CAD bodies or mass. Placement is fixed after applying; intersecting product bounds refuse. CPU does not provide diffuse bounce lighting.",
"render.perspective": "원근 카메라",
@@ -1813,6 +2229,7 @@
"render.pick_help": "바디, 면 또는 구성요소를 선택합니다. 빈 공간을 클릭하면 선택이 해제되고 Shift 또는 Ctrl로 추가하거나 전환합니다. 강조 표시는 실시간 제품 뷰에만 나타납니다.",
"render.pick_label": "선택",
"render.pick_up_label": "가져오기",
"render.pick_up_prompt": "외관을 가져올 객체를 클릭하세요",
"render.pick_waiting": "제품 선택은 아직 지원되지 않습니다.",
"render.preview": "통합 미리보기",
"render.preview_help": "래스터 셰이딩과 블렌딩 투명도를 사용합니다. 굴절, HDRI 및 최종 렌더링은 아직 지원하지 않습니다.",
@@ -1823,11 +2240,24 @@
"render.property_source": "출처: {id} - {locator}",
"render.property_uncertainty": "불확도: {value}",
"render.property_unknown": "알 수 없음",
"render.quality_balanced": "균형",
"render.quality_custom": "사용자 지정",
"render.quality_draft": "초안",
"render.quality_high": "높음",
"render.radial_assign": "외관 지정",
"render.radial_compare": "비교",
"render.radial_fit": "제품 맞추기",
"render.radial_save": "샷 저장",
"render.recent_looks": "최근 외관",
"render.regrade_label": "색상 재조정",
"render.reload_settings": "저장된 설정 다시 불러오기",
"render.remove_override": "재정의 제거",
"render.replace_all": "모두 바꾸기",
"render.replace_label": "바꾸기",
"render.replace_saved_surface": "Replace an existing saved binding for this target",
"render.replace_with": "바꿀 외관",
"render.restore_camera": "저장된 카메라 복원",
"render.result_actual": "100%",
"render.result_actual_size": "100%",
"render.result_reduced_display": "표시 미리보기를 뷰포트 장치 또는 캐시 제한에 맞춰 축소했습니다. 보관된 PNG와 내보내기는 전체 해상도를 유지합니다. 이 축소 보기에서는 원본 100% 검사가 불가능합니다.",
"render.return_design": "설계로 돌아가기",
@@ -1858,11 +2288,43 @@
"render.saved_surface_remove": "Remove saved binding",
"render.saved_surfaces": "Saved surface bindings",
"render.saved_surfaces_help": "Pinned built-in maps follow the selected occurrence in local millimeters. A replaced or missing target is an error, never an automatic reassignment.",
"render.scene_all_shots": "모든 샷 ({count})",
"render.scene_batch_reason": "모든 샷에는 아직 지원되지 않는 저장된 샷 렌더링 대기열이 필요합니다.",
"render.scene_check_now": "지금 검사",
"render.scene_check_passed": "검사 통과 · 참고 {notes}개",
"render.scene_check_stale": "검사가 오래됨 · 다시 검사",
"render.scene_check_unchecked": "아직 검사하지 않음 · 참고 0개",
"render.scene_light_summary": "{environment} · 조명 {lights}개",
"render.scene_look_summary": "외관 {looks}개 · 재정의 {overrides}개",
"render.scene_open_check": "검사 열기",
"render.scene_ready": "렌더링 준비",
"render.scene_reminder": "장면은 설계를 보존합니다. 렌더링에서 형상, 엔지니어링 속성 및 CAD는 변경되지 않습니다.",
"render.scene_reminders": "알림",
"render.scene_renderer_ready": "{renderer} 준비됨",
"render.scene_stages": "단계",
"render.search_appearances": "외관 {count}개 검색",
"render.setup_name": "설정 이름",
"render.shell_tab_appearance": "모양",
"render.shell_tab_camera": "카메라",
"render.shell_tab_scene": "장면",
"render.shot_aperture": "조리개",
"render.shot_distance": "거리",
"render.shot_dof": "피사계 심도",
"render.shot_edit_output": "출력에서 편집",
"render.shot_exposure_reason": "노출에는 CPU 광선 추적 또는 GPU 경로 추적이 필요합니다.",
"render.shot_exposure_section": "노출",
"render.shot_focus_distance": "초점 거리",
"render.shot_fov_reason": "시야각에는 원근 투영이 필요합니다.",
"render.shot_frame_subject": "피사체 맞추기",
"render.shot_invalid_camera": "카메라 값은 범위 내의 유한한 수여야 합니다.",
"render.shot_lens": "렌즈",
"render.shot_lens_enable_reason": "조리개와 초점 거리를 편집하려면 피사계 심도를 켜세요.",
"render.shot_lens_gpu_reason": "피사계 심도에는 GPU 경로 추적이 필요합니다.",
"render.shot_lens_perspective_reason": "피사계 심도에는 원근 투영이 필요합니다.",
"render.shot_look_selection": "선택 항목 바라보기",
"render.shot_selection_reason": "바라볼 바디나 면을 선택하세요.",
"render.shot_size": "크기",
"render.shot_target": "대상",
"render.shots_camera_changed": "이 샷을 저장한 후 카메라가 변경되었습니다",
"render.shots_name_help": "현재 샷의 고유한 이름을 입력하세요.",
"render.shots_no_result": "렌더링 결과 없음",
@@ -1871,19 +2333,114 @@
"render.shots_save": "샷 저장",
"render.shots_update": "샷 업데이트",
"render.show_shots_label": "샷 스트립 표시",
"render.size_4k": "4K",
"render.size_4k_uhd": "4K UHD",
"render.size_custom": "사용자 지정…",
"render.size_full_hd": "풀 HD",
"render.size_hd": "HD",
"render.size_presets": "크기 프리셋",
"render.size_presets_pending": "출력 편집기와 함께 제공 예정",
"render.size_preview": "미리보기",
"render.size_square": "정사각형",
"render.spot_cone": "스폿 원뿔",
"render.stage_frame": "구도",
"render.stage_layout.appearance_note": "클릭하여 선택 항목에 적용합니다.",
"render.stage_layout.studio_note": "클릭하여 적용 전에 검토하세요.",
"render.stage_light": "조명",
"render.stage_look": "외관",
"render.stage_orthographic": "직교 투영",
"render.stage_output": "출력",
"render.stage_panel_count": "Saved panels",
"render.stage_panels.acknowledge": "교체 내용과 제한 사항을 확인했습니다",
"render.stage_panels.appearance_note": "클릭하여 선택 항목에 적용합니다. 모델로 끌어 놓으세요. 선택 항목이 없으면 클릭하여 페인트를 시작합니다.",
"render.stage_panels.apply": "적용",
"render.stage_panels.apply_studio": "스튜디오 적용",
"render.stage_panels.badge_blocked": "차단됨",
"render.stage_panels.badge_native": "네이티브",
"render.stage_panels.badge_projection": "투영",
"render.stage_panels.badge_reference": "참조",
"render.stage_panels.badge_specification": "사양만",
"render.stage_panels.candidate_summary": "후보: 출처가 있는 값 {count}개. 등급과 마감 검토가 필요합니다.",
"render.stage_panels.captured_bounds": "캡처한 장면 경계 사용",
"render.stage_panels.centre": "중심",
"render.stage_panels.depth": "깊이",
"render.stage_panels.environments": "환경",
"render.stage_panels.extent": "크기",
"render.stage_panels.fit_save": "맞춤 및 저장",
"render.stage_panels.gpu_required": "GPU 경로 추적 필요",
"render.stage_panels.keep": "유지",
"render.stage_panels.kept": "유지",
"render.stage_panels.kept_fields": "카메라, 샘플링, 이미지 크기, 광학 바인딩, CAD 형상 및 공학 속성.",
"render.stage_panels.kept_quality": "방식, 카메라, 조명, 환경, 스테이지, 광학 설정, 노출 및 톤 매핑.",
"render.stage_panels.mine": "내 항목",
"render.stage_panels.mine_pending": "개인 스튜디오 저장은 아직 지원되지 않습니다.",
"render.stage_panels.omits": "생략",
"render.stage_panels.paint_pending": "페인트 및 끌어서 할당은 아직 지원되지 않습니다. 외관을 적용할 대상을 선택하세요.",
"render.stage_panels.partial_reference": "후보: 출처가 있는 값만 포함합니다. 등급, 상태 및 출처를 검토하세요. 알 수 없는 값은 그대로 유지됩니다.",
"render.stage_panels.plane": "평면",
"render.stage_panels.prepare_plan": "생성 계획 준비",
"render.stage_panels.projects": "투영",
"render.stage_panels.quality_ack": "고정 예산과 생략 사항을 확인했습니다",
"render.stage_panels.quality_omissions": "적응형 중지 및 오차 목표, 별도 투과 깊이, 러시안 룰렛 규칙, 원시 선형 출력, EXR 마스터 및 수렴 인증.",
"render.stage_panels.reference": "참조",
"render.stage_panels.references": "참조",
"render.stage_panels.remove_optics": "광학 설정 제거",
"render.stage_panels.remove_optics_help": "이 샷에 저장된 광학 설정을 제거합니다. 원본 형상은 유지됩니다.",
"render.stage_panels.remove_optics_title": "저장된 광학 설정을 제거할까요?",
"render.stage_panels.remove_shot": "샷 제거",
"render.stage_panels.remove_stage": "스테이지 제거",
"render.stage_panels.remove_stage_help": "이 샷에 저장된 수동 패널을 제거합니다. 카메라 배경은 유지됩니다.",
"render.stage_panels.remove_stage_title": "저장된 스테이지를 제거할까요?",
"render.stage_panels.repeat": "반복",
"render.stage_panels.replaces": "교체",
"render.stage_panels.replaces_environment": "환경",
"render.stage_panels.replaces_maps": "선택한 바디의 임시 맵. 저장된 광학 설정과 충돌할 수 있습니다.",
"render.stage_panels.replaces_physical": "없음. 이 계획은 읽기 전용입니다.",
"render.stage_panels.replaces_quality": "이미지 크기, 고정 샘플 수, 경로 깊이, 시드 및 노이즈 제거.",
"render.stage_panels.replaces_rig": "조명, 환경 및 스테이지",
"render.stage_panels.replaces_saved_maps": "선택한 바디에 저장된 표면 맵. 임시 설정과 충돌할 수 있습니다.",
"render.stage_panels.replaces_stage": "저장된 바닥 및 수동 스테이지 패널",
"render.stage_panels.replaces_studio": "조명, 환경, 노출 및 스테이지",
"render.stage_panels.replaces_uniform": "선택한 바디의 불투명 외관. 공간 맵은 균일한 값으로 근사합니다.",
"render.stage_panels.review_environment": "환경 검토",
"render.stage_panels.review_maps": "GPU 맵 검토",
"render.stage_panels.review_physical": "물리 참조 계획",
"render.stage_panels.review_quality": "고정 샘플링 예산 사용",
"render.stage_panels.review_rig": "조명 리그 맞춤",
"render.stage_panels.review_saved_maps": "저장된 맵 검토",
"render.stage_panels.review_stage": "바닥 및 스테이지 검토",
"render.stage_panels.review_studio": "네이티브 스튜디오 검토",
"render.stage_panels.review_uniform": "균일한 외관 검토",
"render.stage_panels.rig_summary": "제작된 조명 리그 · 광원 {emitters}개, 카드 {cards}개",
"render.stage_panels.rigs": "리그",
"render.stage_panels.save_maps": "이 샷에 맵 저장",
"render.stage_panels.scope": "범위",
"render.stage_panels.search_studios": "스튜디오 검색",
"render.stage_panels.search_surfaces": "표면 및 참조 검색",
"render.stage_panels.source_note": "제작된 기본 색상 소스 맵. 측정된 재질이 아닙니다.",
"render.stage_panels.specifications": "사양 · 읽기 전용",
"render.stage_panels.studio_ack": "조명, 환경, 노출 및 스테이지 교체 확인",
"render.stage_panels.studio_note": "클릭하여 검토하세요. 확인 후에만 조명, 환경 및 스테이지를 교체합니다. 조명은 계속 편집할 수 있습니다.",
"render.stage_panels.studios": "스튜디오",
"render.stage_panels.subtitle_environment": "원본 HDR 환경 · 전체 장면",
"render.stage_panels.subtitle_maps": "제작된 공간 맵 · 임시 미리 보기",
"render.stage_panels.subtitle_physical": "읽기 전용 계획 · 재질 생성 또는 할당 없음",
"render.stage_panels.subtitle_quality": "고정 GPU 예산 · 향후 요구 사항 생략",
"render.stage_panels.subtitle_rig": "제작된 조명 리그 · 광원 및 수동 카드",
"render.stage_panels.subtitle_saved_maps": "제작된 맵 · 이 샷에 저장",
"render.stage_panels.subtitle_stage": "물리적 바닥 및 스테이지 · 제품에 맞춤",
"render.stage_panels.subtitle_studio": "네이티브 스튜디오 · 전체 장면에 적용",
"render.stage_panels.subtitle_uniform": "균일한 근사 · 측정된 재질이 아님",
"render.stage_panels.surfaces": "표면",
"render.stage_panels.surfaces_references": "표면 및 참조",
"render.stage_panels.target": "대상",
"render.stage_panels.use_budget": "이 예산 사용",
"render.stage_panels.use_maps": "GPU 맵 사용",
"render.stage_panels.use_uniform": "균일한 외관 사용",
"render.stage_preview_note": "통합 미리 보기 · 직접광",
"render.state_completed": "완료된 이미지",
"render.state_in_progress": "이미지 생성 중",
"render.state_model": "모델 미리보기",
"render.strip_label": "스트립",
"render.studio_tiles_require_gpu": "스튜디오에는 GPU 경로 추적이 필요합니다. 출력 편집기에서 GPU를 선택하세요.",
"render.studios_environments": "스튜디오 및 환경",
@@ -1926,12 +2483,20 @@
"render.unavailable_preview": "이 설정은 사용할 수 없는 미리보기 프로필을 요청합니다.",
"render.unsaved": "저장하지 않은 미리보기 변경 사항",
"render.use_preview": "통합 미리보기 사용",
"render.wait_add_light": "아직 지원되지 않음: 이름이 있는 조명 만들기",
"render.wait_batch": "아직 지원되지 않음: 저장된 샷 렌더 대기열",
"render.wait_compare": "아직 지원되지 않음: 보관된 이미지 비교",
"render.wait_paint": "아직 지원되지 않음: 제품 선택 및 모양 페인팅",
"render.wait_pick_up": "아직 지원되지 않음: 제품 선택 및 모양 샘플링",
"render.wait_replace": "아직 지원되지 않음: 모양이 사용된 모든 곳 바꾸기",
"render.wait_solo": "아직 지원되지 않음: 조명 표시 및 단독 표시 제어",
"render.wear_applies_to": "적용 대상",
"render.wear_layer_count": "레이어 {count}개",
"render.wear_layer_one": "레이어 {count}개",
"render.wear_layers": "레이어",
"render.wear_no_layers": "레이어 없음",
"render.wear_selected_layer": "선택한 레이어",
"render.wear_title": "마모",
"sample.bracket.about": "2 mm 판금 규칙을 적용한 베이스 플랜지, 에지 플랜지, 헴",
"sample.bracket.name": "판금 브래킷",
"sample.enclosure.about": "리프, 나사 보스, 레스트, 스냅핏이 있는 쉘 처리된 박스",
@@ -2027,6 +2592,10 @@
"sketch_text.path_hint": "텍스트가 따라갈 스케치 곡선: 여기를 클릭한 다음 곡선을 클릭",
"sketch_text.use_font_file": "글꼴 파일 {path} 사용",
"solid": "솔리드",
"status.editing": "{name} 편집 중",
"status.under_constrained": "구속 부족 (자유도 {count}개)",
"status.under_constrained_one": "구속 부족 (자유도 {count}개)",
"status.units_tip": "설계 단위입니다. 클릭하여 변경",
"the angle must be a number": "각도는 숫자여야 합니다",
"the curves must be in one sketch": "곡선은 하나의 스케치 안에 있어야 합니다",
"the direction must be an axis, a sketch line or a straight edge": "방향은 축, 스케치 선 또는 직선 모서리여야 합니다",
@@ -2055,7 +2624,9 @@
"timeline.move_to_group": "특성을 폴더로 이동",
"timeline.rename_group": "특성 폴더 이름 변경",
"timeline.reorder_many": "특성 순서 변경",
"timeline.suppress_features": "특성 비활성화",
"timeline.ungroup": "특성 폴더 제거",
"timeline.unsuppress_features": "특성 비활성화 해제",
"to the face": "면까지",
"to the next face": "다음 면까지",
"toolbar.customize_note": "{tab} 탭입니다. 명령을 선택하면 도구 모음에 해당 버튼이 추가됩니다. 패널의 드롭다운에서 행을 도구 모음으로 끌거나, 버튼을 도구 모음 밖으로 끌어 제거하거나, 드롭다운 행의 고정 핀을 사용할 수도 있습니다.",
@@ -2677,6 +3248,10 @@
"ui.history_marker_tip": "이력 마커: 드래그하여 모델을 되돌립니다. 새 피처는 여기에 추가됩니다",
"ui.history_names": "이름",
"ui.history_play": "끝까지 재생",
"ui.history_play_button_hide": "재생 버튼 숨기기",
"ui.history_play_button_show": "재생 버튼 표시",
"ui.history_play_finish_action": "기록을 재생하기 전에 현재 작업을 완료하세요",
"ui.history_play_roll_back": "재생하기 전에 기록 마커를 이전 단계로 이동하세요",
"ui.history_show_names": "이름 표시",
"ui.history_title": "기록",
"ui.history_toggle_names": "피처 이름 표시/숨기기",
@@ -2799,6 +3374,15 @@
"ui.plugins_skipped": "폴더 {count}개를 읽을 수 없습니다.",
"ui.plugins_version": "{version}",
"ui.point": "점",
"ui.point_cloud_auto_range": "범위 자동 설정",
"ui.point_cloud_color_by": "색상 기준",
"ui.point_cloud_file_colors": "파일 색상",
"ui.point_cloud_height_high": "최고 높이",
"ui.point_cloud_height_low": "최저 높이",
"ui.point_cloud_no_file_colors": "파일에 색상 정보가 없습니다",
"ui.point_cloud_single_color": "단색",
"ui.point_cloud_size": "점 크기",
"ui.point_cloud_units": "파일 단위",
"ui.point_under_the_cursor": "커서 아래의 점",
"ui.points": "점",
"ui.polygon": "다각형",
@@ -2842,6 +3426,8 @@
"ui.restore_defaults": "기본값 복원",
"ui.reverse_horizontal_pan_direction": "수평 이동 방향 반전",
"ui.reverse_horizontal_pan_tip": "두 손가락 수평 스크롤과 엄지 휠이 반대 방향으로 이동합니다",
"ui.reverse_trackpad_orbit_direction": "트랙패드 회전 방향 반전",
"ui.reverse_trackpad_orbit_tip": "Shift를 누른 채 두 손가락으로 스크롤하면 반대 방향으로 회전합니다",
"ui.reverse_vertical_pan_direction": "수직 이동 방향 반전",
"ui.reverse_vertical_pan_tip": "두 손가락 수직 스크롤이 반대 방향으로 이동합니다",
"ui.reverse_zoom_direction": "확대/축소 방향 반전",
@@ -2981,6 +3567,12 @@
"ui.view_angles_roll": "롤",
"ui.view_angles_yaw": "요",
"ui.view_centre": "뷰 중심",
"ui.viewport_status_clear": "{name} 끄기",
"ui.viewport_status_clear_hint": "{name} 끄기 · Esc",
"ui.viewport_status_key": "{name} 범례 표시",
"ui.viewport_status_minimum_radius": "최소 반지름",
"ui.viewport_status_pairs": "{count}쌍",
"ui.viewport_status_stripes": "줄무늬 {count}개",
"ui.viewport_theme_follow": "테마 따르기",
"ui.visual_shaded_hidden_edges": "음영 처리 및 숨겨진 모서리",
"ui.visual_shaded_with_edges": "음영 처리 및 모서리",
@@ -3046,5 +3638,6 @@
"use a positive nominal diameter and a pitch smaller than it": "양수인 호칭 지름과 그보다 작은 피치를 사용하세요",
"values must be finite numbers": "값은 유한한 숫자여야 합니다",
"values must be numbers or expressions": "값은 숫자 또는 식이어야 합니다",
"view.render_inspector": "렌더 검사기",
"↑ ↓ choose · Enter / Tab complete · Esc dismiss": "↑ ↓ 선택 · Enter / Tab 완성 · Esc 닫기"
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+9
View File
@@ -479,6 +479,7 @@
"appearance.pbr_opaque": "Nieprzezroczysty PBR",
"appearance.roughness": "Chropowatość",
"appearance.surface_response": "Reakcja powierzchni",
"at the face": "przy ścianie",
"browser.body_name": "Bryła{number}",
"browser.calibrate_title": "Kalibruj: {name}",
"browser.capture_many": "Przesunięto komponenty ({count}), ale ich położenia nie zostały zapamiętane.",
@@ -779,6 +780,7 @@
"cmd.sketch_spline_control_point": "Splajn z punktów kontrolnych",
"cmd.sketch_spline_control_point_5": "Splajn z punktów kontrolnych (stopień 5)",
"cmd.sketch_spline_fit_point": "Splajn przez punkty",
"cmd.sketch_spline_reverse": "Odwróć kierunek splajnu",
"cmd.sketch_spun_profile": "Profil obrotowy",
"cmd.sketch_toggle_driven": "Przełącz wymiar sterowany",
"cmd.sketch_trim_path": "Przytnij wzdłuż ścieżki",
@@ -1136,6 +1138,13 @@
"prefs.left_click": "Kliknięcie lewym",
"prefs.live_input": "Bieżące wejście",
"prefs.live_preview": "Podgląd na żywo",
"prefs.max_file_size": "Maksymalny rozmiar otwieranego pliku",
"prefs.max_file_size_design": "Pliki projektów",
"prefs.max_file_size_flag": "To uruchomienie używa --max-file-size {size} aż do zamknięcia SolidCraft. Te ustawienia obowiązują przy uruchomieniu bez tej opcji.",
"prefs.max_file_size_note": "Domyślnie: 512 MB i 256 MB; maksymalnie 16 GB. Otwarcie pliku wymaga pamięci kilkakrotnie większej od jego rozmiaru. Projekt z dużym importem może wymagać wyższego limitu pliku projektu, aby go zapisać i ponownie otworzyć.",
"prefs.max_file_size_step": "Pliki STEP i importu",
"prefs.max_file_size_web": "Aplikacja internetowa otwiera pliki STEP i importu do 512 MB oraz projekty do 256 MB: karta przeglądarki nie pomieści większych plików. W aplikacji komputerowej można zwiększyć te limity.",
"prefs.megabytes": "MB",
"prefs.minutes": "minut",
"prefs.minutes_suffix": " min",
"prefs.mouse": "Mysz i gładzik",
+9
View File
@@ -582,6 +582,7 @@
"appearance.pbr_opaque": "PBR opaco",
"appearance.roughness": "Rugosidade",
"appearance.surface_response": "Resposta da superfície",
"at the face": "na face",
"browser.body_name": "Corpo{number}",
"browser.calibrate_title": "Calibrar: {name}",
"browser.capture_many": "{count} componentes foram movidos, mas suas posições não foram capturadas.",
@@ -885,6 +886,7 @@
"cmd.sketch_spline_control_point": "Spline por pontos de controle",
"cmd.sketch_spline_control_point_5": "Spline por pontos de controle (grau 5)",
"cmd.sketch_spline_fit_point": "Spline por pontos de ajuste",
"cmd.sketch_spline_reverse": "Inverter direção do spline",
"cmd.sketch_spun_profile": "Perfil de revolução",
"cmd.sketch_toggle_driven": "Alternar cota conduzida",
"cmd.sketch_trim_path": "Aparar ao longo do caminho",
@@ -1259,6 +1261,13 @@
"prefs.left_click": "Clique esquerdo",
"prefs.live_input": "Entrada ao vivo",
"prefs.live_preview": "Visualização ao vivo",
"prefs.max_file_size": "Tamanho máximo de arquivo a abrir",
"prefs.max_file_size_design": "Arquivos de projeto",
"prefs.max_file_size_flag": "Esta execução foi iniciada com --max-file-size {size}, que vale até fechar o SolidCraft. Estas configurações se aplicam ao iniciar sem essa opção.",
"prefs.max_file_size_note": "Padrões: 512 MB e 256 MB; máximo de 16 GB. Abrir um arquivo exige várias vezes seu tamanho em memória. Um projeto que mantém uma importação grande pode precisar de um limite maior para ser salvo e reaberto.",
"prefs.max_file_size_step": "Arquivos STEP e de importação",
"prefs.max_file_size_web": "O aplicativo web abre arquivos STEP e de importação de até 512 MB e projetos de até 256 MB: uma aba do navegador não comporta arquivos maiores. O aplicativo para desktop permite aumentar esses limites.",
"prefs.megabytes": "MB",
"prefs.minutes": "minutos",
"prefs.minutes_suffix": " min",
"prefs.mouse": "Mouse e trackpad",
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+489
View File
@@ -258,6 +258,8 @@
"Flanges": "凸緣",
"Flat Pattern": "展開圖",
"Flat size": "展開尺寸",
"Flat size X": "展開尺寸 X",
"Flat size Y": "展開尺寸 Y",
"Follow camera (Look At sketches)": "跟隨相機(注視草圖)",
"Follow the camera (Look At sketches)": "跟隨相機(注視草圖)",
"Font": "字型",
@@ -289,6 +291,7 @@
"Horiz./Vert.": "水平 / 垂直",
"I-Beam": "工字鋼",
"IMAGES": "影像",
"If you are offline or GitHub does not open, use Copy report and keep the text to submit later.": "如果您處於離線狀態或 GitHub 無法開啟,請使用「複製報告」並保留文字,稍後再提交。",
"Import material into design": "將材質匯入設計",
"Import…": "匯入…",
"In This Design": "在此設計中",
@@ -399,13 +402,16 @@
"Of": "的值",
"On your computer": "在此電腦上",
"Opacity": "不透明度",
"Open GitHub": "開啟 GitHub",
"Open GitHub draft": "開啟 GitHub 草稿",
"Open GitHub issue form": "開啟 GitHub Issue 表單",
"Open bodies (no volume)": "未閉合實體(無體積)",
"Open library...": "開啟零件庫...",
"Open local libraries in the desktop app. You can export this design's library here.": "請在桌面應用程式中開啟本機零件庫。您可以在此匯出目前設計的零件庫。",
"Open surface — no volume": "未閉合曲面 — 無體積",
"Open-source parametric 3D CAD in Rust. Licensed MIT OR Apache-2.0.": "使用 Rust 編寫的開源參數化 3D CAD。基於 MIT OR Apache-2.0 授權。",
"Opens your browser and copies the report text for you to paste into GitHub.": "開啟瀏覽器,並複製報告文字,供您貼到 GitHub。",
"Opens your browser and copies the report text. Review and submit your report on GitHub.": "開啟瀏覽器並複製報告文字。請在 GitHub 上檢閱並提交報告。",
"Opens your browser. Review and submit your report on GitHub.": "開啟瀏覽器。請在 GitHub 上檢查並提交報告。",
"Operator": "運算子",
"Orbit (right drag)": "環轉(右鍵拖曳)",
@@ -486,6 +492,7 @@
"Reopen the designs that were open when SolidCraft was last closed": "重新開啟上次關閉 SolidCraft 時開啟的設計",
"Replace existing library file": "取代現有零件庫檔案",
"Report a bug — review a screenshot and open a GitHub draft": "回報錯誤 — 檢閱截圖並開啟 GitHub 草稿",
"Report copied. Keep this text to submit on GitHub when you are online.": "已複製報告。請保留此文字,待連線後在 GitHub 上提交。",
"Report text copied. Paste it into GitHub and submit your report there.": "報告文字已複製。請貼到 GitHub 並在該處提交報告。",
"Reports are public. A GitHub account is required.": "報告為公開內容,需要 GitHub 帳號。",
"Reset Toolbar": "重設工具列",
@@ -547,6 +554,7 @@
"Sections (one sketch each)": "剖面(每個一張草圖)",
"Select Other": "選取其他",
"Select Other: hold the left button still on the model (or right-click › Select Other…) to list everything under the cursor; click again on the same spot to select the next thing there. Double-click the middle button to go Home (Preferences › Navigation).": "「選擇其他」:在模型上按住左鍵(或右鍵點擊 › 選擇其他…)列出游標下的所有物件;在同一位置再次點擊可選擇該處的下一個物件。雙擊中鍵轉到主檢視(偏好設定 › 導覽)。",
"Select Same Look": "選擇相同外觀",
"Select bodies (a face picks its body)": "選擇實體(點擊面即選擇其所屬實體)",
"Select bodies or faces instead": "改為選擇實體或面",
"Select edges": "選取邊",
@@ -581,6 +589,7 @@
"Slider": "滑塊",
"Slot width": "槽寬",
"Snap to face and edge centres": "吸附到面和邊的中心",
"SolidCraft cannot submit reports directly. Submit on GitHub; no token is needed in the app.": "SolidCraft 無法直接提交報告。請在 GitHub 上提交;應用程式內不需要權杖。",
"SolidCraft closed before these designs were saved. Their last autosave can be opened.": "SolidCraft 在這些設計儲存前已關閉。可以開啟它們的上次自動儲存。",
"Spacing 2 must be a non-zero number": "間距 2 必須是非零數字",
"Spacing must be a non-zero number": "間距必須是非零數字",
@@ -757,6 +766,7 @@
"appearance.pbr_opaque": "不透明 PBR",
"appearance.roughness": "粗糙度",
"appearance.surface_response": "表面反應",
"at the face": "在面上",
"bom.group_children": "子零件併入所屬零件的列",
"browser.body_name": "實體{number}",
"browser.calibrate_title": "校準:{name}",
@@ -765,6 +775,7 @@
"browser.capture_one": "一個元件已移動,但尚未擷取其位置。",
"browser.component_name": "元件{number}",
"browser.edit_canvas_title": "編輯畫布:{name}",
"browser.edit_point_cloud_title": "編輯點雲:{name}",
"browser.move_title": "移動:{name}",
"browser.parameters": "參數 ({count})",
"browser.precision": "精度: {precision}",
@@ -785,6 +796,7 @@
"click a plane or planar face": "按一下平面或平坦面",
"click sketch curves": "按一下草圖曲線",
"cmd.appearance_assign": "外觀",
"cmd.appearance_chain": "外觀鏈",
"cmd.appearance_library": "外觀庫",
"cmd.appearance_list": "列出外觀",
"cmd.appearance_paint": "塗抹外觀",
@@ -814,7 +826,9 @@
"cmd.component_create": "新建元件",
"cmd.component_cycle_color": "循環切換元件顏色",
"cmd.component_delete": "刪除元件",
"cmd.component_edit_in_place": "就地編輯",
"cmd.component_extract": "提取到檔案",
"cmd.component_finish_edit": "完成編輯",
"cmd.component_from_bodies": "由實體建立元件",
"cmd.component_insert_design": "插入設計",
"cmd.component_links": "列出連結",
@@ -989,14 +1003,57 @@
"cmd.plastic_rest": "墊塊",
"cmd.plastic_rules": "列出塑膠規則",
"cmd.plastic_snap_fit": "卡扣",
"cmd.pointcloud_delete": "刪除點雲",
"cmd.pointcloud_edit": "編輯點雲",
"cmd.pointcloud_insert": "插入點雲",
"cmd.pointcloud_list": "點雲",
"cmd.render_aging_describe": "分層表面老化",
"cmd.render_backends": "彩現後端",
"cmd.render_batch": "彩現所有鏡頭",
"cmd.render_camera_fit": "取景彩現主體",
"cmd.render_camera_get": "檢查彩現相機",
"cmd.render_cancel": "取消彩現",
"cmd.render_compare": "比較影像",
"cmd.render_effects_describe": "透鏡與創意效果",
"cmd.render_export": "匯出 PNG",
"cmd.render_hdr_inspect": "檢查 HDR 來源",
"cmd.render_library_appearance_apply": "套用資源庫不透明外觀",
"cmd.render_library_describe": "檢查彩現資源庫資源",
"cmd.render_library_environment_apply": "套用內建 HDR 環境",
"cmd.render_library_list": "瀏覽彩現資源庫",
"cmd.render_library_physical_prepare": "準備物理參考",
"cmd.render_library_preview": "檢查原創表面貼圖",
"cmd.render_library_studio_apply": "套用原創攝影棚燈光",
"cmd.render_library_studio_prepare": "準備原創攝影棚燈光",
"cmd.render_library_surface_bind": "儲存表面繫結",
"cmd.render_library_surface_prepare": "準備原創表面貼圖",
"cmd.render_library_surface_unbind": "移除表面繫結",
"cmd.render_library_targets": "尋找彩現資源庫目標",
"cmd.render_lights_add": "新增燈光",
"cmd.render_lights_solo": "獨奏燈光",
"cmd.render_optics_bind": "儲存光學繫結",
"cmd.render_optics_unbind": "移除光學繫結",
"cmd.render_output_size": "設定彩現輸出大小",
"cmd.render_preflight": "檢查彩現請求",
"cmd.render_preset_apply": "套用原生攝影棚",
"cmd.render_preset_resolve": "檢閱原生攝影棚",
"cmd.render_quality_prepare": "檢閱固定取樣預算",
"cmd.render_result_close": "關閉彩現影像",
"cmd.render_result_copy": "複製彩現影像",
"cmd.render_result_pin": "保留顯示的彩現結果",
"cmd.render_result_regrade": "重新調色線性母檔",
"cmd.render_result_view": "檢視彩現影像",
"cmd.render_scene": "檢查彩現場景",
"cmd.render_settings_apply": "套用彩現相機",
"cmd.render_settings_capture_hdr": "儲存含 HDR 的彩現設定",
"cmd.render_settings_get": "彩現設定",
"cmd.render_settings_set": "儲存彩現設定",
"cmd.render_shot_duplicate": "複製彩現鏡頭",
"cmd.render_shot_remove": "移除彩現鏡頭",
"cmd.render_shot_rename": "重新命名彩現鏡頭",
"cmd.render_stage_backdrop": "儲存物理彩現背景",
"cmd.render_stage_clear": "移除彩現佈景",
"cmd.render_stage_ground": "儲存彩現地面",
"cmd.render_start": "彩現影像",
"cmd.render_status": "彩現進度",
"cmd.select_clear": "清除選擇",
@@ -1088,6 +1145,7 @@
"cmd.sketch_spline_control_point_5": "控制點雲形線(5 次)",
"cmd.sketch_spline_fit_point": "擬合點雲形線",
"cmd.sketch_spline_insert_point": "新增雲形線點",
"cmd.sketch_spline_reverse": "反向雲形線方向",
"cmd.sketch_spun_profile": "旋轉輪廓",
"cmd.sketch_toggle_diameter": "切換半徑 / 直徑",
"cmd.sketch_toggle_driven": "切換從動尺寸",
@@ -1129,13 +1187,19 @@
"cmd.timeline_export_script": "匯出命令指令碼",
"cmd.timeline_inspect": "檢查特徵",
"cmd.timeline_paste": "貼上特徵",
"cmd.timeline_play": "播放歷程記錄",
"cmd.timeline_redefine": "編輯特徵",
"cmd.timeline_rename": "重新命名",
"cmd.timeline_reorder": "重排特徵",
"cmd.timeline_roll_to": "滾動歷程標記",
"cmd.timeline_rollback": "移動時間軸標記",
"cmd.timeline_stop": "停止播放歷程記錄",
"cmd.timeline_suppress": "抑制特徵",
"cmd.view.render_browser": "彩現瀏覽器",
"cmd.view.render_dock": "移動彩現停靠面板",
"cmd.view.render_focus": "彩現聚焦檢視",
"cmd.view_ambient_occlusion": "環境光遮蔽",
"cmd.view_angle_readout": "檢視角度",
"cmd.view_apply": "還原命名檢視",
"cmd.view_back": "後視圖",
"cmd.view_bottom": "仰視圖",
@@ -1151,7 +1215,9 @@
"cmd.view_list": "列出命名檢視",
"cmd.view_navigate": "導覽檢視",
"cmd.view_navigation_bar": "導覽列",
"cmd.view_next_tab": "下一個索引標籤",
"cmd.view_normal_to": "正視於選取項目",
"cmd.view_previous_tab": "上一個索引標籤",
"cmd.view_rename": "重新命名命名檢視",
"cmd.view_right": "右視圖",
"cmd.view_save": "新建命名檢視",
@@ -1270,6 +1336,7 @@
"help.appearance.assign": "為所選的實體、面或元件設定顏色或材質外觀,不改變其重量。用於區分零件或預覽表面處理效果。",
"help.attributions": "署名資訊 (ATTRIBUTION.md)",
"help.build": "版本 {version} · 提交 {commit} · 建置日期 {date}",
"help.component.finish_edit": "儲存就地編輯的零件,返回其組合件,並以該零件更新組合件。連結零件的變更完成後使用。",
"help.connect_note": "請重新啟動各個助理以載入 SolidCraft 伺服器。每個檔案在變更前都已備份為 .bak。",
"help.connect_title": "連接 AI 助理",
"help.face.delete": "刪除所選的面,並由相鄰的面封閉留下的缺口,也可以讓缺口保持開放、成為曲面。用於移除礙事的圓角、孔或凸座。",
@@ -1280,6 +1347,7 @@
"help.mit": "MIT 授權",
"help.notice": "NOTICE",
"help.parameters.change": "開啟用於驅動設計尺寸的具名數值與運算式表。用於在同一處修改尺寸,讓所有使用該尺寸的特徵隨之更新。",
"help.pointcloud.insert": "將 PLY、XYZ 或 PTS 掃描資料作為點雲插入模型旁。以實測資料建立模型時,可作為參考。",
"help.solid.align": "移動所選實體,使其上的點、面或平面與別處的點、面或平面對齊。用於將一個零件貼靠到另一個零件上,而無需測量偏移量。",
"help.solid.chamfer": "以指定的距離在所選邊上切出平直的斜面。用於去除銳邊,或使銷釘、螺絲更容易插入。",
"help.solid.combine": "結合多個實體、從目標實體中切除,或只保留它們共有的體積,還可以保留工具實體。用於合併零件、用一個形體切割另一個形體,或找出兩個實體重疊的位置。",
@@ -1305,6 +1373,7 @@
"help.third_party": "第三方授權",
"help.timeline.compute_all": "從頭重新計算時間軸中的所有特徵。用於重新整理模型,並查看哪些特徵失敗。",
"help.timeline.delete": "從時間軸中刪除所選特徵;刪除草圖時,由它建立的特徵也會一併刪除。用於移除不再需要的步驟。",
"help.timeline.play": "逐一重播其餘特徵,每次重建後暫停半秒。再次執行此命令或按 Escape 可停止;「移至結尾」會立即跳到結尾。",
"hole_presets.confirm_delete": "確認刪除",
"hole_presets.delete": "刪除",
"hole_presets.delete_prompt": "刪除此個人預設?現有的孔不會改變。",
@@ -1408,6 +1477,8 @@
"keymap.command_id": "命令 ID",
"keymap.empty": "沒有符合的命令",
"keymap.use_anyway": "仍在此處使用 {key}",
"label.move_to_left_side": "移到左側",
"label.move_to_right_side": "移到右側",
"manage.appearance_hint": "為所選物件選擇外觀,或將色票拖到實體或面上。",
"manage.assign_hint": "選擇實體並指定其塑膠設計規則。",
"manage.config_hint": "編輯組態列、欄和規則,然後啟用或預覽某一列。",
@@ -1492,7 +1563,9 @@
"nav.free_orbit_upright.help": "左右拖曳滑鼠時,模型會繞世界的垂直軸旋轉;上下拖曳則可不受限制地越過頂部傾斜。",
"nav.free_orbit_upright.label": "繞垂直軸旋轉",
"nav.fusion.help": "中鍵拖曳可平移,Shift+中鍵可環繞,右鍵拖曳可環繞",
"nav.hfss.help": "Alt+左鍵拖曳可平移,Shift+Alt+左鍵可縮放,在空白處按 Ctrl+左鍵拖曳可環轉",
"nav.inventor.help": "中鍵拖曳可平移,Shift+中鍵可環繞,Ctrl+中鍵可縮放,右鍵拖曳可環繞",
"nav.maya.help": "Alt+左鍵拖曳可環轉,Alt+中鍵可平移,Alt+右鍵可縮放;中鍵拖曳同樣可平移",
"nav.openscad.help": "在空白處以左鍵拖曳可環繞,Shift+左鍵拖曳可框選,拖曳草圖幾何可編輯;右鍵或中鍵拖曳可平移,Shift+右鍵或 Shift+中鍵拖曳可縮放",
"nav.perspective.sketch": "編輯草圖時會使用正交檢視。完成草圖後才能切換為透視。",
"nav.solidworks.help": "中鍵拖曳可環繞,Ctrl+中鍵可平移,Shift+中鍵可縮放,右鍵拖曳可環繞",
@@ -1610,11 +1683,13 @@
"parts.automatic_name": "自動",
"parts.dimension.across_flats": "對邊寬度",
"parts.dimension.bore": "內徑",
"parts.dimension.d": "公稱直徑",
"parts.dimension.head_diameter": "頭部直徑",
"parts.dimension.head_height": "頭部高度",
"parts.dimension.height": "高度",
"parts.dimension.inner": "內徑",
"parts.dimension.outer": "外徑",
"parts.dimension.pitch": "螺距",
"parts.dimension.socket": "內六角對邊",
"parts.dimension.socket_depth": "內六角深度",
"parts.dimension.thickness": "厚度",
@@ -1673,6 +1748,8 @@
"prefs.bodies_folders_never": "不顯示",
"prefs.bodies_folders_several": "僅限多個實體",
"prefs.bottom": "底部",
"prefs.bottom_centre": "下方置中",
"prefs.bottom_right": "右下方",
"prefs.browser": "瀏覽器",
"prefs.built_in": "內建",
"prefs.button_left": "左鍵拖曳",
@@ -1724,6 +1801,8 @@
"prefs.history": "歷程記錄",
"prefs.history_origin_bodies": "在頂部顯示原點與實體",
"prefs.history_origin_bodies_note": "左側或瀏覽器下方的歷程記錄,會以作用中元件的「實體」資料夾和「原點」開頭,其顯示切換(眼睛圖示)和選單與瀏覽器中相同。底部的歷程記錄維持不變。",
"prefs.history_play_button": "歷程記錄控制項中的「播放歷程記錄」按鈕",
"prefs.history_play_button_note": "將「播放歷程記錄」放在歷程記錄控制項的「後退一步」與「前進一步」之間。也可以在控制項上按一下滑鼠右鍵來顯示或隱藏。",
"prefs.history_sketches": "草圖",
"prefs.history_sketches_in_order": "依建立順序",
"prefs.history_sketches_note": "「草圖」設為「位於其特徵下」時,左側的歷程記錄在寬度足以顯示名稱時,會把每個草圖縮排一層,列在由它建立的第一個特徵之下。底部的時間軸一律保持建立順序。",
@@ -1731,6 +1810,7 @@
"prefs.hold_stop_snapping": "按住以停用鎖點",
"prefs.icons_only": "僅圖示",
"prefs.imported_file": "已匯入的檔案",
"prefs.in_browser": "瀏覽器內",
"prefs.input": "輸入",
"prefs.interface": "介面",
"prefs.interface_language": "介面語言",
@@ -1741,8 +1821,19 @@
"prefs.layout_note": "精簡模式會將面板停靠在視窗邊緣。瀏覽器半透明僅適用於浮動模式。助理的位置請在「助理」頁面中變更。",
"prefs.left": "左側",
"prefs.left_click": "左鍵點擊",
"prefs.linked_designs": "連結設計",
"prefs.live_input": "即時輸入",
"prefs.live_preview": "即時預覽",
"prefs.logo": "標誌",
"prefs.logo_accent": "強調色",
"prefs.logo_theme": "主題色彩",
"prefs.max_file_size": "可開啟的最大檔案",
"prefs.max_file_size_design": "設計檔案",
"prefs.max_file_size_flag": "本次啟動指定了 --max-file-size {size},此值在關閉 SolidCraft 前有效。不帶此選項啟動時才會套用這些設定。",
"prefs.max_file_size_note": "預設值:512 MB 和 256 MB;上限為 16 GB。開啟檔案需要數倍於檔案大小的記憶體。保留大型匯入資料的設計可能需要提高設計檔案上限,才能儲存並重新開啟。",
"prefs.max_file_size_step": "STEP 和匯入檔案",
"prefs.max_file_size_web": "網頁版可開啟最大 512 MB 的 STEP 和匯入檔案,以及最大 256 MB 的設計:瀏覽器分頁無法容納更大的檔案。桌面版可提高這些上限。",
"prefs.megabytes": "MB",
"prefs.minutes": "分鐘",
"prefs.minutes_suffix": " min",
"prefs.mouse": "滑鼠與觸控板",
@@ -1783,6 +1874,8 @@
"prefs.shift_add_ctrl_toggle": "Shift 僅新增;Ctrl / Cmd 切換選擇",
"prefs.shift_add_note": "開啟:Shift 新增,Ctrl / Cmd 切換選擇。關閉(預設):兩者皆切換選擇。",
"prefs.shortcuts": "快捷鍵",
"prefs.sketch_conflict_colour": "衝突幾何以衝突顏色顯示",
"prefs.sketch_conflict_colour_note": "草圖的拘束發生衝突時,失敗拘束所涉及的曲線與點也會以衝突顏色繪製,而不只是其符號或尺寸。關閉時:維持原本的顏色。",
"prefs.sketch_exit_view": "草圖結束時",
"prefs.sketch_exit_view.keep": "保持目前檢視",
"prefs.sketch_exit_view.previous": "返回先前的檢視",
@@ -1791,11 +1884,17 @@
"prefs.sketch_selection": "草圖與選取",
"prefs.sketch_selection_heading": "草圖與選取",
"prefs.sketch_selection_note": "草圖如何貼齊,以及點擊如何選取。",
"prefs.sketch_tab_always": "保持顯示「草圖」索引標籤",
"prefs.sketch_tab_always_note": "沒有開啟草圖時,「草圖」索引標籤仍保留在功能區中,位於「模型」之後。使用其繪圖工具時,會在所選的平面或面上、或在你接著選取的平面上開始草圖,並直接啟用該工具。",
"prefs.sketch_tracking_guides": "圓心與中點對齊輔助線",
"prefs.sketch_tracking_guides_note": "游標停在圓心或直線邊的中點上,再水平或垂直移動,即可顯示暫時的點線輔助線。",
"prefs.sketching": "草圖",
"prefs.snap_drawing_note": "繪製或拖曳草圖點時使用。",
"prefs.source": "來源",
"prefs.speed": "速度",
"prefs.stand_up_note": "以 Z 軸向上開啟 STEP 或 IGES 檔案後,詢問是否繞 X 軸旋轉 90°。",
"prefs.status_bar": "狀態列",
"prefs.status_bar_note": "視窗底部的細長列會顯示正在編輯的內容、以顏色表示的開啟中草圖狀態,以及設計的單位;按一下單位即可變更。草圖狀態就不會再顯示在檢視的角落。",
"prefs.status_done": "完成",
"prefs.status_error": "錯誤",
"prefs.status_selected": "已選取",
@@ -1803,15 +1902,20 @@
"prefs.supersampling_brief": "以更高解析度繪製檢視再縮小:非常清晰,但負載較高。",
"prefs.tab_accent_note": "強調色跟隨目前的分頁",
"prefs.theme_file": "主題檔案",
"prefs.theme_file_or_paste": "檔案或貼上",
"prefs.theme_follow": "跟隨主題檔案",
"prefs.theme_follow_error": "未套用:{error}。保留上次有效的主題。",
"prefs.theme_follow_launch": "僅本次執行跟隨 (--theme-file);其他工具改寫檔案時會重新載入。",
"prefs.theme_follow_note": "其他工具改寫檔案時會重新載入。選擇主題將停止跟隨。",
"prefs.theme_follow_off": "關閉",
"prefs.theme_follow_stop": "停止跟隨",
"prefs.theme_import_hint": "按一下以選擇主題檔案、將檔案拖放到此處,或在已複製主題的情況下按 Ctrl+V(Mac 為 Cmd+V)",
"prefs.theme_paste": "貼上主題",
"prefs.theme_paste_none": "剪貼簿中沒有 SolidCraft 主題",
"prefs.timeline_half_hour": "−30 分鐘",
"prefs.timeline_now": "現在",
"prefs.timeline_quarter_hour": "−15",
"prefs.toast_place": "通知位置",
"prefs.toggle_item": "加入此項目,或再次移除",
"prefs.toolbar": "工具列",
"prefs.top": "頂部",
@@ -1874,7 +1978,47 @@
"render.aging_upward": "朝上的沉積",
"render.all_controls_help": "密集檢視目前所有控制項。各分區頁面提供專注的編輯方式,不會變更底層請求。",
"render.all_shots_label": "所有鏡頭",
"render.appearance_editor.absorption": "吸收",
"render.appearance_editor.base_colour": "基礎顏色",
"render.appearance_editor.body_reason": "光學繫結作用於整個實體。請選取「實體」以編輯這些控制項。",
"render.appearance_editor.boundary": "邊界",
"render.appearance_editor.box": "長方體",
"render.appearance_editor.choose_image": "選擇影像…",
"render.appearance_editor.closed": "封閉實體",
"render.appearance_editor.coat": "透明塗層",
"render.appearance_editor.cpu_reason": "需要 CPU 光線追蹤。",
"render.appearance_editor.glass": "玻璃與吸收",
"render.appearance_editor.glass_enable": "在此實體上使用物理玻璃",
"render.appearance_editor.glass_note": "封閉玻璃使用幾何距離。無法與透明塗層或貼圖用於同一實體。",
"render.appearance_editor.gpu_reason": "需要 GPU 路徑追蹤。",
"render.appearance_editor.ior": "折射率 (IOR)",
"render.appearance_editor.maps": "貼圖",
"render.appearance_editor.normal": "法線",
"render.appearance_editor.normal_strength": "法線強度",
"render.appearance_editor.origin": "原點",
"render.appearance_editor.recipe": "配方",
"render.appearance_editor.reflection_sampling": "所有反光實體的取樣",
"render.appearance_editor.reflections": "反射",
"render.appearance_editor.remove": "移除已儲存項",
"render.appearance_editor.remove_note": "從此鏡頭移除已儲存的光學設定。幾何形狀與已指派的風格會保留。",
"render.appearance_editor.remove_title": "移除已儲存的光學設定?",
"render.appearance_editor.replace": "取代此實體已儲存的光學設定",
"render.appearance_editor.revalidate": "重新驗證此實體",
"render.appearance_editor.save": "儲存這些光學設定",
"render.appearance_editor.save_reason": "儲存這些光學設定需要在最新的 GPU 實體上使用物理玻璃。塗層與本機影像貼圖仍為暫時性。",
"render.appearance_editor.saved": "已隨此鏡頭儲存",
"render.appearance_editor.saved_state": "這些光學設定已隨此鏡頭儲存。",
"render.appearance_editor.scatter_reason": "內部散射需要封閉實體邊界。",
"render.appearance_editor.temporary": "這些光學設定在此分頁中為暫時性。請儲存以便隨鏡頭保留。",
"render.appearance_editor.thickness": "厚度",
"render.appearance_editor.thickness_reason": "厚度適用於薄板;封閉玻璃使用幾何距離。",
"render.appearance_editor.thin": "薄板",
"render.appearance_editor.u_repeat": "U 重複",
"render.appearance_editor.v_repeat": "V 重複",
"render.appearance_editor.v_up": "紋理 V 軸朝上",
"render.appearance_editor.weight": "權重",
"render.appearance_physics_separate": "視覺外觀不會指定密度、熱學資料或其他工程屬性。",
"render.appearances": "外觀",
"render.availability_native": "原生組合;套用前請先檢閱",
"render.availability_projection": "支援的投影;請參閱範圍與省略項目",
"render.availability_reference": "參考資料;不會自動指派",
@@ -1929,6 +2073,13 @@
"render.camera_set": "設定彩現相機",
"render.camera_target": "目標位置 · mm",
"render.camera_yaw": "偏航",
"render.category_metal": "金屬",
"render.category_paint": "塗料",
"render.category_plastic": "塑膠",
"render.category_wood": "木材",
"render.check_opaque": "透明度:僅支援不透明表面;支援背景 Alpha。",
"render.check_sorted_alpha": "透明度:排序 Alpha 近似。",
"render.check_transmission": "透明度:物理透射。",
"render.chromatic_offset": "邊緣色差偏移",
"render.clear_stage": "移除已儲存的佈景",
"render.copy_request": "複製 JSON",
@@ -2028,6 +2179,87 @@
"render.effects_reset_lens": "重設鏡頭效果",
"render.effects_seed": "圖樣種子",
"render.emitted_axis": "發射軸",
"render.env_advanced": "進階",
"render.env_backdrop": "背景",
"render.env_backdrop_pending": "彩現器尚不支援環境可見度與背景模糊。",
"render.env_blur": "模糊",
"render.env_change": "變更",
"render.env_choose_source": "編輯照明前,請先在「攝影棚」與「環境」中選擇環境。",
"render.env_clear": "清除",
"render.env_colour": "顏色",
"render.env_environments": "環境",
"render.env_ground": "地面",
"render.env_ground_pending": "物理地面以有限的漫射表面接收陰影。尚不支援僅接收陰影與地面反射。",
"render.env_intensity": "強度",
"render.env_invalid_edit": "無效的環境編輯。",
"render.env_physical_ground": "物理地面",
"render.env_preview_help": "示意球體範例;並非所選環境的預覽。",
"render.env_reflection": "反射",
"render.env_ring_help": "拖曳圓環以旋轉照明。按住 Shift 可鎖點至 15°。",
"render.env_rotate": "旋轉",
"render.env_set": "設定彩現環境",
"render.env_shadow_catcher": "陰影接收器",
"render.env_show_environment": "顯示環境",
"render.env_source": "來源",
"render.env_stage_details": "編輯地面需要光線追蹤與單一地面面板。請使用「場景」編輯其他舞台面板。",
"render.env_studios": "攝影棚",
"render.environment.albedo": "反照率",
"render.environment.atmosphere": "大氣",
"render.environment.backdrop_note": "背景僅供相機看見。它不會照明、投射陰影或反射,輸出透明背景時會被拒絕。",
"render.environment.blur_pending": "無法使用模糊:彩現器沒有背景模糊設定。",
"render.environment.builtin": "內建 HDR",
"render.environment.check": "檢查檔案",
"render.environment.checked": "已檢查 HDR 檔案。儲存時會內嵌這些位元組。",
"render.environment.choose": "選擇 HDR…",
"render.environment.constant": "恆定",
"render.environment.cyclorama": "環形背景幕",
"render.environment.embedded": "儲存於此設計內",
"render.environment.end": "終點",
"render.environment.extinction": "消光",
"render.environment.file": "檔案",
"render.environment.fit": "擬合並儲存地面",
"render.environment.floor_wall": "地板與牆面",
"render.environment.gap": "間隙",
"render.environment.gradient": "漸層",
"render.environment.gradient_gpu": "漸層背景需要 GPU 路徑追蹤。",
"render.environment.ground": "地面與舞台",
"render.environment.hdr": "HDR",
"render.environment.hdr_file": "HDR 檔案",
"render.environment.horizon": "地平線",
"render.environment.horizontal": "水平",
"render.environment.keep": "保留",
"render.environment.lighting_samples": "照明取樣數",
"render.environment.margin": "範圍餘量",
"render.environment.max": "最大邊界",
"render.environment.medium": "參與介質",
"render.environment.min": "最小邊界",
"render.environment.mode": "模式",
"render.environment.needs_gpu": "需要 GPU 路徑追蹤。",
"render.environment.none": "無",
"render.environment.orientation": "方向與強度",
"render.environment.phase": "相位",
"render.environment.primaries": "將未指定的原色視為線性 sRGB",
"render.environment.primaries_gpu": "解讀未指定的原色需要 GPU 路徑追蹤。",
"render.environment.radial": "放射狀",
"render.environment.radial_only": "中心與半徑僅適用於放射狀模式。",
"render.environment.reflectance": "反射率",
"render.environment.remove": "移除舞台",
"render.environment.remove_confirm": "要移除已儲存的舞台嗎?",
"render.environment.remove_note": "從此鏡頭移除 {count} 個被動面板。相機背景會保留。",
"render.environment.replace": "確認取代現有舞台",
"render.environment.rotation_hdr": "旋轉需要使用 CPU 光線追蹤的 HDR 來源。",
"render.environment.samples_cpu": "照明取樣數由 GPU 路徑追蹤預算決定;此設定需要 CPU 光線追蹤。",
"render.environment.saved_panels": "已儲存的面板 {count}",
"render.environment.sky_ground": "地面",
"render.environment.sky_note": "供照明使用的原創天空漸層;並非校準過的大氣。",
"render.environment.source_raytrace": "環境來源需要 CPU 或 GPU 光線追蹤。",
"render.environment.stage_raytrace": "物理舞台需要 CPU 或 GPU 光線追蹤。",
"render.environment.start": "起點",
"render.environment.vertical": "垂直",
"render.environment.world": "世界",
"render.environment.world_pending": "無法使用世界背景:環境的相機可見度尚無已儲存的設定。",
"render.environment.zenith": "天頂",
"render.environment_tiles_require_raytrace": "環境需要 CPU 或 GPU 光線追蹤。請在「輸出」編輯器中選擇。",
"render.error_area_samples": "area_samples 必須為 1、4、16 或 64",
"render.error_binding_allocation": "無法保留材質繫結",
"render.error_body_bound": "產品預覽超出其擷取實體的上限",
@@ -2099,6 +2331,8 @@
"render.flare_strength": "亮部眩光強度",
"render.flare_threshold": "場景線性眩光閾值",
"render.fold_browser": "摺疊瀏覽器",
"render.frame_presets": "畫面預設",
"render.frame_presets_pending": "將隨「鏡頭」編輯器推出",
"render.gpu_depth": "最大路徑深度",
"render.gpu_options_help": "取樣數、深度、種子和曝光會隨此設定一併儲存。僅儲存目前啟用的影像方法。",
"render.gpu_path_failed": "GPU 路徑追蹤器無法使用",
@@ -2159,6 +2393,36 @@
"render.inner_half_angle": "內半角",
"render.inspect_scene": "重新整理已擷取的場景摘要",
"render.inspector": "檢查器",
"render.inspector_advanced": "進階",
"render.inspector_all_users": "全部 {count} 個套用對象",
"render.inspector_applies_to": "套用於",
"render.inspector_both_users": "兩個套用對象",
"render.inspector_chain": "此風格的來源",
"render.inspector_colour": "顏色",
"render.inspector_edit": "編輯",
"render.inspector_finish": "表面處理",
"render.inspector_from_material": "來自材質",
"render.inspector_gloss": "光澤",
"render.inspector_material": "材質",
"render.inspector_matte": "霧面",
"render.inspector_metal": "金屬",
"render.inspector_opacity": "不透明度",
"render.inspector_opaque_help": "表面處理與光學欄位使用不透明 PBR(不透明度 1)。較低的不透明度則使用純量著色。",
"render.inspector_pick_target": "請選取此類型的目標以檢視其外觀。",
"render.inspector_remove": "移除覆寫",
"render.inspector_replace": "取代…",
"render.inspector_reset": "重設",
"render.inspector_satin": "緞面",
"render.inspector_save_library": "儲存到資源庫…",
"render.inspector_set_all": "外觀不一。編輯會設定所有已選取目標的風格。",
"render.inspector_soon": "即將推出",
"render.inspector_target_limit": "最多只能選取 10000 個目標來檢視外觀。",
"render.inspector_textures": "紋理",
"render.inspector_this_body": "此實體",
"render.inspector_this_component": "此元件",
"render.inspector_this_face": "此面",
"render.inspector_this_target": "此目標",
"render.inspector_used_by": "{count} 個套用對象",
"render.keep_editing": "繼續編輯",
"render.layer_down": "下移",
"render.layer_enabled": "圖層已啟用",
@@ -2170,8 +2434,12 @@
"render.lens_effects_title": "仿透鏡與攝影效果",
"render.library_all": "目錄",
"render.library_all_states": "所有可用性狀態",
"render.library_appearance_available": "可用外觀",
"render.library_applicable": "適用的資源",
"render.library_applied": "已套用資源投影。開始前請檢查完整的彩現請求。",
"render.library_apply_appearance": "套用外觀",
"render.library_apply_hdr": "以此 HDR 環境儲存",
"render.library_apply_hint": "點擊以套用 · 拖曳至模型上",
"render.library_apply_maps": "使用原創 GPU 表面貼圖",
"render.library_apply_studio": "儲存原創攝影棚投影",
"render.library_apply_uniform": "套用均勻不透明外觀",
@@ -2187,15 +2455,23 @@
"render.library_extent": "主體範圍",
"render.library_favorite": "加入收藏",
"render.library_favorites": "收藏",
"render.library_filters": "目錄與可用性",
"render.library_grid": "網格",
"render.library_hdr": "內建 HDR 環境",
"render.library_hdr_help": "將原始 HDR 內嵌於已儲存的設定。原創經度原點會明確轉換;儲存後不再需要外部檔案。",
"render.library_in_design": "設計中",
"render.library_inspect_only": "選擇即可檢視;不會自動套用任何內容。收藏和最近記錄屬於此開啟的文件工作階段。",
"render.library_ior": "IOR",
"render.library_light_concepts": "燈光概念",
"render.library_list": "清單",
"render.library_maps_help": "內建貼圖可連同已固定的來源和局部實例對應一併儲存。暫時的光學覆寫仍為獨立模式。",
"render.library_material_concepts": "材質概念",
"render.library_metallic": "金屬度",
"render.library_native_scenes": "原生攝影棚",
"render.library_next": "下一頁",
"render.library_omitted": "未包含",
"render.library_opacity": "不透明度",
"render.library_other": "其他外觀",
"render.library_physical_profiles": "物理參考設定檔",
"render.library_previous": "上一頁",
"render.library_quality_concepts": "品質規格",
@@ -2205,6 +2481,7 @@
"render.library_results": "符合的資源",
"render.library_rig_help": "在明確指定的中心和實際範圍一次完成擬合。完整燈組包含被動反光卡;校準阻礙仍會被拒絕。儲存前會以保守標準檢查發光體與反光卡的間隙。",
"render.library_rigs": "原創燈組",
"render.library_roughness": "粗糙度",
"render.library_save_maps": "將貼圖儲存到此設定",
"render.library_scene_bounds": "使用已擷取的場景邊界",
"render.library_scenes": "場景規格",
@@ -2228,6 +2505,7 @@
"render.library_unfavorite": "移除收藏",
"render.library_uniform_ack": "使用均勻近似,不含空間或進階效果",
"render.library_usable": "可執行的投影",
"render.library_users": "套用對象",
"render.light_anchor_pending": "尚無法變更燈光座標系。",
"render.lights_fixed_to": "燈光固定於",
"render.linear_help": "在降噪、曝光、色調對應、濾鏡與背景之前,保留 32 位元浮點 RGBA 母檔。線性 sRGB/D65;覆蓋率預乘。額外記憶體須明確核可。無壓縮,也無額外通道。",
@@ -2311,12 +2589,34 @@
"render.optics_saved": "已儲存的光學目標",
"render.optics_saved_help": "確切的定義、特徵與實例身分在離線重新開啟後仍會保留。遺失、被取代或隱藏的目標會被拒絕;工程材質不變。移除已儲存的目標前,請先儲存或捨棄數值編輯。",
"render.outer_half_angle": "外半角",
"render.output_advanced": "進階",
"render.output_backend_ready": "就緒",
"render.output_check": "檢查",
"render.output_check_help": "執行「檢查」可在不開始彩現的情況下檢閱此請求。",
"render.output_check_summary": "檢查 · 備註:{count}",
"render.output_copy": "複製",
"render.output_destination": "目的地",
"render.output_destination_help": "匯出完成的影像時,請選擇目的檔案。",
"render.output_dimensions": "大小",
"render.output_effects": "效果",
"render.output_export": "匯出 PNG…",
"render.output_exr_unavailable": "此處無法設定 EXR 輸出。線性 EXR 匯出需要保留線性母檔的已完成 GPU 影像。",
"render.output_fit": "適合",
"render.output_format": "格式",
"render.output_format_status": "PNG 是確切的已完成顯示影像。選用的 GPU EXR 會在顯示濾鏡之前,保留原始場景線性 FLOAT32 輻射亮度。匯出絕不會以預覽快取或其他工作取代。",
"render.output_image": "影像",
"render.output_largest": "最大 {width} × {height}",
"render.output_lock_ratio": "鎖定長寬比",
"render.output_over_budget": "所要求的影像超出所選的資源範圍。請明確選擇相容的尺寸或設定檔;不會自動降級。",
"render.output_presets_help": "格式、品質與檢查清單位於輸出編輯器中。",
"render.output_quality": "品質",
"render.output_quality_waiting": "等待品質約定",
"render.output_ratio_refused": "連動的尺寸超出此方法的大小上限。先前的尺寸會保留;請解除鎖定比例,或選擇較小的值。",
"render.output_ready": "可開始彩現",
"render.output_size_ok": "大小正常 · {width} × {height} px",
"render.output_swap_orientation": "交換寬度與高度",
"render.output_tools_inspector": "請在「輸出」檢查器中編輯尺寸與格式。",
"render.output_view_image": "檢視影像",
"render.page_aging": "老化與污染",
"render.page_all": "所有控制項",
"render.page_appearance": "外觀",
@@ -2377,10 +2677,18 @@
"render.property_unknown": "未知",
"render.quality_ack": "確認固定預算的投影與省略項目",
"render.quality_apply": "使用此固定取樣預算",
"render.quality_balanced": "平衡",
"render.quality_custom": "自訂",
"render.quality_draft": "草稿",
"render.quality_high": "高",
"render.quality_projection_help": "Q 預設包含未來的需求。此操作僅投影受支援的固定取樣 PNG 預算,並明確省略自適應停止、原始線性輸出與獨立的穿透上限。",
"render.quality_review": "檢閱取樣預算",
"render.queue_pending": "此介面沒有自動化的正式生產佇列或動畫彩現器。已完成的靜態影像仍可單獨匯出。",
"render.radial_assign": "指派外觀",
"render.radial_compare": "比較",
"render.radial_distortion": "徑向畸變",
"render.radial_fit": "適合產品檢視",
"render.radial_save": "儲存鏡頭",
"render.regrade_action": "重新調色原始母檔(不降噪)",
"render.regrade_help": "以這些呈現控制項,從所選的已完成原始母檔建立獨立的 PNG。不會追蹤光線、變更已擷取的尺寸/相機/光源,也不會覆寫 EXR。不會重新套用降噪:原始母檔不保留其引導資料。衍生檔仍可透過相同的工作控制項匯出。",
"render.regrade_label": "重新調色",
@@ -2389,6 +2697,7 @@
"render.replace_label": "取代",
"render.replace_saved_surface": "取代此目標現有的已儲存繫結",
"render.restore_camera": "還原已儲存相機",
"render.result_actual": "100%",
"render.result_actual_help": "每個顯示像素對應一個影像像素。",
"render.result_actual_size": "100%",
"render.result_capture": "擷取的修訂版本",
@@ -2446,6 +2755,7 @@
"render.scene_review": "解析並檢閱",
"render.scene_review_help": "套用前請檢閱完整的原生組合。未繫結的進階 SCENE 規格不會被替代。",
"render.scene_scope_details": "組合範圍",
"render.search_appearances": "搜尋 {count} 個外觀",
"render.setup_legacy_environment": "此舊版設定使用傳統的環境旋轉或強度。這些值會保留;儲存完整影像工作前,請明確轉換它們。",
"render.setup_name": "設定名稱",
"render.setup_numeric_help": "「儲存」會記錄作用中的影像方法及其所有數值設定。重新載入或選擇其他設定會取代此草稿;相機請另行還原。",
@@ -2455,6 +2765,7 @@
"render.sharpening": "細節銳利化",
"render.shell_tab_appearance": "彩現外觀",
"render.shell_tab_camera": "彩現相機",
"render.shell_tab_lighting": "照明",
"render.shell_tab_scene": "彩現場景",
"render.shot_duplicate": "複製已儲存的鏡頭",
"render.shot_manager": "已儲存的鏡頭",
@@ -2464,22 +2775,126 @@
"render.shot_remove_title": "移除已儲存的鏡頭?",
"render.shot_rename": "重新命名已儲存的鏡頭",
"render.shot_saved_only": "請先儲存目前的草稿。複製與重新命名會保留確切的已儲存選項與資源參照。",
"render.shots_camera_changed": "儲存此鏡頭後相機已變更",
"render.shots_name_help": "請為目前的鏡頭輸入唯一的名稱。",
"render.shots_no_result": "尚無彩現",
"render.shots_result": "彩現 {number} · {width} × {height}",
"render.shots_revert": "還原",
"render.shots_save": "儲存鏡頭",
"render.shots_update": "更新鏡頭",
"render.show_shots_label": "顯示鏡頭列",
"render.size_4k": "4K",
"render.size_4k_uhd": "4K UHD",
"render.size_custom": "自訂…",
"render.size_full_hd": "Full HD",
"render.size_hd": "HD",
"render.size_presets": "尺寸預設",
"render.size_presets_pending": "將隨「輸出」編輯器推出",
"render.size_preview": "預覽",
"render.size_square": "正方形",
"render.sky_ground": "地面 · 線性 RGB",
"render.sky_horizon": "地平線 · 線性 RGB",
"render.sky_zenith": "天頂 · 線性 RGB",
"render.soft_focus": "柔焦",
"render.spot_cone": "聚光錐角",
"render.stage_frame": "畫面",
"render.stage_layout.appearance_note": "按一下以套用至選取項目。",
"render.stage_layout.studio_note": "按一下以先檢閱再套用。",
"render.stage_light": "燈光",
"render.stage_look": "風格",
"render.stage_orthographic": "正交",
"render.stage_output": "輸出",
"render.stage_panel_count": "已儲存的面板",
"render.stage_panels.acknowledge": "我了解取代內容與限制",
"render.stage_panels.appearance_note": "按一下以套用至選取項目。可拖曳到模型上。未選取任何項目時,按一下會啟用「塗料」。",
"render.stage_panels.apply": "套用",
"render.stage_panels.apply_studio": "套用攝影棚",
"render.stage_panels.badge_blocked": "已封鎖",
"render.stage_panels.badge_native": "原生",
"render.stage_panels.badge_projection": "投影",
"render.stage_panels.badge_reference": "參考",
"render.stage_panels.badge_specification": "僅規格",
"render.stage_panels.candidate_summary": "候選項:{count} 個有來源的值。等級與表面處理需要檢閱。",
"render.stage_panels.captured_bounds": "使用擷取的場景邊界",
"render.stage_panels.centre": "中心",
"render.stage_panels.depth": "深度",
"render.stage_panels.environments": "環境",
"render.stage_panels.extent": "範圍",
"render.stage_panels.fit_save": "擬合並儲存",
"render.stage_panels.gpu_required": "需要 GPU 路徑追蹤",
"render.stage_panels.keep": "保留",
"render.stage_panels.kept": "已保留",
"render.stage_panels.kept_fields": "相機、取樣、尺寸、光學綁定、CAD 幾何與工程屬性。",
"render.stage_panels.kept_quality": "方法、相機、照明、環境、舞台、光學、曝光與色調對應。",
"render.stage_panels.mine": "我的",
"render.stage_panels.mine_pending": "尚不支援儲存個人攝影棚。",
"render.stage_panels.omits": "省略內容",
"render.stage_panels.paint_pending": "尚不支援塗料與拖曳指派。請選取目標以套用風格。",
"render.stage_panels.partial_reference": "候選項:僅限有來源的值;請檢閱等級、狀態與來源。未知的值仍為未知。",
"render.stage_panels.plane": "平面",
"render.stage_panels.prepare_plan": "準備建立計畫",
"render.stage_panels.projects": "專案",
"render.stage_panels.quality_ack": "我了解固定預算及其省略內容",
"render.stage_panels.quality_omissions": "自適應停止與誤差目標、獨立的透射深度、俄羅斯輪盤規則、原始線性輸出、EXR 母檔與收斂認證。",
"render.stage_panels.reference": "參考",
"render.stage_panels.references": "參考",
"render.stage_panels.remove_optics": "移除光學設定",
"render.stage_panels.remove_optics_help": "從此鏡頭移除已儲存的光學設定。來源幾何會保留。",
"render.stage_panels.remove_optics_title": "要移除已儲存的光學設定嗎?",
"render.stage_panels.remove_shot": "移除鏡頭",
"render.stage_panels.remove_stage": "移除舞台",
"render.stage_panels.remove_stage_help": "從此鏡頭移除已儲存的被動面板。相機背景會保留。",
"render.stage_panels.remove_stage_title": "要移除已儲存的舞台嗎?",
"render.stage_panels.repeat": "重複",
"render.stage_panels.replaces": "取代內容",
"render.stage_panels.replaces_environment": "環境",
"render.stage_panels.replaces_maps": "所選實體上的暫時貼圖;已儲存的光學設定可能衝突。",
"render.stage_panels.replaces_physical": "無。此計畫為唯讀。",
"render.stage_panels.replaces_quality": "影像尺寸、固定取樣數、路徑深度、種子與降噪。",
"render.stage_panels.replaces_rig": "照明、環境與舞台",
"render.stage_panels.replaces_saved_maps": "所選實體上已儲存的表面貼圖;暫時覆寫可能衝突。",
"render.stage_panels.replaces_stage": "已儲存的地面與被動舞台面板",
"render.stage_panels.replaces_studio": "照明、環境、曝光與舞台",
"render.stage_panels.replaces_uniform": "所選實體上的不透明外觀。空間貼圖會以均勻值近似。",
"render.stage_panels.review_environment": "檢閱環境",
"render.stage_panels.review_maps": "檢閱 GPU 貼圖",
"render.stage_panels.review_physical": "物理參考計畫",
"render.stage_panels.review_quality": "使用固定取樣預算",
"render.stage_panels.review_rig": "擬合燈組",
"render.stage_panels.review_saved_maps": "檢閱已儲存的貼圖",
"render.stage_panels.review_stage": "檢閱地面與舞台",
"render.stage_panels.review_studio": "檢閱原生攝影棚",
"render.stage_panels.review_uniform": "檢閱均勻外觀",
"render.stage_panels.rig_summary": "原創燈組 · {emitters} 個發光體、{cards} 張卡片",
"render.stage_panels.rigs": "燈組",
"render.stage_panels.save_maps": "將貼圖儲存至此鏡頭",
"render.stage_panels.scope": "範圍",
"render.stage_panels.search_studios": "搜尋攝影棚",
"render.stage_panels.search_surfaces": "搜尋表面與參考",
"render.stage_panels.source_note": "原創基色來源貼圖。並非實測材質。",
"render.stage_panels.specifications": "規格 · 唯讀",
"render.stage_panels.studio_ack": "確認取代照明、環境、曝光與舞台",
"render.stage_panels.studio_note": "按一下以檢閱。套用時僅在確認後才會取代照明、環境與舞台。燈光仍可編輯。",
"render.stage_panels.studios": "攝影棚",
"render.stage_panels.subtitle_environment": "原創 HDR 環境 · 整個場景",
"render.stage_panels.subtitle_maps": "原創空間貼圖 · 暫時預覽",
"render.stage_panels.subtitle_physical": "唯讀計畫 · 不建立也不指派材質",
"render.stage_panels.subtitle_quality": "固定 GPU 預算 · 省略未來需求",
"render.stage_panels.subtitle_rig": "原創燈組 · 發光體與被動卡片",
"render.stage_panels.subtitle_saved_maps": "原創貼圖 · 隨此鏡頭儲存",
"render.stage_panels.subtitle_stage": "物理地面與舞台 · 依產品擬合",
"render.stage_panels.subtitle_studio": "原生攝影棚 · 套用於整個場景",
"render.stage_panels.subtitle_uniform": "均勻近似 · 並非實測材質",
"render.stage_panels.surfaces": "表面",
"render.stage_panels.surfaces_references": "表面與參考",
"render.stage_panels.target": "目標",
"render.stage_panels.use_budget": "使用此預算",
"render.stage_panels.use_maps": "使用 GPU 貼圖",
"render.stage_panels.use_uniform": "使用均勻外觀",
"render.stage_preview_note": "整合式預覽 · 直接光",
"render.state_completed": "已完成影像",
"render.state_in_progress": "影像進行中",
"render.state_model": "模型預覽",
"render.strip_label": "鏡頭列",
"render.studio_add_area": "新增面光源",
"render.studio_ambient": "恆定環境輻射亮度",
@@ -2518,8 +2933,10 @@
"render.studio_sky_help": "用於照明的原創天空漸層;並非經校準的大氣模型。",
"render.studio_sun": "太陽",
"render.studio_sun_radius": "角半徑",
"render.studio_tiles_require_gpu": "攝影棚需要 GPU 路徑追蹤。請在「輸出」編輯器中選擇 GPU。",
"render.studio_title": "彩現攝影棚",
"render.studio_tone_map": "色調對應",
"render.studios_environments": "攝影棚與環境",
"render.subsurface_enable": "內部散射隨機漫步",
"render.subsurface_help": "僅限封閉的介電質。散射係數與 RGB 吸收係數是各自獨立的每 mm 係數。光徑會在實際幾何內部散射,然後在邊界處折射或反射。請停用直接陰影穿透、表面降噪和外部體積,並使用單一菲涅爾分層。這不是擴散著色器、密度網格或實測材質。高密度介質可能需要更多取樣數和路徑深度。",
"render.subsurface_rate": "散射碰撞率",
@@ -2573,6 +2990,7 @@
"render.volume_max": "最大邊界 · 世界座標 mm",
"render.volume_min": "最小邊界 · 世界座標 mm",
"render.volume_title": "有界均質體積",
"render.wait_add_light": "尚未支援:建立具名燈光",
"render.wait_batch": "尚未支援:已儲存鏡頭的彩現佇列",
"render.wait_compare": "尚未支援:保留影像的比較",
"render.wait_paint": "尚未支援:產品拾取與外觀塗刷",
@@ -2627,6 +3045,7 @@
"select two components": "請選取兩個元件",
"set by the sketch's lines": "由草圖的線條決定",
"settings.display_quality_note": "等級越精細,曲面和邊顯示越平滑,但網格化耗時更長。只影響檢視區,不影響設計或匯出。",
"settings.double_click_components": "按兩下元件以啟用它,或就地編輯連結的元件",
"settings.frame_rate_details_note": "加入最近各影格耗時的圖表(疊加繪製的三角形數量)、影格耗時直方圖,以及 GPU 繪製的內容。點擊檢視中的影格率即可顯示或隱藏。",
"settings.frame_rate_note": "在檢視右下角顯示每秒影格數。",
"settings.measure_axis_distances": "顯示 X/Y/Z 距離",
@@ -2639,6 +3058,7 @@
"settings.reset_intro": "這些設定在此電腦上無法正常工作,會導致 SolidCraft 無法啟動,因此已變更:",
"settings.reset_title": "設定已變更",
"settings.supersampling_note": "以更高解析度繪製檢視再縮小:在低於 4K 的螢幕上邊、線和網格更平滑。會消耗 GPU 時間:1.5× 時約 2.25 倍像素,2× 時 4 倍。",
"settings.update_changed_links": "切換回分頁時,更新已變更的連結設計",
"settings.window_system_details": "詳細資料",
"settings.window_system_note_now": "重新啟動後生效。目前:{now}。",
"settings.window_system_wayland_limited": "在原生 Wayland 下部分功能受限。",
@@ -2685,6 +3105,10 @@
"sketch_text.path_hint": "文字所跟隨的草圖曲線:先點擊此處,再選擇曲線",
"sketch_text.use_font_file": "使用字型檔案 {path}",
"solid": "實體",
"status.editing": "正在編輯 {name}",
"status.under_constrained": "拘束不足({count} 個自由度)",
"status.under_constrained_one": "拘束不足({count} 個自由度)",
"status.units_tip": "設計的單位。按一下可變更",
"the angle must be a number": "角度必須是數字",
"the curves must be in one sketch": "曲線必須位於同一個草圖中",
"the direction must be an axis, a sketch line or a straight edge": "方向必須是軸、草圖直線或直邊",
@@ -2730,7 +3154,15 @@
"toolbar.customize_note": "{tab} 索引標籤。勾選命令可將其按鈕新增到工具列。您也可以將面板下拉選單中的某一行拖到工具列,將按鈕拖出工具列以移除,或使用下拉選單行中的固定圖示。",
"toolbar.image": "影像",
"toolbar.render": "彩現",
"toolbar.render_appearance": "外觀",
"toolbar.render_camera": "相機",
"toolbar.render_environment": "環境",
"toolbar.render_lighting": "照明",
"toolbar.render_lights": "燈光",
"toolbar.render_result": "結果",
"toolbar.render_scene": "場景",
"toolbar.render_stage": "佈景",
"toolbar.render_studio": "攝影棚",
"trace.points": "路徑上的 {count} 個點",
"trace.stopped_by_contact": "在取樣 {sample} 處結束:{a} 會穿過 {b}",
"trace.stopped_by_loop": "在取樣 {sample} 處結束:經過 {joint} 的環路無法再閉合",
@@ -3115,6 +3547,9 @@
"ui.blocked": "被遮擋",
"ui.bodies": "實體",
"ui.bodies_all_if_none": "實體(未選擇則全部)",
"ui.body_kind_mesh": "網格實體",
"ui.body_kind_solid": "實心實體",
"ui.body_kind_surface": "曲面實體",
"ui.bottom": "下視",
"ui.box": "長方體",
"ui.break": "打斷",
@@ -3209,6 +3644,7 @@
"ui.design_properties.part_number": "零件編號",
"ui.design_properties.project": "專案",
"ui.design_properties.revision": "修訂版本",
"ui.design_saved": "已儲存至 {path}",
"ui.diameter": "直徑",
"ui.dimension": "尺寸",
"ui.direct_interaction": "直接互動",
@@ -3234,6 +3670,24 @@
"ui.easyprint_uploading": "正在上傳到 Printables…",
"ui.edit": "編輯",
"ui.editJointLimits": "編輯接頭限制",
"ui.edit_in_place": "就地編輯",
"ui.edit_in_place_after_turn": "代理的回合結束時才會完成編輯",
"ui.edit_in_place_agent_busy": "代理仍在此設計中工作;請於其回合結束後再試",
"ui.edit_in_place_already_queued": "已有一項編輯在等待代理的回合結束",
"ui.edit_in_place_assembly_closed": "{name} 已關閉",
"ui.edit_in_place_banner": "正在 {name} 中編輯",
"ui.edit_in_place_busy": "請先完成或取消目前開啟的項目",
"ui.edit_in_place_none": "沒有正在就地編輯的連結設計",
"ui.edit_in_place_not_saved": "零件有尚未儲存的變更;請儲存以完成編輯",
"ui.edit_in_place_open_elsewhere": "{name} 已在另一個 SolidCraft 中開啟",
"ui.edit_in_place_opens_after_turn": "代理的回合結束時才會開啟零件",
"ui.edit_in_place_refresh_dropped": "更新連結執行期間組合件已變更;請再執行一次",
"ui.edit_in_place_refresh_stopped": "更新連結尚未完成就已停止",
"ui.edit_in_place_refreshing": "正在更新 {name} 中的連結…",
"ui.edit_in_place_save_first": "請先儲存組合件:其連結的設計是依其檔案找到的",
"ui.edit_in_place_save_waits": "{name} 正在執行更新連結;請待其完成後再儲存",
"ui.edit_in_place_saved_elsewhere": "零件已儲存到另一個檔案;組合件仍連結 {name}",
"ui.edit_in_place_wait": "請等待設計中正在執行的作業完成",
"ui.edit_section_analysis": "編輯截面分析",
"ui.ellipse": "橢圓",
"ui.emboss_wrap_note": "與受支援圓柱相切的正交線輪廓會自動纏繞。選取一個壁以指定目標。",
@@ -3308,6 +3762,7 @@
"ui.heading_edit": "編輯",
"ui.heading_extrude": "擠出",
"ui.heading_fillet": "圓角",
"ui.heading_finish_editing": "完成編輯",
"ui.heading_finish_sketch": "完成草圖",
"ui.heading_form": "造型",
"ui.heading_front": "前視",
@@ -3378,6 +3833,10 @@
"ui.history_marker_tip": "歷程標記:拖曳可回溯模型;新特徵會加在此處",
"ui.history_names": "名稱",
"ui.history_play": "播放到結尾",
"ui.history_play_button_hide": "隱藏播放按鈕",
"ui.history_play_button_show": "顯示播放按鈕",
"ui.history_play_finish_action": "播放歷程記錄前,請先完成目前的操作",
"ui.history_play_roll_back": "播放前,請先將歷程記錄標記往回移",
"ui.history_show_names": "顯示名稱",
"ui.history_sketch_listed_under": "列在 {feature} 之下",
"ui.history_title": "歷程記錄",
@@ -3505,6 +3964,7 @@
"ui.pinToShortcuts": "固定到快捷方式",
"ui.pinToToolbar": "固定到工具列",
"ui.pipe": "管道",
"ui.pitch": "螺距",
"ui.placement": "放置",
"ui.placement_handles": "放置控點",
"ui.placement_handles_tip": "墊塊、凸座或卡扣預覽上的控點:拖曳標記可在模型上移動,拖曳其環可旋轉",
@@ -3519,6 +3979,15 @@
"ui.plugins_skipped": "有 {count} 個資料夾無法讀取。",
"ui.plugins_version": "{version}",
"ui.point": "點",
"ui.point_cloud_auto_range": "自動範圍",
"ui.point_cloud_color_by": "顏色依據",
"ui.point_cloud_file_colors": "檔案顏色",
"ui.point_cloud_height_high": "最高",
"ui.point_cloud_height_low": "最低",
"ui.point_cloud_no_file_colors": "檔案沒有顏色",
"ui.point_cloud_single_color": "單一顏色",
"ui.point_cloud_size": "點大小",
"ui.point_cloud_units": "檔案單位",
"ui.point_under_the_cursor": "游標下的點",
"ui.points": "點",
"ui.polygon": "多邊形",
@@ -3566,6 +4035,10 @@
"ui.restore_defaults": "還原預設值",
"ui.reverse_horizontal_pan_direction": "反轉水平平移方向",
"ui.reverse_horizontal_pan_tip": "水平雙指捲動和拇指滾輪向相反方向平移",
"ui.reverse_trackpad_orbit_direction": "反轉觸控板環轉方向",
"ui.reverse_trackpad_orbit_tip": "Shift 搭配雙指捲動會朝相反方向環轉",
"ui.reverse_vertical_pan_direction": "反轉垂直平移方向",
"ui.reverse_vertical_pan_tip": "垂直雙指捲動時改往相反方向平移",
"ui.reverse_zoom_direction": "反轉縮放方向",
"ui.revolutions": "圈數",
"ui.revolve": "旋轉",
@@ -3711,7 +4184,22 @@
"ui.updateToCurrentView": "更新為目前檢視",
"ui.upload": "上傳",
"ui.vertical_constraint": "垂直拘束",
"ui.view_angles": "檢視角度",
"ui.view_angles_convention": "以向上軸為準的角度(單位為度)。偏航 0° 為前視圖,90° 為左視圖,−90° 為右視圖,180° 為後視圖;俯仰 90° 為俯視圖;滾轉為正值時,模型順時針轉動。",
"ui.view_angles_help": "在方向控制器下方顯示檢視的俯仰、偏航與滾轉角度(單位為度)及其投影方式。按一下讀值即可輸入精確角度。",
"ui.view_angles_ortho": "正交",
"ui.view_angles_persp": "透視",
"ui.view_angles_pitch": "俯仰",
"ui.view_angles_readout": "俯仰 {pitch} · 偏航 {yaw} · 滾轉 {roll}",
"ui.view_angles_roll": "滾轉",
"ui.view_angles_yaw": "偏航",
"ui.view_centre": "檢視中心",
"ui.viewport_status_clear": "關閉 {name}",
"ui.viewport_status_clear_hint": "關閉 {name} · Esc",
"ui.viewport_status_key": "顯示 {name} 的圖例",
"ui.viewport_status_minimum_radius": "最小半徑",
"ui.viewport_status_pairs": "{count} 對",
"ui.viewport_status_stripes": "{count} 道條紋",
"ui.viewport_theme_follow": "跟隨主題",
"ui.visual_shaded_hidden_edges": "含隱藏邊的著色",
"ui.visual_shaded_with_edges": "含邊線的著色",
@@ -3782,6 +4270,7 @@
"values must be finite numbers": "值必須是有限數字",
"values must be numbers or expressions": "值必須是數字或運算式",
"view.auto_ortho_faces": "環轉時使用透視,正對面時使用正交",
"view.render_inspector": "彩現檢查器",
"web.files.insert_drawings_hint": "將 CAD 檔案、網格、DXF 或 SVG 插入目前開啟的設計",
"web.files.insert_stored_drawings_hint": "插入目前開啟的設計(CAD 檔案、網格、DXF、SVG)",
"web.open_full": "在 SolidCraft 中開啟",
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -7,7 +7,7 @@ pub const DEFAULT_MATERIAL: &str = "Default";
pub const DEFAULT_DENSITY: f64 = 1.29;
/// Physical materials: name and density (g/cm³).
pub const MATERIALS: [(&str, f64); 14] = [
pub const MATERIALS: &[(&str, f64)] = &[
(DEFAULT_MATERIAL, DEFAULT_DENSITY),
("Steel", 7.85),
("Stainless Steel", 8.0),
+79
View File
@@ -18,6 +18,8 @@ struct U {
depth: vec4<f32>, // x = 1: reversed depth (1 near, 0 far); y, z: the faces' push (`FACE_BIAS`)
tint: vec4<f32>, // xyz added to a whole hovered body's colour before lighting
sel: vec4<f32>, // xyz a whole selected body's colour before lighting
product_lights_meta: vec4<f32>, // explicit preview flag and bounded count
product_lights: array<vec4<f32>,84>, // position/kind, radiance, axis/cone, attenuation
};
fn reversed() -> bool {
@@ -471,6 +473,36 @@ fn shade(i: TOut) -> vec4<f32> {
return lit(i, 1.0);
}
fn product_light_unit(v: vec3<f32>) -> vec3<f32> {
let scale=max(max(abs(v.x),abs(v.y)),abs(v.z));
if scale == 0.0 { return vec3<f32>(0.0,0.0,1.0); }
return normalize(v/scale);
}
// Direction and incident radiance for an unshadowed analytic preview sample.
fn product_light_sample(k: u32, p: vec3<f32>) -> mat2x3<f32> {
let source=u.product_lights[k*4u];
let colour=u.product_lights[k*4u+1u];
let axis=u.product_lights[k*4u+2u];
let falloff=u.product_lights[k*4u+3u];
var direction=product_light_unit(source.xyz);
var weight=1.0;
if source.w > 0.5 {
let delta=source.xyz-p;
let distance=max(length(delta),falloff.y);
direction=product_light_unit(delta);
weight=falloff.x/max(distance*distance,0.000001);
if source.w == 2.0 {
let cosine=dot(product_light_unit(axis.xyz),-direction);
var cone=select(0.0,1.0,cosine>=colour.w);
if axis.w-colour.w>0.000001 {cone=smoothstep(colour.w,axis.w,cosine);}
weight *= cone;
}
if source.w == 3.0 {weight *= max(dot(product_light_unit(axis.xyz),-direction),0.0);}
}
return mat2x3<f32>(direction,colour.xyz*weight);
}
fn lit(i: TOut, visibility: f32) -> vec4<f32> {
return lit_color(i, visibility, i.c);
}
@@ -485,6 +517,17 @@ fn lit_color(i: TOut, visibility: f32, base: vec4<f32>) -> vec4<f32> {
let v = normalize(u.back.xyz);
var n = normalize(i.n);
if (dot(n, v) < 0.0) { n = -n; }
if u.product_lights_meta.x>0.0 {
var radiance=vec3<f32>(0.0);
for (var k=0u;k<min(u32(u.product_lights_meta.y),21u);k+=1u) {
if u.product_lights[k*4u].w == 4.0 {radiance+=to_linear(base.rgb)*u.product_lights[k*4u+1u].xyz/3.141592653589793;continue;}
let sample=product_light_sample(k,i.wp);
radiance+=to_linear(base.rgb)*sample[1]*(max(dot(n,sample[0]),0.0)/3.141592653589793);
}
let mapped=radiance/(vec3<f32>(1.0)+radiance);
let encoded=select(mapped*12.92,1.055*pow(mapped,vec3<f32>(1.0/2.4))-vec3<f32>(0.055),mapped>vec3<f32>(0.0031308));
return out_color(vec4<f32>(encoded,base.a));
}
let key = normalize(v * 0.8 + vec3<f32>(-0.3, 0.2, 0.6));
let diff = max(dot(n, key), 0.0);
let fill = max(dot(n, v), 0.0);
@@ -653,3 +696,39 @@ fn fs_img(i: IOut) -> @location(0) vec4<f32> {
fn fs_line_all(i: LOut) -> @location(0) vec4<f32> {
return out_color(i.c);
}
// Point clouds: each point is a round dot a few pixels across, facing the screen, depth-tested
// and written like the model's faces, so the model hides the points behind it and they hide it.
// The colour's alpha carries the dot's size (eighths of a pixel).
struct POut {
@builtin(position) pos: vec4<f32>,
@location(0) c: vec4<f32>,
@location(1) wp: vec3<f32>,
@location(2) at: vec2<f32>,
};
@vertex
fn vs_point(@builtin(vertex_index) vi: u32, @location(0) p: vec3<f32>, @location(1) c: vec4<f32>) -> POut {
var xs = array<f32, 6>(-1.0, 1.0, 1.0, -1.0, 1.0, -1.0);
var ys = array<f32, 6>(-1.0, -1.0, 1.0, -1.0, 1.0, 1.0);
let at = vec2<f32>(xs[vi], ys[vi]);
let size = max(c.a * 255.0 / 8.0, 1.0);
let centre = u.vp * vec4<f32>(p, 1.0);
let half = u.screen.xy * 0.5;
var o: POut;
o.pos = vec4<f32>(centre.xy + at * size * 0.5 / half * centre.w, centre.z, centre.w);
// Behind the eye: nothing.
if (near_z(centre) < 0.0) { o.pos = vec4<f32>(0.0, 0.0, 0.0, -1.0); }
o.c = vec4<f32>(c.rgb, 1.0);
o.wp = p;
// Dots under two pixels are squares: a disc that small loses its centre pixel.
o.at = at * select(1.0, 0.0, size < 2.0);
return o;
}
@fragment
fn fs_point(i: POut) -> @location(0) vec4<f32> {
if (clipped(i.wp) || dot(i.at, i.at) > 1.0) { discard; }
return out_color(i.c);
}
+9
View File
@@ -193,6 +193,8 @@ impl Tokens {
sketch_halo: Color32::from_rgb(240, 243, 247),
sketch_point: Color32::BLACK,
sketch_locked: Color32::from_rgb(0, 140, 60),
// The error red (`error`).
sketch_conflict: Color32::from_rgb(214, 54, 54),
// Sketch dimensions in a plum of their own, apart from the blue and black curves for
// every colour vision mode (#7861).
dimension: Color32::from_rgb(130, 42, 110),
@@ -343,6 +345,7 @@ impl Tokens {
t.selected_bg = Color32::from_rgb(42, 70, 110);
t.construction_geom = icon_primary(crate::icon_svg::CONSTRUCTION_PRIMARY[1]);
t.error = Color32::from_rgb(240, 100, 96);
t.sketch_conflict = t.error;
t.warning = Color32::from_rgb(236, 170, 70);
t.icon = Color32::from_rgb(208, 214, 226);
t.timeline = Color32::from_rgb(33, 37, 45);
@@ -413,6 +416,9 @@ impl Tokens {
}
t.construction_geom = icon_primary(crate::icon_svg::CONSTRUCTION_RED_GREEN[dark as usize]);
t.glyph_text = icon_primary(crate::icon_svg::CONSTRAINT_RED_GREEN[dark as usize]);
// A deeper red keeps conflicting sketch geometry (#7244) apart from the orange
// construction and centerline lines and the crimson lost links for a red-green loss.
t.sketch_conflict = Color32::from_rgb(195, 35, 30);
t.surface_accent = if dark { Color32::from_rgb(200, 135, 55) } else { Color32::from_rgb(164, 80, 0) };
t.mesh_accent = if dark { Color32::from_rgb(190, 175, 70) } else { Color32::from_rgb(130, 103, 0) };
t.form_accent = if dark { Color32::from_rgb(165, 135, 220) } else { Color32::from_rgb(115, 73, 205) };
@@ -443,6 +449,9 @@ impl Tokens {
t.preview_sketch = Color32::from_rgb(125, 180, 105);
t.glyph_text = icon_primary(crate::icon_svg::CONSTRAINT_BLUE_YELLOW[dark as usize]);
t.construction_geom = icon_primary(crate::icon_svg::CONSTRUCTION_BLUE_YELLOW[dark as usize]);
// Conflicting sketch geometry (#7244) apart from the lost links and the construction and
// centerline lines for a blue-yellow loss: darker on the light view, lighter on the dark.
t.sketch_conflict = if dark { Color32::from_rgb(255, 170, 160) } else { Color32::from_rgb(165, 15, 30) };
if dark {
t.sketch_locked = Color32::from_rgb(140, 225, 110);
t.box_crossing = Color32::from_rgb(240, 110, 170);
+3
View File
@@ -1,4 +1,6 @@
{
"order": 76,
"provenance": "Original black-and-white palette",
"base": "dark",
"colors": {
"accent": "#ffffff",
@@ -142,6 +144,7 @@
"sketch": "#ffffff",
"sketch_accent": "#ffffff",
"sketch_centerline": "#ffffff",
"sketch_conflict": "#ffffff",
"sketch_construction": "#ffffff",
"sketch_fixed": "#ffffff",
"sketch_halo": "#000000",
+3
View File
@@ -1,4 +1,6 @@
{
"order": 75,
"provenance": "Original black-and-white palette",
"base": "light",
"colors": {
"accent": "#000000",
@@ -142,6 +144,7 @@
"sketch": "#000000",
"sketch_accent": "#000000",
"sketch_centerline": "#000000",
"sketch_conflict": "#000000",
"sketch_construction": "#000000",
"sketch_fixed": "#000000",
"sketch_halo": "#ffffff",
+2
View File
@@ -1,4 +1,6 @@
{
"order": 220,
"provenance": "Maps the Okibi design system",
"base": "light",
"colors": {
"accent": "#c63a00",
@@ -1,4 +1,6 @@
{
"order": 110,
"provenance": "Original SolidCraft theme",
"base": "dark",
"colors": {
"accent": "#ffbc48",
+2
View File
@@ -1,4 +1,6 @@
{
"order": 120,
"provenance": "Original SolidCraft theme",
"base": "dark",
"colors": {
"accent": "#66ddff",
@@ -1,4 +1,6 @@
{
"order": 200,
"provenance": "Original SolidCraft mapping of Catppuccin (MIT palette)",
"base": "dark",
"colors": {
"accent": "#cba6f7",
+3
View File
@@ -1,4 +1,6 @@
{
"order": 250,
"provenance": "Original mapping of the IBM Color Graphics Adapter palette",
"base": "dark",
"colors": {
"accent": "#55ffff",
@@ -142,6 +144,7 @@
"sketch": "#55ffff",
"sketch_accent": "#ff55ff",
"sketch_centerline": "#ffff55",
"sketch_conflict": "#ff5555",
"sketch_construction": "#aaaaaa",
"sketch_fixed": "#ffffff",
"sketch_halo": "#000000",
+2
View File
@@ -1,4 +1,6 @@
{
"order": 240,
"provenance": "Original warm paper and charcoal palette",
"base": "dark",
"colors": {
"accent": "#e8845e",
+2
View File
@@ -1,4 +1,6 @@
{
"order": 230,
"provenance": "Original warm paper and charcoal palette",
"base": "light",
"colors": {
"accent": "#bf5634",
+2
View File
@@ -1,4 +1,6 @@
{
"order": 90,
"provenance": "Original SolidCraft theme",
"base": "light",
"colors": {
"accent": "#007aff",
+2
View File
@@ -1,4 +1,6 @@
{
"order": 180,
"provenance": "Original SolidCraft theme",
"base": "dark",
"colors": {
"accent": "#4aa3d8",
@@ -1,4 +1,6 @@
{
"order": 100,
"provenance": "Original SolidCraft theme",
"base": "dark",
"colors": {
"accent": "#4dff79",
@@ -1,4 +1,6 @@
{
"order": 20,
"provenance": "Original SolidCraft mapping of Gruvbox (MIT palette)",
"format": "solidcraft-theme/1",
"name": "Gruvbox Dark Hard",
"base": "dark",
@@ -1,4 +1,6 @@
{
"order": 30,
"provenance": "Original SolidCraft mapping of Gruvbox (MIT palette)",
"format": "solidcraft-theme/1",
"name": "Gruvbox Dark Soft",
"base": "dark",
@@ -1,4 +1,6 @@
{
"order": 10,
"provenance": "Original SolidCraft mapping of Gruvbox (MIT palette)",
"format": "solidcraft-theme/1",
"name": "Gruvbox Dark",
"base": "dark",
@@ -1,4 +1,6 @@
{
"order": 50,
"provenance": "Original SolidCraft mapping of Gruvbox (MIT palette)",
"format": "solidcraft-theme/1",
"name": "Gruvbox Light Hard",
"base": "light",
@@ -1,4 +1,6 @@
{
"order": 60,
"provenance": "Original SolidCraft mapping of Gruvbox (MIT palette)",
"format": "solidcraft-theme/1",
"name": "Gruvbox Light Soft",
"base": "light",
@@ -1,4 +1,6 @@
{
"order": 40,
"provenance": "Original SolidCraft mapping of Gruvbox (MIT palette)",
"format": "solidcraft-theme/1",
"name": "Gruvbox Light",
"base": "light",
@@ -1,4 +1,6 @@
{
"order": 170,
"provenance": "Original SolidCraft theme",
"base": "dark",
"colors": {
"accent": "#00bfff",
+2
View File
@@ -1,4 +1,6 @@
{
"order": 160,
"provenance": "Original SolidCraft mapping of Nord (MIT palette)",
"base": "dark",
"colors": {
"accent": "#88c0d0",
+2
View File
@@ -1,4 +1,6 @@
{
"order": 190,
"provenance": "Original SolidCraft mapping of Dracula (MIT palette)",
"base": "dark",
"colors": {
"accent": "#bd93f9",
+2
View File
@@ -1,4 +1,6 @@
{
"order": 210,
"provenance": "Maps the Okibi design system",
"base": "dark",
"colors": {
"accent": "#ff7c50",
+2
View File
@@ -1,4 +1,6 @@
{
"order": 130,
"provenance": "Original SolidCraft mapping of Atom One Dark (MIT palette)",
"base": "dark",
"colors": {
"accent": "#61afef",
+2
View File
@@ -1,4 +1,6 @@
{
"order": 80,
"provenance": "Original SolidCraft theme",
"base": "light",
"colors": {
"accent": "#555599",
@@ -1,4 +1,6 @@
{
"order": 150,
"provenance": "Original SolidCraft mapping of Solarized (MIT palette)",
"base": "light",
"colors": {
"accent": "#268bd2",
@@ -1,4 +1,6 @@
{
"order": 70,
"provenance": "Original SolidCraft theme",
"base": "light",
"colors": {
"accent": "#000080",
+2
View File
@@ -1,4 +1,6 @@
{
"order": 140,
"provenance": "Original SolidCraft mapping of Tokyo Night (MIT palette)",
"base": "dark",
"colors": {
"accent": "#7aa2f7",
+10 -8
View File
@@ -747,7 +747,7 @@ mod tests {
fn stable_ids_categories_and_original_licences_cover_the_requested_pack() {
let mut ids = BTreeSet::new();
let mut names = BTreeSet::new();
for preset in &STARTER_PACK {
for preset in STARTER_PACK {
assert!(preset.id.starts_with("starter.") && preset.id.len() <= 128);
assert!(preset.id.bytes().all(|b| b.is_ascii_lowercase() || b.is_ascii_digit() || b == b'.' || b == b'-'));
assert!(ids.insert(preset.id));
@@ -767,14 +767,14 @@ mod tests {
(Category::Solar, 2),
(Category::Regolith, 4),
] {
assert_eq!(STARTER_PACK.iter().filter(|p| p.category == category).count(), count);
assert!(STARTER_PACK.iter().filter(|p| p.category == category).count() >= count);
}
}
#[test]
fn opaque_construction_and_owned_look_roundtrip_preserve_current_response() {
let mut admitted = 0;
for preset in &STARTER_PACK {
for preset in STARTER_PACK {
if let Recipe::Opaque(recipe) = preset.recipe {
let look = preset.opaque_look().unwrap();
assert_eq!(look.opacity, 1.0);
@@ -789,7 +789,7 @@ mod tests {
admitted += 1;
}
}
assert_eq!(admitted, 34);
assert!(admitted >= 34);
}
#[test]
@@ -821,8 +821,10 @@ mod tests {
#[test]
fn legacy_library_and_six_existing_finish_names_are_not_overridden_or_duplicated() {
assert_eq!(crate::appearance::LIBRARY.len(), 20);
for (name, color, opacity) in crate::appearance::LIBRARY {
assert!(!crate::appearance::LIBRARY.is_empty());
let mut names = BTreeSet::new();
for &(name, color, opacity) in crate::appearance::LIBRARY {
assert!(!name.is_empty() && names.insert(name.to_ascii_lowercase()));
let look = crate::appearance::library(name).unwrap();
assert_eq!(look.color, color);
assert_eq!(look.opacity, opacity);
@@ -844,7 +846,7 @@ mod tests {
#[test]
fn uniform_previews_and_planned_resource_scale_are_explicit_and_not_bindings() {
let mut recipes = 0;
for preset in &STARTER_PACK {
for preset in STARTER_PACK {
if let Some(recipe) = preset.future_texture_recipe {
assert!(preset.name.contains("Uniform Preview"));
assert!(preset.preview_note.contains("Uniform opaque preview only"));
@@ -855,7 +857,7 @@ mod tests {
recipes += 1;
}
}
assert_eq!(recipes, 14);
assert!(recipes >= 14);
}
}
}
+8
View File
@@ -255,6 +255,14 @@ pub fn map_point_expr(m: &Mat, p: &mut crate::PointExpr) {
}
}
/// Map a displacement given as length expressions, retaining its parameter dependencies.
/// Unlike a point, a displacement is unaffected by the frame's translation.
pub fn map_vector_expr(m: &Mat, v: &mut crate::PointExpr) {
let mut rotation = *m;
rotation[3] = [0.0, 0.0, 0.0, 1.0];
map_point_expr(&rotation, v);
}
impl FeatureKind {
/// Map the feature's world geometry (points, directions, explicit planes) by `m`.
pub fn transform_geometry(&mut self, m: &Mat) {
+10 -4
View File
@@ -215,10 +215,16 @@ fn named_vertex(st: &ModelState, at: Vec3, names: &[String]) -> Option<Vec3> {
let ends: Vec<[Vec3; 2]> = names
.iter()
.map(|n| {
// The edge with that name itself, never the one nearest the old pick.
let on = bodies(st).find_map(|b| crate::naming::find_edge(b, n, at).ok())?.0;
let pts = edge_points(st, on, &None).ok()?;
Some([*pts.first()?, *pts.last()?])
// The edge with that name itself, never the one nearest the old pick, and its ends
// on the body that has it: picked again by a point on it, a corner found the first
// edge of any body through that corner, such as another body's edge running past
// it, so a vertex took that edge's end (#8650).
bodies(st).find_map(|b| {
let hit = crate::name_lookup::locate_edge(b, n, at).ok()?;
let m = b.mesh();
let pts = m.edges.get(hit.edge)?;
Some([*pts.first()?, *pts.last()?])
})
})
.collect::<Option<_>>()?;
let (first, rest) = ends.split_first()?;
+9 -3
View File
@@ -2727,6 +2727,9 @@ pub struct Document {
/// Reference images on planes (Insert Canvas).
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub canvases: Vec<crate::canvas::Canvas>,
/// Scanned points kept as a reference (Insert Point Cloud).
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub point_clouds: Vec<crate::point_cloud::PointCloud>,
/// Comments of feature-input parameters (by name).
#[serde(default, skip_serializing_if = "std::collections::BTreeMap::is_empty")]
pub param_comments: std::collections::BTreeMap<String, String>,
@@ -2932,6 +2935,7 @@ impl Document {
.map(|g| g.id)
.chain(self.timeline_groups.iter().map(|g| g.id))
.chain(self.canvases.iter().map(|c| c.id))
.chain(self.point_clouds.iter().map(|c| c.id))
.chain(a.joints.iter().map(|j| j.id))
.chain(a.contact_sets.iter().map(|c| c.id))
.chain(a.studies.iter().map(|s| s.id))
@@ -2979,6 +2983,7 @@ impl Document {
appearances: Default::default(),
favorites: Default::default(),
canvases: Vec::new(),
point_clouds: Vec::new(),
param_comments: Default::default(),
browser_groups: Vec::new(),
timeline_groups: Vec::new(),
@@ -3346,12 +3351,13 @@ impl Document {
Ok(id)
}
/// A component by id or name (0 / "root" is the design itself).
/// A component by id or name (0 / "root" is the design itself). A component that carries the
/// design's own name is found by that name: the design is still named by 0 / "root".
pub fn find_component(&self, key: &str) -> Option<u64> {
if key == "0" || key.eq_ignore_ascii_case("root") || key == self.name {
if key == "0" || key.eq_ignore_ascii_case("root") {
return Some(0);
}
self.components.iter().find(|c| c.id.to_string() == key || c.name == key).map(|c| c.id)
self.components.iter().find(|c| c.id.to_string() == key || c.name == key).map(|c| c.id).or_else(|| (key == self.name).then_some(0))
}
/// Read a design file's JSON (any format this build knows; older ones are upgraded).
+1 -1
View File
@@ -216,7 +216,7 @@ fn a_fixed_unit_is_a_length_unit_of_the_expression_table() {
read(&v).map(|d| d.units)
};
for (unit, kind, _) in expr::UNITS {
assert_eq!(units(json!({"fixed": {"unit": unit}})).is_ok(), kind == expr::Kind::Length, "{unit}");
assert_eq!(units(json!({"fixed": {"unit": unit}})).is_ok(), *kind == expr::Kind::Length, "{unit}");
}
assert_eq!(units(json!({"fixed": {"unit": "in"}})).unwrap(), Units::Fixed { unit: "in".into() });
assert_eq!(units(json!("follow_model")).unwrap(), Units::FollowModel);
+24 -12
View File
@@ -1865,6 +1865,14 @@ fn placement_digest(doc: &Document, f: &Feature, st: Option<&ModelState>) -> u64
reads.placed_body(st, tool);
}
}
// A pattern of bodies copies them along its directions or about its axis in its own
// component's frame, so it follows where each body it copies is placed relative to that
// frame: copies of a root block, patterned in a component, move with the component.
FeatureKind::Pattern { bodies, .. } if !bodies.is_empty() => {
for b in bodies {
reads.placed_body(st, &b.0);
}
}
// Joins, cuts and intersects meet their targets where those are placed (#3383).
kind if drawn_tools_change_bodies(kind) => reads.drawn_targets(st, f),
FeatureKind::Sketch { plane, sketch } => {
@@ -2721,10 +2729,22 @@ fn note_join_apart(before: &ModelState, after: &ModelState, f: &Feature, warning
if operation != Operation::Join {
return;
}
for (name, n) in join_pieces_added(before, after) {
append_warning(
warning,
format!("the joined piece doesn't touch `{name}`, so `{name}` is now in {n} separate pieces (New Body makes it a body of its own)"),
);
}
}
/// The bodies a Join from `before` to `after` left in more separate pieces than it found, with
/// their piece counts now: empty when the joined material made one body with what it touched
/// (or bridged pieces). A lid closing a cavity adds a void, not a piece.
pub fn join_pieces_added(before: &ModelState, after: &ModelState) -> Vec<(String, usize)> {
let pieces = |b: &Body| b.lumps().map_or(1, |l| l.len());
// Pieces of the bodies the join changed or absorbed before it, and of those it kept after.
let (mut had, mut have) = (0usize, 0usize);
let mut grown: Vec<(&str, usize)> = Vec::new();
let mut grown: Vec<(String, usize)> = Vec::new();
for was in &before.bodies {
match after.body(&was.name) {
Some(now) if now.body.same_shape(&was.body) => {}
@@ -2733,21 +2753,13 @@ fn note_join_apart(before: &ModelState, after: &ModelState, f: &Feature, warning
had += old;
have += new;
if new > old {
grown.push((now.name.as_str(), new));
grown.push((now.name.clone(), new));
}
}
None => had += pieces(&was.body),
}
}
if have <= had {
return;
}
for (name, n) in grown {
append_warning(
warning,
format!("the joined piece doesn't touch `{name}`, so `{name}` is now in {n} separate pieces (New Body makes it a body of its own)"),
);
}
if have <= had { Vec::new() } else { grown }
}
/// Add tool bodies to the model according to the operation.
@@ -6240,7 +6252,7 @@ pub fn pattern_matrices(doc: &Document, st: &ModelState, p: &crate::PatternKind)
fn pattern_transforms(doc: &Document, vals: &BTreeMap<String, Value>, st: &ModelState, component: u64, p: &crate::PatternKind) -> Result<Vec<Mat>> {
let count = |e: &str| -> Result<usize> {
let n = val(vals, e, Kind::Unitless)?.round();
let n = expr::eval_count(e, vals)?;
if !(1.0..=MAX_INSTANCES as f64).contains(&n) {
return Err(DocError::Invalid(format!("pattern count must be 1…{MAX_INSTANCES}")));
}
+59 -5
View File
@@ -127,7 +127,7 @@ impl Kind {
}
/// Units a parameter or an expression may use: name, kind and size (mm or radians).
pub const UNITS: [(&str, Kind, f64); 14] = [
pub const UNITS: &[(&str, Kind, f64)] = &[
("mm", Kind::Length, 1.0),
("cm", Kind::Length, 10.0),
("m", Kind::Length, 1000.0),
@@ -145,7 +145,7 @@ pub const UNITS: [(&str, Kind, f64); 14] = [
];
/// Functions an expression may call (name, signature) — for autocomplete and help.
pub const FUNCTIONS: [(&str, &str); 23] = [
pub const FUNCTIONS: &[(&str, &str)] = &[
("sin", "sin(angle)"),
("cos", "cos(angle)"),
("tan", "tan(angle)"),
@@ -172,7 +172,7 @@ pub const FUNCTIONS: [(&str, &str); 23] = [
];
/// Constants an expression may use.
pub const CONSTANTS: [&str; 2] = ["pi", "PI"];
pub const CONSTANTS: &[&str] = &["pi", "PI"];
/// Kind and size (mm or radians per unit) of a parameter's unit; empty means unit-less.
pub fn unit_info(u: &str) -> Option<(Kind, f64)> {
@@ -352,6 +352,14 @@ fn lex_spans(s: &str) -> Result<Vec<(Tok, usize, usize)>, DocError> {
{
i = k + 1;
}
// A value typed as a definition, `name = expression` (#4071), is worth its expression: the
// name is what it defines, not part of it (`Document::define_inline` stores it apart).
if i == 0
&& definition(s).is_some()
&& let Some(eq) = s.find('=')
{
i = cs.iter().position(|(b, _)| *b > eq).unwrap_or(cs.len());
}
while let Some(&(_, c)) = cs.get(i) {
if c.is_whitespace() {
i += 1;
@@ -565,6 +573,10 @@ pub fn rename_reference(s: &str, old: &str, new: &str) -> String {
/// Is the expression just a number (with an optional unit), like `20`, `20 mm` or `-1.5 in`?
pub fn is_literal(s: &str) -> bool {
// A definition names its value: it is not just a number, whatever it defines (#4071).
if definition(s).is_some() {
return false;
}
let Ok(toks) = lex(s) else { return false };
let toks: &[Tok] = match toks.first() {
Some(Tok::Op('-' | '+')) => toks.get(1..).unwrap_or_default(),
@@ -592,8 +604,8 @@ fn is_name_shaped(s: &str) -> bool {
/// A value typed as a definition, `name = expression` (or `#name = expression`, #2371): the name
/// without the `#` and the text after the first `=`, both trimmed (the text may be empty). `None` for anything else, including text whose
/// left side is not shaped like a name (`2 = 3`), which stays an ordinary expression and fails
/// to parse as before. The dimension input defines a user parameter this way (#2916); other
/// value inputs can take the same form later.
/// to parse as before. Every value input defines a user parameter this way (#2916, #4071): until
/// `Document::define_inline` stores the parameter, the text evaluates as its expression.
pub fn definition(s: &str) -> Option<(&str, &str)> {
let (name, rhs) = s.split_once('=')?;
let name = name.trim();
@@ -970,6 +982,24 @@ fn call(f: &str, args: &[Value], d: Defaults) -> Result<Value, DocError> {
})
}
/// Evaluate a count: a unit-less whole number. A length or angle says how to fix it, and a
/// fraction is refused rather than rounded to a different number of copies.
pub fn eval_count(s: &str, vals: &BTreeMap<String, Value>) -> Result<f64, DocError> {
let e = s.trim();
let value = eval_with(e, &|n| vals.get(n).copied().ok_or_else(|| DocError::Expr(format!("unknown parameter `{n}`"))))?;
if let Some(kind @ (Kind::Length | Kind::Angle)) = value.kind() {
let subject = if vals.contains_key(e) { format!("`{e}`") } else { "this expression".into() };
let remedy = if vals.contains_key(e) { "set its Unit to none to use it as a count" } else { "use a unit-less expression as a count" };
return Err(DocError::Expr(format!("{subject} is {} ({}); {remedy}", value.describe(), kind.default_unit())));
}
let n = value.to_kind(Kind::Unitless)?;
// Allow float noise such as `10 / 3 * 3`, never a real fraction.
if !n.is_finite() || (n - n.round()).abs() > 1e-9 {
return Err(DocError::Expr(format!("a count must be a whole number; `{e}` is {n}")));
}
Ok(n.round())
}
/// Evaluate an expression; `lookup` resolves parameter names. Bare numbers are mm / degrees.
pub fn eval_with(s: &str, lookup: &dyn Fn(&str) -> Result<Value, DocError>) -> Result<Value, DocError> {
eval_with_defaults(s, lookup, Defaults::default())
@@ -979,6 +1009,9 @@ pub fn eval_with(s: &str, lookup: &dyn Fn(&str) -> Result<Value, DocError>) -> R
pub fn eval_with_defaults(s: &str, lookup: &dyn Fn(&str) -> Result<Value, DocError>, defaults: Defaults) -> Result<Value, DocError> {
let (toks, spans): (Vec<Tok>, Vec<(usize, usize)>) = lex_spans(s)?.into_iter().map(|(t, a, b)| (t, (a, b))).unzip();
if toks.is_empty() {
if let Some((name, _)) = definition(s) {
return Err(DocError::Expr(format!("`{name} =` needs a value after the `=`")));
}
return Err(DocError::Expr("empty expression".into()));
}
let mut p = Parser { toks, spans, pos: 0, lookup, depth: 0, defaults };
@@ -1470,6 +1503,27 @@ mod tests {
}
}
/// Until the design stores it, a definition is worth its expression (#4071): the name is
/// not a reference, it is never a plain number, and it renames like its expression.
#[test]
fn a_definition_evaluates_as_its_expression() {
let look = |n: &str| if n == "a" { Ok(Value::length(4.0)) } else { Err(DocError::Expr(format!("unknown parameter `{n}`"))) };
let ev = |s: &str| eval_with(s, &look).and_then(|v| v.to_kind(Kind::Length));
assert_eq!(ev("w = 20").ok(), Some(20.0));
assert_eq!(ev("#w = a * 2").ok(), Some(8.0));
assert_eq!(ev("szerokość=1 in").ok(), Some(25.4));
assert_eq!(references("w = a + b"), ["a", "b"]);
assert!(references("w = 3").is_empty());
assert_eq!(rename_reference("w = a * 2", "a", "len"), "w = len * 2");
assert_eq!(rename_reference("a = a * 2", "a", "len"), "a = len * 2");
assert!(!is_literal("w = 20") && !is_bare_number("w = 20"));
assert!(ev("w = w").unwrap_err().to_string().contains("unknown parameter `w`"));
assert!(ev("w =").unwrap_err().to_string().contains("`w =` needs a value after the `=`"));
for bad in ["w = = 3", "2 = 3", "w == 3", "w = 3 = 4", "= 5 ="] {
assert!(ev(bad).is_err(), "{bad}");
}
}
/// A reserved name is refused by saying what kind of word it is.
#[test]
fn a_reserved_name_is_refused_by_its_kind() {
+9 -10
View File
@@ -716,6 +716,7 @@ pub fn read(s: &str) -> Result<Document> {
{
return Err(DocError::Invalid("document too large".into()));
}
crate::point_cloud::check_all(&d.point_clouds)?;
let feature_ids: std::collections::BTreeSet<_> = d.features.iter().map(|feature| feature.id).collect();
let mut group_ids = std::collections::BTreeSet::new();
let mut grouped_features = std::collections::BTreeSet::new();
@@ -1493,16 +1494,14 @@ mod tests {
file["format_pending"] = serde_json::json!(["not-a-change-anyone-made"]);
file["features"] = serde_json::json!([{"type": "emboss", "face": {"body": "Body", "at": [0, 0, 0], "a_newer_key": true}}]);
let error = read(&file.to_string()).unwrap_err().to_string();
if PENDING.is_empty() {
assert!(error.contains("emboss face"), "a list beside a folded format means nothing: {error}");
} else {
assert_eq!(
error,
format!(
"this design was saved by a newer SolidCraft (file format {FORMAT} with `not-a-change-anyone-made`, which this version doesn't know): update SolidCraft to open it"
)
);
}
// With changes pending, FORMAT is made of them; once they are folded it is the folded
// format, which is made of changes too. Either way an unknown change is a newer build's.
assert_eq!(
error,
format!(
"this design was saved by a newer SolidCraft (file format {FORMAT} with `not-a-change-anyone-made`, which this version doesn't know): update SolidCraft to open it"
)
);
}
/// Drawings follow the same rules from their own first format: folded formats follow on from 1
@@ -0,0 +1,5 @@
//! A design can hold point clouds (`point_clouds`: scanned points kept as a reference, #5151),
//! their points and colours a binary part of the design file (base64 in a plain JSON design), with
//! how they are coloured (`color_by`, `color`, `height_range`).
//! Older designs need no transformation: they have none. The last release refuses a design
//! saved with this (the newer format number).
+202
View File
@@ -0,0 +1,202 @@
//! Values typed as definitions, `name = expression` (#4071): any value input, typed or sent as
//! a command's parameter, can name its value. Until the design stores it, such a text evaluates
//! as its expression (`expr::definition`), so a command reads and checks it like any other value;
//! [`Document::define_inline`] then makes the user parameter `name` with that expression and
//! leaves `name` where the text was.
use serde::Serialize;
use crate::expr::{self, Kind};
use crate::params::ExprRole;
use crate::walk::Walk;
use crate::{DocError, Document, FeatureKind, Result};
/// A user parameter a value typed as `name = expression` defined.
#[derive(Clone, Debug, PartialEq, Serialize)]
pub struct Defined {
pub name: String,
pub expression: String,
pub unit: String,
}
/// How the place a definition was typed in reads a bare number, which the parameter keeps.
#[derive(Clone, Copy)]
enum Reads<'a> {
/// A typed value of this kind: lengths in the design's units, angles in degrees.
Typed(Kind),
/// A model parameter's (a dimension's) own unit.
Unit(&'a str),
/// A primitive's placement coordinate: millimetres whatever the design's units.
Millimetres,
/// A value of no fixed kind: the parameter takes its value's unit.
Inferred,
}
/// A definition found: the name, its expression and its unit (`None`: its value's own).
struct Pending {
name: String,
expression: String,
unit: Option<String>,
}
/// The definitions found so far: each slot's text becomes the name, the definition is kept.
struct Found {
units: String,
defs: Vec<Pending>,
problem: Option<String>,
}
impl Found {
/// If `text` is a definition, note it and leave the name in its place.
fn take(&mut self, text: &mut String, reads: Reads) {
let Some((name, rhs)) = expr::definition(text) else { return };
if rhs.is_empty() {
self.problem.get_or_insert_with(|| format!("`{name} =` needs a value after the `=`"));
return;
}
let (expression, unit) = match reads {
Reads::Typed(Kind::Length) => {
let units = expr::length_unit_or_mm(&self.units);
(with_unit(rhs, units), Some(units.to_string()))
}
Reads::Typed(Kind::Angle) => (rhs.to_string(), Some("deg".to_string())),
Reads::Typed(Kind::Unitless) => (rhs.to_string(), Some(String::new())),
Reads::Unit(u) => (rhs.to_string(), Some(u.to_string())),
Reads::Millimetres => (rhs.to_string(), Some("mm".to_string())),
Reads::Inferred => (rhs.to_string(), None),
};
let name = name.to_string();
match self.defs.iter().find(|d| d.name == name) {
// The same definition in two places (one typed value a command stores twice).
Some(d) if d.expression == expression && d.unit == unit => {}
Some(_) => {
self.problem.get_or_insert_with(|| format!("`{name}` is defined twice with different values"));
return;
}
None => self.defs.push(Pending { name: name.clone(), expression, unit }),
}
*text = name;
}
/// [`Found::take`] for an expression field.
fn take_expr(&mut self, e: &mut expr::Expr, reads: Reads) {
if expr::definition(e.as_str()).is_none() {
return;
}
let mut text = e.as_str().to_string();
self.take(&mut text, reads);
*e = text.into();
}
}
/// A bare number in the design's length unit, as a typed length reads it.
fn with_unit(rhs: &str, units: &str) -> String {
if units != "mm" && expr::is_bare_number(rhs) { format!("{} {units}", rhs.trim()) } else { rhs.to_string() }
}
impl Document {
/// Store every value typed as `name = expression`: the user parameter `name` with that
/// expression (a bare number read as the value would read it, in that unit), and `name`
/// where the text was. A name that is taken or reserved is refused, as is a definition where
/// none can be made: in a parameter's own expression or a configuration cell. All or nothing:
/// on an error the design is unchanged.
pub fn define_inline(&mut self) -> Result<Vec<Defined>> {
// Where a definition is refused: a parameter's expression defines nothing else (the
// parameters command renames the parameter instead), nor does a configuration row.
if let Some(p) = self.params.iter().find(|p| !p.model && expr::definition(&p.expr).is_some()) {
let other = expr::definition(&p.expr).map(|(n, _)| n).unwrap_or_default();
return Err(DocError::Invalid(format!(
"the expression of `{}` cannot define another parameter `{other}`: add `{other}` as a parameter of its own",
p.name
)));
}
// Only a parameter's cells are expressions (a text parameter's are texts).
let numeric: Vec<bool> =
self.configs.columns.iter().map(|c| matches!(c, crate::config::Column::Param(n) if self.text_param(n).is_none())).collect();
let mut cells = self.configs.rows.iter().flat_map(|r| r.cells.iter().zip(&numeric).filter(|(_, n)| **n).map(|(c, _)| c));
if let Some(other) = cells.find_map(|c| expr::definition(c).map(|(n, _)| n)) {
return Err(DocError::Invalid(format!("a configuration cell cannot define the parameter `{other}`: add it in Parameters first")));
}
let mut next = self.clone();
let mut found = Found { units: next.units.clone(), defs: Vec::new(), problem: None };
for p in next.params.iter_mut().filter(|p| p.model) {
let unit = p.unit.clone();
found.take(&mut p.expr, Reads::Unit(&unit));
}
for f in &mut next.features {
f.kind.walk_exprs_mut(&mut |(_, e, kind, role)| {
let reads = if role == ExprRole::Placement { Reads::Millimetres } else { Reads::Typed(kind) };
found.take_expr(e, reads);
});
if let FeatureKind::Sketch { sketch, .. } = &mut f.kind {
for p in &mut sketch.patterns {
if let Some(e) = p.count_expression.as_mut() {
found.take(e, Reads::Typed(Kind::Unitless));
}
for (key, e) in &mut p.expressions {
let kind = match key.as_str() {
"count" | "count2" => Kind::Unitless,
"angle" => Kind::Angle,
_ => Kind::Length,
};
found.take(e, Reads::Typed(kind));
}
}
for link in &mut sketch.links {
if let solidcraft_sketch::LinkSource::Text { exprs, .. } = &mut link.source {
for e in [&mut exprs.x, &mut exprs.y, &mut exprs.height].into_iter().flatten() {
found.take(e, Reads::Typed(Kind::Length));
}
if let Some(e) = exprs.angle.as_mut() {
found.take(e, Reads::Typed(Kind::Angle));
}
}
}
}
}
for e in next.assembly.exprs_mut() {
found.take(e, Reads::Inferred);
}
for r in &mut next.sheet.rules {
let kinds = r.fields().map(|(_, _, k)| k);
for ((_, e), k) in r.fields_mut().into_iter().zip(kinds) {
found.take(e, Reads::Typed(k));
}
}
for r in &mut next.plastic.rules {
let kinds = r.fields().map(|(_, _, k)| k);
for ((_, e), k) in r.fields_mut().into_iter().zip(kinds) {
found.take(e, Reads::Typed(k));
}
}
for c in &mut next.canvases {
c.plane.walk_exprs_mut(&mut |(_, e, kind, _)| found.take_expr(e, Reads::Typed(kind)));
}
if let Some(problem) = found.problem {
return Err(DocError::Invalid(problem));
}
if found.defs.is_empty() {
return Ok(Vec::new());
}
for d in &found.defs {
if let Some(problem) = Self::param_name_problem(&d.name) {
return Err(DocError::Invalid(problem));
}
if self.name_taken(&d.name) {
return Err(DocError::Invalid(format!(
"there is already a parameter `{}`: type `{}` to use it, or change it in Parameters",
d.name, d.name
)));
}
}
let mut out = Vec::with_capacity(found.defs.len());
for d in found.defs {
next.add_user_param(&d.name, &d.expression, d.unit.as_deref(), None)
.map_err(|e| DocError::Invalid(format!("`{} = {}`: {e}", d.name, d.expression)))?;
let unit = next.param(&d.name).map(|p| p.unit.clone()).unwrap_or_default();
out.push(Defined { name: d.name, expression: d.expression, unit });
}
*self = next;
Ok(out)
}
}
+8 -5
View File
@@ -36,7 +36,9 @@ pub mod frame;
mod history_names;
pub mod hole_reference;
pub mod ids;
mod inline_params;
pub use format_offsets::whole_profile_selection_from_value;
pub use inline_params::Defined;
pub mod joints;
mod lineage;
pub mod metadata;
@@ -50,6 +52,7 @@ pub mod persistent_name;
pub mod physical_material;
mod piece_names;
pub mod pipe_thread_catalog;
pub mod point_cloud;
mod points;
mod profile_refs;
pub mod progress;
@@ -72,15 +75,15 @@ pub mod text_params;
pub use assembly::{
BomType, IDENTITY, MAX_PLACEMENT_DEPTH, MAX_PLACEMENTS, Mat, Occurrence, WorldNames, apply_point, apply_vector, is_identity, map_point_expr,
mat_inverse, mat_mul, rigid,
map_vector_expr, mat_inverse, mat_mul, rigid,
};
pub use document::*;
pub use eval::{
EdgeRef, FeatureResult, Model, ModelBody, ModelState, PlacedBodies, RevolveExtent, SavedModel, SolvedSketch, ThreadInfo, curve_pick_error,
edge_names_for, edge_refs, face_point_names, face_point_state, hole_direction_at, import_body_names, map_wire, metric_thread_sizes,
object_height, parse_metric_thread, pattern_matrices, revolve_extent, revolve_extent_with_convention, select_profiles, sketch_hole_direction,
sketch_line_plane, state_in_frame, state_in_frame_at, suggested_thread, tangent_face_chain, through_all_distance, world_state,
world_state_reusing,
edge_names_for, edge_refs, face_point_names, face_point_state, hole_direction_at, import_body_names, join_pieces_added, map_wire,
metric_thread_sizes, object_height, parse_metric_thread, pattern_matrices, revolve_extent, revolve_extent_with_convention, select_profiles,
sketch_hole_direction, sketch_line_plane, state_in_frame, state_in_frame_at, suggested_thread, tangent_face_chain, through_all_distance,
world_state, world_state_reusing,
};
pub use eval::{EvalCache, KeptResults};
pub use expr::Expr;

Some files were not shown because too many files have changed in this diff Show More