mirror of
https://github.com/bherbruck/solidcraft.git
synced 2026-11-10 18:55:14 +00:00
Compare commits
123 Commits
remove-view-cube
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| f56114219b | |||
| 2215a9a50a | |||
| 182d2c6bd8 | |||
| 126e91f95b | |||
| 54e5190955 | |||
| 6ca950789c | |||
| 89e3cb13b1 | |||
| 87400c80ef | |||
| d4e8c0b034 | |||
| 595bc8069c | |||
| 44fe6a0f24 | |||
| 12a9a7f0f9 | |||
| 3749c14ad1 | |||
| 9c4970d2b2 | |||
| 8d13350c30 | |||
| 995b80a78f | |||
| 7d271b3252 | |||
| a3dcc9ca55 | |||
| 2874e782fe | |||
| d8113d096c | |||
| 023b55277f | |||
| 3e2cc277ee | |||
| 5f46248771 | |||
| 176ba5464f | |||
| 1ab3a5b179 | |||
| 2b26c1729e | |||
| 99270af8d4 | |||
| 4647e30acf | |||
| b34844c34b | |||
| be098f3ac5 | |||
| 66b7d77e65 | |||
| 7f00422057 | |||
| 472bacb16f | |||
| 6a9318bd73 | |||
| 21c6faa4e9 | |||
| a7fc90bd70 | |||
| f2207de0a0 | |||
| ddacb344b4 | |||
| 312454f899 | |||
| a347568301 | |||
| b8cb6eecd6 | |||
| 9b97d8dc8f | |||
| fcf16720d4 | |||
| dfa47ab18a | |||
| 1f207899b4 | |||
| 10c8fb66c1 | |||
| 3cb35fe8c4 | |||
| 017c47a402 | |||
| ce79b4a3c3 | |||
| b0fc4c4cc5 | |||
| 89ad5ad172 | |||
| 875e30a321 | |||
| 3c81f9ece6 | |||
| 1449d50420 | |||
| 1aa2136c1b | |||
| fd40424900 | |||
| db01a69625 | |||
| 87a50d01a2 | |||
| 43655eca67 | |||
| a0585c9d1f | |||
| e54b379906 | |||
| 9d468f900f | |||
| 4d91782c69 | |||
| 390db99255 | |||
| fadefe56ab | |||
| 94ce45a1f2 | |||
| 52c9f72249 | |||
| c9d6a9f131 | |||
| c50ebfdc5b | |||
| de1a8737a9 | |||
| ceac257649 | |||
| b55c3c2da8 | |||
| 7b0ab2f23c | |||
| 100a2eb633 | |||
| 71f1db91ab | |||
| d7a6aacbb9 | |||
| 41356709bf | |||
| 5d7897b22c | |||
| ad145c6374 | |||
| efc8969f96 | |||
| 881cecb909 | |||
| 42b7892fa6 | |||
| bf5cd7a88e | |||
| cf9706890f | |||
| c3c80adf51 | |||
| a187e8dd58 | |||
| a0dbd760b4 | |||
| f048096459 | |||
| bcea30a641 | |||
| d4860e0863 | |||
| 9de15ea9bc | |||
| f5263a4853 | |||
| fbabfca7a4 | |||
| 967b0d4401 | |||
| ab07e1fd28 | |||
| 840062c991 | |||
| 2e0e4815f1 | |||
| 4f7ca2c6bf | |||
| ed1d8a5682 | |||
| cbb1ab5a42 | |||
| 005bbe6711 | |||
| 3a4f7a1a1e | |||
| 16c720dfbe | |||
| 8e0219403f | |||
| 05e9020413 | |||
| 92c2103ffb | |||
| 170f9e240c | |||
| a20d08b753 | |||
| 6802e2d86a | |||
| 2b0e51df23 | |||
| 255f7ab0af | |||
| ba61db7c33 | |||
| 6b91257c02 | |||
| 075336bfb2 | |||
| 70c2312f16 | |||
| df127b45d5 | |||
| b34a0ad748 | |||
| a52217f4e0 | |||
| e8e73e11ab | |||
| 64614d7071 | |||
| 0c0ac5faca | |||
| 68a4399ad9 | |||
| 3de9bfefc3 |
@@ -48,13 +48,6 @@ filter = "binary(action_matrix) & test(=action_matrix_sample)"
|
||||
threads-required = 12
|
||||
priority = 100
|
||||
|
||||
# The longest test by far (a median of 950 s on the 32 vCPU runner, #14362) starts at once, beside
|
||||
# the action matrix sample. In the list below it would wait behind the tests that sort before it,
|
||||
# and the run ends when it does.
|
||||
[[profile.ci.overrides]]
|
||||
filter = "package(solidcraft-kernel) & test(=thread_tests::a_long_thread_cuts_without_a_deep_tree)"
|
||||
priority = 100
|
||||
|
||||
# The slowest tests start first, so a shard does not end with one of them running alone on a
|
||||
# core while the others sit idle. Medians from the CI test timings (the junit artifacts), slowest
|
||||
# first; a test over ~100 s belongs here (the medians of 24 full runs added the last ones, #14362).
|
||||
@@ -154,5 +147,12 @@ max-threads = 1
|
||||
|
||||
[[profile.local-ci.overrides]]
|
||||
platform = "cfg(windows)"
|
||||
filter = "package(solidcraft-gpu) | package(solidcraft) | (package(solidcraft-ui-egui) & test(/(offscreen|gpu)/))"
|
||||
# Viewport tests also open real devices when their names do not contain "gpu".
|
||||
filter = """
|
||||
package(solidcraft-gpu) | package(solidcraft) | (package(solidcraft-ui-egui) & (
|
||||
test(/(offscreen|gpu)/)
|
||||
| test(/^viewport::tests::/)
|
||||
| test(=render_workspace::tests::progressive_image_controls_route_to_the_registered_host)
|
||||
))
|
||||
"""
|
||||
test-group = "windows-gpu"
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
# Preserve canonical source receipts and the runtime icon-discovery snapshot.
|
||||
.gitattributes text eol=lf
|
||||
/assets/icons/ui/design/requested_icons.txt text eol=lf
|
||||
/crates/look/icons/design/requested_icons.txt text eol=lf
|
||||
# Shaders reach the code through include_str!, and tests match multi-line WGSL excerpts
|
||||
# written as Rust strings (always LF), so a CRLF checkout must not change them (#13138).
|
||||
*.wgsl text eol=lf
|
||||
|
||||
@@ -30,7 +30,6 @@ on:
|
||||
- "crates/kernel/**"
|
||||
- "crates/geom/**"
|
||||
- "crates/smlib/**"
|
||||
- "crates/step/**"
|
||||
- "crates/io/src/**"
|
||||
- "crates/doc/src/**"
|
||||
- "crates/engine/src/**"
|
||||
@@ -51,7 +50,6 @@ on:
|
||||
- "crates/kernel/**"
|
||||
- "crates/geom/**"
|
||||
- "crates/smlib/**"
|
||||
- "crates/step/**"
|
||||
- "crates/io/src/**"
|
||||
- "crates/doc/src/**"
|
||||
- "crates/engine/src/**"
|
||||
|
||||
+453
-452
@@ -42,13 +42,13 @@ Editable drawing code, native projects and shipped exports are collected under `
|
||||
| examples/render-path-studio.json | SolidCraft contributors | original procedural opaque enclosure, teal insert and metal fasteners for progressive rendering; no imported models | MIT OR Apache-2.0 |
|
||||
| crates/gpu/src/path/path.wgsl | SolidCraft contributors | original software BVH traversal and path integration using the existing SolidCraft surface/studio equations; no external shader source | MIT OR Apache-2.0 |
|
||||
| crates/gpu/src/pbr.rs | SolidCraft contributors | original WGSL translation of SolidCraft's opaque surface and fixed studio reference, embedded as Rust source; no external shader code | MIT OR Apache-2.0 |
|
||||
| assets/icons/app/macos/source/SolidCraft.icon/icon.json | SolidCraft contributors | approved Icon Composer composition and appearance settings for the original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/app/macos/source/SolidCraft.icon/Assets/02-grid.svg | SolidCraft contributors | original perspective grid with elliptical radial alpha, exported from VectorCraft | MIT OR Apache-2.0 |
|
||||
| assets/icons/app/macos/source/SolidCraft.icon/Assets/02-grid-dark.svg | SolidCraft contributors | original blue perspective grid with elliptical radial alpha, exported from VectorCraft for the Dark appearance | MIT OR Apache-2.0 |
|
||||
| assets/icons/app/macos/source/SolidCraft.icon/Assets/03-solid-blue-cutout.svg | SolidCraft contributors | original saturated blue CAD solid with transparent topology cutouts, edited and exported with VectorCraft | MIT OR Apache-2.0 |
|
||||
| assets/icons/app/macos/exports/Assets.car | SolidCraft contributors | Apple actool compilation of assets/icons/app/macos/source/SolidCraft.icon for macOS; contains original artwork only | MIT OR Apache-2.0 |
|
||||
| assets/icons/app/macos/source/SolidCraft.icon/icon.json | SolidCraft contributors | approved Icon Composer composition and appearance settings for the original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| assets/icons/app/macos/source/SolidCraft.icon/Assets/02-grid.svg | SolidCraft contributors | original perspective grid with elliptical radial alpha, exported from VectorCraft | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| assets/icons/app/macos/source/SolidCraft.icon/Assets/02-grid-dark.svg | SolidCraft contributors | original blue perspective grid with elliptical radial alpha, exported from VectorCraft for the Dark appearance | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| assets/icons/app/macos/source/SolidCraft.icon/Assets/03-solid-blue-cutout.svg | SolidCraft contributors | original saturated blue CAD solid with transparent topology cutouts, edited and exported with VectorCraft | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| assets/icons/app/macos/exports/Assets.car | SolidCraft contributors | Apple actool compilation of assets/icons/app/macos/source/SolidCraft.icon for macOS; contains original artwork only | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| assets/archive/icons/macos-v1/source/icon.vectorcraft | SolidCraft contributors | retained editable historical VectorCraft source, with named face and background layers; redundant exports retired | MIT OR Apache-2.0 |
|
||||
| assets/icons/app/macos/exports/icon.icns | SolidCraft contributors | macOS fallback compiled by Apple's actool from the approved assets/icons/app/macos/source/SolidCraft.icon composition | MIT OR Apache-2.0 |
|
||||
| assets/icons/app/macos/exports/icon.icns | SolidCraft contributors | macOS fallback compiled by Apple's actool from the approved assets/icons/app/macos/source/SolidCraft.icon composition | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| assets/models/test_boat.bin | 3DBenchy.com | 3DBenchy.com | Public Domain |
|
||||
| assets/models/make_test_boat.py | SolidCraft contributors | original script that packs a model into the compact file above | MIT OR Apache-2.0 |
|
||||
| docs/screenshots/class-a-blend.png | SolidCraft contributors | screenshot of SolidCraft itself: a 24 mm and a 10 mm box bridged by a `surface.blend` sheet (G1 at both edges), rendered by the app's `ui.render` in the dark theme with examples/demo/class_a_shots.py | MIT OR Apache-2.0 |
|
||||
@@ -73,14 +73,14 @@ Editable drawing code, native projects and shipped exports are collected under `
|
||||
| docs/design/ux-redesign/start-page.png | SolidCraft contributors | original UX mockup (start page (File view)) rendered from an HTML mockup that uses the original Technical Accent icon set; no third-party artwork, and not a screenshot of any other CAD product | MIT OR Apache-2.0 |
|
||||
| docs/design/ux-redesign/workspaces.png | SolidCraft contributors | original UX mockup (workspace switcher) rendered from an HTML mockup that uses the original Technical Accent icon set; no third-party artwork, and not a screenshot of any other CAD product | MIT OR Apache-2.0 |
|
||||
| docs/design/ux-redesign/command-map.png | SolidCraft contributors | original UX mockup (ribbon command map) rendered from an HTML mockup that uses the original Technical Accent icon set; no third-party artwork, and not a screenshot of any other CAD product | MIT OR Apache-2.0 |
|
||||
| assets/branding/web/source/og.png | SolidCraft contributors | original 1280 × 640 social preview card (the SolidCraft mark, name and tagline), served by the docs site for link previews | MIT OR Apache-2.0 |
|
||||
| assets/branding/web/source/og.png | SolidCraft contributors | original 1280 × 640 social preview card (the SolidCraft mark, name and tagline), served by the docs site for link previews | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| docs/book/src/generated/sample-plate.png | SolidCraft contributors | copy of docs/screenshots/sample-plate.png made by `cargo xtask book` (gitignored) | MIT OR Apache-2.0 |
|
||||
| docs/book/src/generated/bracket.png | SolidCraft contributors | rendered by `cargo xtask book` (`solidcraft-cli snapshot examples/bracket.json`; gitignored) | MIT OR Apache-2.0 |
|
||||
| docs/book/src/generated/enclosure.png | SolidCraft contributors | rendered by `cargo xtask book` (`solidcraft-cli snapshot docs/book/scripts/enclosure.json`; gitignored) | MIT OR Apache-2.0 |
|
||||
| docs/book/src/generated/revolve.png | SolidCraft contributors | rendered by `cargo xtask book` (`solidcraft-cli snapshot docs/book/scripts/revolve.json`; gitignored) | MIT OR Apache-2.0 |
|
||||
| docs/book/src/generated/sheet-metal.png | SolidCraft contributors | rendered by `cargo xtask book` (`solidcraft-cli snapshot docs/book/scripts/sheet-metal.json`; gitignored) | MIT OR Apache-2.0 |
|
||||
| assets/fonts/ibm-plex-mono/IBMPlexMono-Regular.ttf | IBM Corp. (IBM Plex Mono) | https://github.com/IBM/plex (via google/fonts), unmodified; licence text in assets/fonts/ibm-plex-mono/OFL.txt; the interface monospace font | SIL OFL 1.1 |
|
||||
| assets/fonts/ibm-plex-sans/IBMPlexSans-Variable.ttf | IBM Corp. (IBM Plex Sans, variable wdth and wght) | https://github.com/IBM/plex (via google/fonts), unmodified; licence text in assets/fonts/ibm-plex-sans/OFL.txt; the default interface font | SIL OFL 1.1 |
|
||||
| crates/look/fonts/ibm-plex-mono/IBMPlexMono-Regular.ttf | IBM Corp. (IBM Plex Mono) | https://github.com/IBM/plex (via google/fonts), unmodified; licence text in crates/look/fonts/ibm-plex-mono/OFL.txt; the interface monospace font | SIL OFL 1.1 |
|
||||
| crates/look/fonts/ibm-plex-sans/IBMPlexSans-Variable.ttf | IBM Corp. (IBM Plex Sans, variable wdth and wght) | https://github.com/IBM/plex (via google/fonts), unmodified; licence text in crates/look/fonts/ibm-plex-sans/OFL.txt; the default interface font | SIL OFL 1.1 |
|
||||
| docs/book/src/generated/tool-preview.png | SolidCraft contributors | rendered by `cargo xtask book` (`solidcraft-cli snapshot docs/book/scripts/tool-preview.json`; gitignored) | MIT OR Apache-2.0 |
|
||||
| assets/fonts/biz-udp-gothic/BIZUDPGothic-Regular.ttf | The BIZ UDGothic Project Authors | https://github.com/googlefonts/morisawa-biz-ud-gothic (Google Fonts), unmodified; licence text in assets/fonts/biz-udp-gothic/OFL.txt; used for web UI Japanese font | SIL OFL 1.1 |
|
||||
| assets/fonts/craft-ui-sc/CraftUI-SC.otf | Adobe / Google Inc. (Noto Sans SC); SolidCraft subset | https://github.com/notofonts/noto-cjk Sans/SubsetOTF/SC Regular, glyph-subset for assets/locales/zh.json and renamed Craft UI SC (OFL reserved-name); licence text in assets/fonts/craft-ui-sc/OFL.txt; web UI Simplified Chinese | SIL OFL 1.1 |
|
||||
@@ -144,24 +144,25 @@ Editable drawing code, native projects and shipped exports are collected under `
|
||||
| assets/fonts/biz-udp-gothic/OFL.txt | The BIZ UDGothic Project Authors | Unmodified accompanying font licence | SIL OFL 1.1 |
|
||||
| assets/fonts/craft-ui-sc/OFL.txt | Adobe / Google Inc. (Noto CJK); SolidCraft header | Accompanying OFL for CraftUI-SC.otf | SIL OFL 1.1 |
|
||||
| assets/fonts/craft-ui-tc/OFL.txt | Adobe / Google Inc. (Noto CJK); SolidCraft header | Accompanying OFL for CraftUI-TC.otf | SIL OFL 1.1 |
|
||||
| assets/fonts/ibm-plex-mono/OFL.txt | IBM Corp. | Unmodified accompanying font licence | SIL OFL 1.1 |
|
||||
| assets/fonts/ibm-plex-sans/OFL.txt | IBM Corp. | Unmodified accompanying font licence | SIL OFL 1.1 |
|
||||
| assets/icons/app/linux/exports/hicolor/128x128/apps/io.tangencylabs.solidcraft.png | SolidCraft contributors | Generated from assets/icons/app/shared/source/app_icon.rs with the original CLI/ICO encoders | MIT OR Apache-2.0 |
|
||||
| assets/icons/app/linux/exports/hicolor/16x16/apps/io.tangencylabs.solidcraft.png | SolidCraft contributors | Generated from assets/icons/app/shared/source/app_icon.rs with the original CLI/ICO encoders | MIT OR Apache-2.0 |
|
||||
| assets/icons/app/linux/exports/hicolor/24x24/apps/io.tangencylabs.solidcraft.png | SolidCraft contributors | Generated from assets/icons/app/shared/source/app_icon.rs with the original CLI/ICO encoders | MIT OR Apache-2.0 |
|
||||
| assets/icons/app/linux/exports/hicolor/256x256/apps/io.tangencylabs.solidcraft.png | SolidCraft contributors | Generated from assets/icons/app/shared/source/app_icon.rs with the original CLI/ICO encoders | MIT OR Apache-2.0 |
|
||||
| assets/icons/app/linux/exports/hicolor/32x32/apps/io.tangencylabs.solidcraft.png | SolidCraft contributors | Generated from assets/icons/app/shared/source/app_icon.rs with the original CLI/ICO encoders | MIT OR Apache-2.0 |
|
||||
| assets/icons/app/linux/exports/hicolor/48x48/apps/io.tangencylabs.solidcraft.png | SolidCraft contributors | Generated from assets/icons/app/shared/source/app_icon.rs with the original CLI/ICO encoders | MIT OR Apache-2.0 |
|
||||
| assets/icons/app/linux/exports/hicolor/512x512/apps/io.tangencylabs.solidcraft.png | SolidCraft contributors | Generated from assets/icons/app/shared/source/app_icon.rs with the original CLI/ICO encoders | MIT OR Apache-2.0 |
|
||||
| assets/icons/app/linux/exports/hicolor/64x64/apps/io.tangencylabs.solidcraft.png | SolidCraft contributors | Generated from assets/icons/app/shared/source/app_icon.rs with the original CLI/ICO encoders | MIT OR Apache-2.0 |
|
||||
| assets/icons/app/shared/source/app_icon.rs | SolidCraft contributors | Original SolidCraft drawing code: the borderless mark, drawn from the faces and gradients of assets/icons/app/macos/source/SolidCraft.icon/Assets/03-solid-blue-cutout.svg | MIT OR Apache-2.0 |
|
||||
| assets/icons/app/shared/source/windows_ico.rs | SolidCraft contributors | Original SolidCraft resource data or drawing code, collected without redesign | MIT OR Apache-2.0 |
|
||||
| assets/icons/app/windows/exports/solidcraft-executable.ico | SolidCraft contributors | Generated from assets/icons/app/shared/source/app_icon.rs with the original CLI/ICO encoders | MIT OR Apache-2.0 |
|
||||
| assets/icons/app/windows/exports/solidcraft.ico | SolidCraft contributors | Generated from assets/icons/app/shared/source/app_icon.rs with the original CLI/ICO encoders | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/source/glyphs.rs | SolidCraft / VectorCraft contributors | Original glyphs; caption geometry adapted from VectorCraft titlebar.rs (https://github.com/storytold/vectorcraft) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/source/markers.rs | SolidCraft contributors | Original SolidCraft resource data or drawing code, collected without redesign | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/source/navigation.rs | SolidCraft contributors | Original SolidCraft resource data or drawing code, collected without redesign | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/source/pointer.rs | SolidCraft contributors | Original SolidCraft resource data or drawing code, collected without redesign | MIT OR Apache-2.0 |
|
||||
| crates/look/fonts/ibm-plex-mono/OFL.txt | IBM Corp. | Unmodified accompanying font licence | SIL OFL 1.1 |
|
||||
| crates/look/fonts/ibm-plex-sans/OFL.txt | IBM Corp. | Unmodified accompanying font licence | SIL OFL 1.1 |
|
||||
| assets/icons/app/linux/exports/hicolor/128x128/apps/io.tangencylabs.solidcraft.png | SolidCraft contributors | Generated from assets/icons/app/shared/source/app_icon.rs with the original CLI/ICO encoders | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| assets/icons/app/linux/exports/hicolor/16x16/apps/io.tangencylabs.solidcraft.png | SolidCraft contributors | Generated from assets/icons/app/shared/source/app_icon.rs with the original CLI/ICO encoders | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| assets/icons/app/linux/exports/hicolor/24x24/apps/io.tangencylabs.solidcraft.png | SolidCraft contributors | Generated from assets/icons/app/shared/source/app_icon.rs with the original CLI/ICO encoders | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| assets/icons/app/linux/exports/hicolor/256x256/apps/io.tangencylabs.solidcraft.png | SolidCraft contributors | Generated from assets/icons/app/shared/source/app_icon.rs with the original CLI/ICO encoders | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| assets/icons/app/linux/exports/hicolor/32x32/apps/io.tangencylabs.solidcraft.png | SolidCraft contributors | Generated from assets/icons/app/shared/source/app_icon.rs with the original CLI/ICO encoders | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| assets/icons/app/linux/exports/hicolor/48x48/apps/io.tangencylabs.solidcraft.png | SolidCraft contributors | Generated from assets/icons/app/shared/source/app_icon.rs with the original CLI/ICO encoders | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| assets/icons/app/linux/exports/hicolor/512x512/apps/io.tangencylabs.solidcraft.png | SolidCraft contributors | Generated from assets/icons/app/shared/source/app_icon.rs with the original CLI/ICO encoders | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| assets/icons/app/linux/exports/hicolor/64x64/apps/io.tangencylabs.solidcraft.png | SolidCraft contributors | Generated from assets/icons/app/shared/source/app_icon.rs with the original CLI/ICO encoders | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| assets/icons/app/shared/source/app_icon.rs | SolidCraft contributors | Original SolidCraft drawing code: the borderless mark, drawn from the faces and gradients of assets/icons/app/macos/source/SolidCraft.icon/Assets/03-solid-blue-cutout.svg | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| assets/icons/app/shared/source/windows_ico.rs | SolidCraft contributors | Original SolidCraft resource data or drawing code, collected without redesign | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| assets/icons/app/windows/exports/solidcraft-executable.ico | SolidCraft contributors | Generated from assets/icons/app/shared/source/app_icon.rs with the original CLI/ICO encoders | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| assets/icons/app/windows/exports/solidcraft.ico | SolidCraft contributors | Generated from assets/icons/app/shared/source/app_icon.rs with the original CLI/ICO encoders | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/src/glyphs.rs | SolidCraft / VectorCraft contributors | Original glyphs; caption geometry adapted from VectorCraft titlebar.rs (https://github.com/storytold/vectorcraft) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/ui-egui/src/icons/markers.rs | SolidCraft contributors | Original SolidCraft resource data or drawing code, collected without redesign | MIT OR Apache-2.0 |
|
||||
| crates/ui-egui/src/icons/navigation.rs | SolidCraft contributors | Original SolidCraft resource data or drawing code, collected without redesign | MIT OR Apache-2.0 |
|
||||
| crates/look/src/compass.rs | SolidCraft contributors | Original SolidCraft resource data or drawing code, collected without redesign | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/src/pointer.rs | SolidCraft contributors | Original SolidCraft resource data or drawing code, collected without redesign | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| assets/locales/cs.json | potuzai | Czech translation of the English catalog, contributed upstream | MIT OR Apache-2.0 |
|
||||
| assets/locales/da.json | SolidCraft contributors | Original Danish translation of SolidCraft's English catalog; no commercial CAD text used | MIT OR Apache-2.0 |
|
||||
| assets/locales/de.json | SolidCraft contributors | Original SolidCraft resource data or drawing code, collected without redesign | MIT OR Apache-2.0 |
|
||||
@@ -201,122 +202,122 @@ Editable drawing code, native projects and shipped exports are collected under `
|
||||
| assets/platforms/windows/solidcraft.en-us.wxl | PhotoCraft / SolidCraft contributors | PhotoCraft packaging templates (https://github.com/storytold/photocraft), adapted for SolidCraft | Apache-2.0 |
|
||||
| assets/platforms/windows/solidcraft.wxs | PhotoCraft / SolidCraft contributors | PhotoCraft packaging templates (https://github.com/storytold/photocraft), adapted for SolidCraft | Apache-2.0 |
|
||||
| crates/viewport-gpu/shaders/viewport.wgsl | SolidCraft contributors | Original SolidCraft resource data or drawing code, collected without redesign | MIT OR Apache-2.0 |
|
||||
| assets/styles/ui/themes/gruvbox-dark.json | SolidCraft contributors | original SolidCraft theme file mapping SolidCraft's UI colours to the Gruvbox palette's colour values (Gruvbox by Pavel Pertsev, https://github.com/morhetz/gruvbox, MIT) | MIT OR Apache-2.0 |
|
||||
| assets/styles/ui/themes/gruvbox-light.json | SolidCraft contributors | original SolidCraft theme file mapping SolidCraft's UI colours to the Gruvbox palette's colour values (Gruvbox by Pavel Pertsev, https://github.com/morhetz/gruvbox, MIT) | MIT OR Apache-2.0 |
|
||||
| assets/styles/ui/themes/solidcraft-95.json | SolidCraft contributors | original SolidCraft theme file | MIT OR Apache-2.0 |
|
||||
| assets/styles/ui/themes/platinum-9.json | SolidCraft contributors | original SolidCraft theme file | MIT OR Apache-2.0 |
|
||||
| assets/styles/ui/themes/cupertino.json | SolidCraft contributors | original SolidCraft theme file | MIT OR Apache-2.0 |
|
||||
| assets/styles/ui/themes/green-phosphor.json | SolidCraft contributors | original SolidCraft theme file | MIT OR Apache-2.0 |
|
||||
| assets/styles/ui/themes/amber-phosphor.json | SolidCraft contributors | original SolidCraft theme file | MIT OR Apache-2.0 |
|
||||
| assets/styles/ui/themes/blueprint.json | SolidCraft contributors | original SolidCraft theme file | MIT OR Apache-2.0 |
|
||||
| assets/styles/ui/themes/one-dark.json | SolidCraft contributors | original SolidCraft theme file with colours adapted from the One Dark palette (Atom One Dark by GitHub Atom, https://github.com/atom/atom, MIT) | MIT OR Apache-2.0 |
|
||||
| assets/styles/ui/themes/tokyo-night.json | SolidCraft contributors | original SolidCraft theme file adapting the colours of a published palette (Tokyo Night by enkia, https://github.com/enkia/tokyo-night-vscode-theme, MIT) | MIT OR Apache-2.0 |
|
||||
| assets/styles/ui/themes/solarized-light.json | SolidCraft contributors | original SolidCraft theme file adapting the colours of a published palette (Solarized by Ethan Schoonover, https://github.com/altercation/solarized, MIT) | MIT OR Apache-2.0 |
|
||||
| assets/styles/ui/themes/solarized-dark.json | SolidCraft contributors | original SolidCraft theme file adapting the colours of a published palette (Solarized by Ethan Schoonover, https://github.com/altercation/solarized, MIT) | MIT OR Apache-2.0 |
|
||||
| assets/styles/ui/themes/nord.json | SolidCraft contributors | original SolidCraft theme file adapting the colours of a published palette (Nord by Sven Greb and the Nord contributors, https://github.com/nordtheme/nord, MIT) | MIT OR Apache-2.0 |
|
||||
| assets/styles/ui/themes/high-contrast.json | SolidCraft contributors | original SolidCraft theme file | MIT OR Apache-2.0 |
|
||||
| assets/styles/ui/themes/graphite.json | SolidCraft contributors | original SolidCraft theme file | MIT OR Apache-2.0 |
|
||||
| assets/styles/ui/themes/nosferatu.json | SolidCraft contributors | original SolidCraft theme file adapting the colours of a published palette (Dracula by Zeno Rocha and the Dracula Theme contributors, https://github.com/dracula/dracula-theme, MIT) | MIT OR Apache-2.0 |
|
||||
| assets/styles/ui/themes/catppuccin-mocha.json | SolidCraft contributors | original SolidCraft theme file adapting the colours of a published palette (Catppuccin by the Catppuccin organisation, https://github.com/catppuccin/catppuccin, MIT) | MIT OR Apache-2.0 |
|
||||
| assets/styles/ui/themes/okibi.json | SolidCraft contributors (Kai Evans) | original SolidCraft theme file mapping SolidCraft's UI colours to the Okibi palette (dark) of the Okibi design system by Kai Evans (https://kaievns.github.io/okibi-akiri-design-system-spec/) | MIT OR Apache-2.0 |
|
||||
| assets/styles/ui/themes/akari.json | SolidCraft contributors (Kai Evans) | original SolidCraft theme file mapping SolidCraft's UI colours to the Akari palette (light) of the Okibi design system by Kai Evans (https://kaievns.github.io/okibi-akiri-design-system-spec/) | MIT OR Apache-2.0 |
|
||||
| crates/look/themes/gruvbox-dark.json | SolidCraft contributors | original SolidCraft theme file mapping SolidCraft's UI colours to the Gruvbox palette's colour values (Gruvbox by Pavel Pertsev, https://github.com/morhetz/gruvbox, MIT) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/themes/gruvbox-light.json | SolidCraft contributors | original SolidCraft theme file mapping SolidCraft's UI colours to the Gruvbox palette's colour values (Gruvbox by Pavel Pertsev, https://github.com/morhetz/gruvbox, MIT) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/themes/solidcraft-95.json | SolidCraft contributors | original SolidCraft theme file | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/themes/platinum-9.json | SolidCraft contributors | original SolidCraft theme file | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/themes/cupertino.json | SolidCraft contributors | original SolidCraft theme file | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/themes/green-phosphor.json | SolidCraft contributors | original SolidCraft theme file | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/themes/amber-phosphor.json | SolidCraft contributors | original SolidCraft theme file | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/themes/blueprint.json | SolidCraft contributors | original SolidCraft theme file | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/themes/one-dark.json | SolidCraft contributors | original SolidCraft theme file with colours adapted from the One Dark palette (Atom One Dark by GitHub Atom, https://github.com/atom/atom, MIT) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/themes/tokyo-night.json | SolidCraft contributors | original SolidCraft theme file adapting the colours of a published palette (Tokyo Night by enkia, https://github.com/enkia/tokyo-night-vscode-theme, MIT) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/themes/solarized-light.json | SolidCraft contributors | original SolidCraft theme file adapting the colours of a published palette (Solarized by Ethan Schoonover, https://github.com/altercation/solarized, MIT) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/themes/solarized-dark.json | SolidCraft contributors | original SolidCraft theme file adapting the colours of a published palette (Solarized by Ethan Schoonover, https://github.com/altercation/solarized, MIT) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/themes/nord.json | SolidCraft contributors | original SolidCraft theme file adapting the colours of a published palette (Nord by Sven Greb and the Nord contributors, https://github.com/nordtheme/nord, MIT) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/themes/high-contrast.json | SolidCraft contributors | original SolidCraft theme file | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/themes/graphite.json | SolidCraft contributors | original SolidCraft theme file | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/themes/nosferatu.json | SolidCraft contributors | original SolidCraft theme file adapting the colours of a published palette (Dracula by Zeno Rocha and the Dracula Theme contributors, https://github.com/dracula/dracula-theme, MIT) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/themes/catppuccin-mocha.json | SolidCraft contributors | original SolidCraft theme file adapting the colours of a published palette (Catppuccin by the Catppuccin organisation, https://github.com/catppuccin/catppuccin, MIT) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/themes/okibi.json | SolidCraft contributors (Kai Evans) | original SolidCraft theme file mapping SolidCraft's UI colours to the Okibi palette (dark) of the Okibi design system by Kai Evans (https://kaievns.github.io/okibi-akiri-design-system-spec/) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/themes/akari.json | SolidCraft contributors (Kai Evans) | original SolidCraft theme file mapping SolidCraft's UI colours to the Akari palette (light) of the Okibi design system by Kai Evans (https://kaievns.github.io/okibi-akiri-design-system-spec/) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| assets/styles/web/loading-logo.svg | SolidCraft contributors | Animation of the SolidCraft mark, built from the paths and gradients of assets/icons/app/macos/source/SolidCraft.icon/Assets/03-solid-blue-cutout.svg; original animation | MIT OR Apache-2.0 |
|
||||
| assets/styles/web/loading.css | SolidCraft contributors | Original SolidCraft resource data or drawing code, collected without redesign | MIT OR Apache-2.0 |
|
||||
| crates/io/src/native_cad/fixtures/block.FCStd | SolidCraft contributors | original 10 × 20 × 30 mm test box saved by FreeCAD 1.1.4 run as an external program (`make_block_fcstd.py` beside it); no third-party geometry | MIT OR Apache-2.0 |
|
||||
| crates/io/src/native_cad/fixtures/block.3dm | SolidCraft contributors | original 10 × 20 × 30 mm test box written with McNeel's MIT-licensed rhino3dm Python package (`make_block_3dm.py` beside it); no third-party geometry | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/aliases.toml | SolidCraft contributors | icon ids that share a master, original SolidCraft data | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/palette.toml | SolidCraft contributors | icon colour roles (light and dark) and accents, original SolidCraft data | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/bug_report.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/chevron.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/chevron_right.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/close.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/disclosure_closed.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/disclosure_open.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/fit.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/folder.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/help.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/home.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/lookat.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/moon.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/nav_settings.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/orbit.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/plus.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/pan.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/perspective.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/prefs_appearance.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/prefs_assistant.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/prefs_design.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/prefs_general.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/prefs_graphics.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/prefs_layout.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/prefs_mouse3d.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/prefs_navigation.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/prefs_plugins.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/prefs_shortcuts.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/prefs_sketch.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/prefs_tools.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/redo.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/save.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/settings.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/settings_keyboard.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/settings_monitor.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/settings_mouse.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/settings_palette.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/settings_plug.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/spin.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/style.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/undo.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/zoom.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/accessibility.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/activate.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/align.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/appearance.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/arc3.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/arc_center.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/arc_slot.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/arc_tangent.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/as_built.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/auto_constrain.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/axis.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/bendtable.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/blend.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/blend_surface.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/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/boss.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/boundary.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/boundary_fill.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/box.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/break.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/c_coincident.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/c_collinear.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/c_concentric.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/c_equal.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/c_fix.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/c_hv.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/c_midpoint.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/c_parallel.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/c_perpendicular.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/c_polygon.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/c_smooth.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/c_symmetry.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/c_tangent.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/camera.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/canvas.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/capture.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/center_of_mass.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/centerline.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/chain.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/chamfer.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/checkpoint.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/circle.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/circle2.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/circle3.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/circle_tt.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/circle_ttt.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/coil.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/colored_components.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/combine.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/component.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| crates/look/icons/design/aliases.toml | SolidCraft contributors | icon ids that share a master, original SolidCraft data | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/palette.toml | SolidCraft contributors | icon colour roles (light and dark) and accents, original SolidCraft data | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/bug_report.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/chevron.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/chevron_right.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/close.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/disclosure_closed.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/disclosure_open.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/fit.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/folder.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/help.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/home.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/lookat.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/moon.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/nav_settings.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/orbit.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/plus.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/pan.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/perspective.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/prefs_appearance.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/prefs_assistant.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/prefs_design.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/prefs_general.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/prefs_graphics.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/prefs_layout.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/prefs_mouse3d.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/prefs_navigation.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/prefs_plugins.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/prefs_shortcuts.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/prefs_sketch.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/prefs_tools.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/redo.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/save.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/settings.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/settings_keyboard.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/settings_monitor.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/settings_mouse.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/settings_palette.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/settings_plug.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/spin.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/style.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/undo.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/zoom.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/accessibility.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/activate.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/align.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/appearance.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/arc3.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/arc_center.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/arc_slot.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/arc_tangent.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/as_built.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/auto_constrain.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/axis.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/bendtable.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/blend.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/blend_surface.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/body.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/boss.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/boundary.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/boundary_fill.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/box.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/break.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/c_coincident.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/c_collinear.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/c_concentric.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/c_equal.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/c_fix.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/c_hv.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/c_midpoint.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/c_parallel.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/c_perpendicular.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/c_polygon.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/c_smooth.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/c_symmetry.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/c_tangent.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/camera.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/canvas.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/capture.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/center_of_mass.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/centerline.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/chain.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/chamfer.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/checkpoint.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/circle.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/circle2.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/circle3.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/circle_tt.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/circle_ttt.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/coil.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/colored_components.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/combine.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/component.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
|
||||
### Render workspace icon drafts
|
||||
|
||||
@@ -324,328 +325,328 @@ Original SolidCraft drawings, Open for owner review; no runtime assignments.
|
||||
|
||||
| File | Author | Source | Licence |
|
||||
|---|---|---|---|
|
||||
| assets/icons/ui/design/svg/model/render_all_shots.svg | SolidCraft contributors | original Camera icon master (64 grid): stacked camera bodies with a lower-right play badge | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/render_appearance.svg | SolidCraft contributors | original Looks icon master (64 grid): shaded look sphere on the top corner of an accent-shaded cube | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/render_aspect_frame.svg | SolidCraft contributors | original Camera icon master (64 grid): wide rounded frame with two opposite corner brackets | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/render_backdrop.svg | SolidCraft contributors | original Studio icon master (64 grid): grey cube in front of a tall upright accent panel | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/render_cancel.svg | SolidCraft contributors | original Output icon master (64 grid): picture with a lower-right round stop badge | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/render_check.svg | SolidCraft contributors | original Output icon master (64 grid): picture with a lower-right round check badge | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/render_compare.svg | SolidCraft contributors | original Output icon master (64 grid): two grey pictures split by a vertical slider with opposed arrows | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/render_copy_look.svg | SolidCraft contributors | original Looks icon master (64 grid): look sphere in a square frame offset from a second frame outline | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/render_execute.svg | SolidCraft contributors | original Output icon master (64 grid): picture with a lower-right round play badge | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/render_export_image.svg | SolidCraft contributors | original Output icon master (64 grid): picture with a large outward diagonal arrow at the upper right | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/render_exposure.svg | SolidCraft contributors | original Camera icon master (64 grid): split light and accent disc with plus and minus marks | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/render_fit_product.svg | SolidCraft contributors | original Camera icon master (64 grid): grey cube inside four corner brackets | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/render_frame_guides.svg | SolidCraft contributors | original Camera icon master (64 grid): rounded frame with a rule-of-thirds grid and four accent nodes | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/render_from_material.svg | SolidCraft contributors | original Looks icon master (64 grid): look sphere struck through above a plain grey slab | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/render_ground.svg | SolidCraft contributors | original Studio icon master (64 grid): grey cube on a slab with an accent contact patch | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/render_lens.svg | SolidCraft contributors | original Camera icon master (64 grid): concentric lens rings around an accent centre | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/render_library.svg | SolidCraft contributors | original Studio icon master (64 grid): row of three look spheres, middle one accent, on a shelf bar | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/render_light_area.svg | SolidCraft contributors | original Lights icon master (64 grid): slanted flat panel above a dotted accent stem | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/render_light_by_highlight.svg | SolidCraft contributors | original Lights icon master (64 grid): shaded sphere with a ringed highlight target and dotted stem arriving from above | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/render_light_point.svg | SolidCraft contributors | original Lights icon master (64 grid): round source disc with centre dot above a dotted accent stem | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/render_light_spot.svg | SolidCraft contributors | original Lights icon master (64 grid): cone source with curved rim above a dotted accent stem | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/render_lighting_presets.svg | SolidCraft contributors | original Studio icon master (64 grid): two stacked cards, the front one holding a light bulb | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/render_output_size.svg | SolidCraft contributors | original Output icon master (64 grid): picture frame with a diagonal double-headed dimension arrow | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/render_paint.svg | SolidCraft contributors | original Looks icon master (64 grid): flat brush with an accent tip, light ferrule and slate handle | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/render_pick_up.svg | SolidCraft contributors | original Looks icon master (64 grid): eyedropper with a grey bulb, slate crossbar and accent sampling tip | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/render_quality.svg | SolidCraft contributors | original Output icon master (64 grid): three rising bars, the tallest in accent | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/render_replace_all.svg | SolidCraft contributors | original Looks icon master (64 grid): grey sample sphere with an arrow to an accent sphere beside a second one | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/render_results.svg | SolidCraft contributors | original Output icon master (64 grid): stack of two pictures, the front one showing a landscape | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/render_same_look.svg | SolidCraft contributors | original Looks icon master (64 grid): look sphere and three cubes, the two matching cubes ringed | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/render_shot.svg | SolidCraft contributors | original Camera icon master (64 grid): camera body with a lower-right plus badge | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/render_shots_strip.svg | SolidCraft contributors | original Camera icon master (64 grid): strip of three small frames, the middle one in accent | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/render_solo_light.svg | SolidCraft contributors | original Lights icon master (64 grid): point source and dotted stem inside four corner focus brackets | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/render_sun.svg | SolidCraft contributors | original Lights icon master (64 grid): source disc with eight short radial rays | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/render_transparent_background.svg | SolidCraft contributors | original Output icon master (64 grid): grey cube on a checker tile | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/render_update_shot.svg | SolidCraft contributors | original Camera icon master (64 grid): camera body with a lower-right refresh badge | MIT OR Apache-2.0 |
|
||||
| crates/look/icons/design/svg/model/render_all_shots.svg | SolidCraft contributors | original Camera icon master (64 grid): stacked camera bodies with a lower-right play badge | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/render_appearance.svg | SolidCraft contributors | original Looks icon master (64 grid): shaded look sphere on the top corner of an accent-shaded cube | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/render_aspect_frame.svg | SolidCraft contributors | original Camera icon master (64 grid): wide rounded frame with two opposite corner brackets | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/render_backdrop.svg | SolidCraft contributors | original Studio icon master (64 grid): grey cube in front of a tall upright accent panel | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/render_cancel.svg | SolidCraft contributors | original Output icon master (64 grid): picture with a lower-right round stop badge | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/render_check.svg | SolidCraft contributors | original Output icon master (64 grid): picture with a lower-right round check badge | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/render_compare.svg | SolidCraft contributors | original Output icon master (64 grid): two grey pictures split by a vertical slider with opposed arrows | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/render_copy_look.svg | SolidCraft contributors | original Looks icon master (64 grid): look sphere in a square frame offset from a second frame outline | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/render_execute.svg | SolidCraft contributors | original Output icon master (64 grid): picture with a lower-right round play badge | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/render_export_image.svg | SolidCraft contributors | original Output icon master (64 grid): picture with a large outward diagonal arrow at the upper right | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/render_exposure.svg | SolidCraft contributors | original Camera icon master (64 grid): split light and accent disc with plus and minus marks | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/render_fit_product.svg | SolidCraft contributors | original Camera icon master (64 grid): grey cube inside four corner brackets | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/render_frame_guides.svg | SolidCraft contributors | original Camera icon master (64 grid): rounded frame with a rule-of-thirds grid and four accent nodes | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/render_from_material.svg | SolidCraft contributors | original Looks icon master (64 grid): look sphere struck through above a plain grey slab | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/render_ground.svg | SolidCraft contributors | original Studio icon master (64 grid): grey cube on a slab with an accent contact patch | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/render_lens.svg | SolidCraft contributors | original Camera icon master (64 grid): concentric lens rings around an accent centre | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/render_library.svg | SolidCraft contributors | original Studio icon master (64 grid): row of three look spheres, middle one accent, on a shelf bar | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/render_light_area.svg | SolidCraft contributors | original Lights icon master (64 grid): slanted flat panel above a dotted accent stem | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/render_light_by_highlight.svg | SolidCraft contributors | original Lights icon master (64 grid): shaded sphere with a ringed highlight target and dotted stem arriving from above | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/render_light_point.svg | SolidCraft contributors | original Lights icon master (64 grid): round source disc with centre dot above a dotted accent stem | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/render_light_spot.svg | SolidCraft contributors | original Lights icon master (64 grid): cone source with curved rim above a dotted accent stem | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/render_lighting_presets.svg | SolidCraft contributors | original Studio icon master (64 grid): two stacked cards, the front one holding a light bulb | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/render_output_size.svg | SolidCraft contributors | original Output icon master (64 grid): picture frame with a diagonal double-headed dimension arrow | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/render_paint.svg | SolidCraft contributors | original Looks icon master (64 grid): flat brush with an accent tip, light ferrule and slate handle | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/render_pick_up.svg | SolidCraft contributors | original Looks icon master (64 grid): eyedropper with a grey bulb, slate crossbar and accent sampling tip | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/render_quality.svg | SolidCraft contributors | original Output icon master (64 grid): three rising bars, the tallest in accent | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/render_replace_all.svg | SolidCraft contributors | original Looks icon master (64 grid): grey sample sphere with an arrow to an accent sphere beside a second one | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/render_results.svg | SolidCraft contributors | original Output icon master (64 grid): stack of two pictures, the front one showing a landscape | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/render_same_look.svg | SolidCraft contributors | original Looks icon master (64 grid): look sphere and three cubes, the two matching cubes ringed | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/render_shot.svg | SolidCraft contributors | original Camera icon master (64 grid): camera body with a lower-right plus badge | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/render_shots_strip.svg | SolidCraft contributors | original Camera icon master (64 grid): strip of three small frames, the middle one in accent | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/render_solo_light.svg | SolidCraft contributors | original Lights icon master (64 grid): point source and dotted stem inside four corner focus brackets | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/render_sun.svg | SolidCraft contributors | original Lights icon master (64 grid): source disc with eight short radial rays | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/render_transparent_background.svg | SolidCraft contributors | original Output icon master (64 grid): grey cube on a checker tile | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/render_update_shot.svg | SolidCraft contributors | original Camera icon master (64 grid): camera body with a lower-right refresh badge | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
|
||||
### UI icon masters (continued)
|
||||
|
||||
| File | Author | Source | Licence |
|
||||
|---|---|---|---|
|
||||
| assets/icons/ui/design/svg/model/compute.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/configuration_table.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/conic.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/constrainer.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/construction.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/convert_sheet.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/copy.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/curvature_comb.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/curvature_map.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/cylinder.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/decal.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/delete.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/dimension.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/dots.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/draft.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/draft_analysis.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/drive.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/dxf.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/edge_continuity.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/edit.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/ellipse.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/emboss.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/environment_map.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/explode.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/export.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/extend.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/extrude.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/eye.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/fastener.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/fillet.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/filter.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/finish.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/fit_section.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/flange.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/flat.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/fold.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/folder.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/graph.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/hem.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/hole.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/import.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/include.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/inspect.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/interference.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/intersect.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/intersection_curve.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/iso_analysis.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/iso_curve.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/joint.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/joint_origin.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/library.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/line.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/line_mid.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/lip.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/list.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/loft.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/material.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/measure.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/min_radius.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/mirror.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/motion_link.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/move.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/new.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/offset.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/offset_face.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/offset_surface.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/open.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/origin.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/params.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/paste.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/patch.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/pattern.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/pattern_circ.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/pattern_path.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/pattern_rect.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/perforate.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/pipe.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/silhouette.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/assistant.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/agent_link.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/offset_two_sides.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/offset_symmetric.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/import_tray.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/export_tray.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/send.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/stop.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/shield.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/status_recovery.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/frame_member.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/render_environment.svg | SolidCraft contributors | original Studio icon master (64 grid): dome with a grey cube inside | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/style_shaded.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/style_wireframe.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/style_hidden_edges.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/style_translucent.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/select_faces_edges.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/select_bodies.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/select_features.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/select_parts.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/select_components.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/select_sketch.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/display.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/grid.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/ground_shadow.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/ambient_occlusion.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/placeholder.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/plane.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/plane_angle.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/plastic_assign.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/plastic_rule.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/play.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/point.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/polygon.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/presspull.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/project.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/project_surface.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/rect.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/rect3.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/rect_center.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/rect_rounded.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/refold.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/rename.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/render_image.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/render_scene.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/reorder.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/rest.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/restore.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/reverse_normal.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/revert.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/revolve.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/rib.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/rigid_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/rollback.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/ruled.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/scale.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/section.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/select.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/sheet.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/sheet_rules.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/shell.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/sketch.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/sketch_chamfer.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/sketch_fillet.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/sketch_mirror.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/slot.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/snap.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/sphere.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/spline.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/spline_cv.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/split_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/split_face.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/spun.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/star.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/status_error.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/status_warning.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/stitch.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/suppress.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/surface.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/svg.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/sweep.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/text.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/thicken.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/thread.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/torus.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/trim.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/unfold.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/unstitch.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/untrim.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/update.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/zebra.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/small/as_built.svg | SolidCraft contributors | small-slot icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/small/component.svg | SolidCraft contributors | small-slot icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/small/curvature_comb.svg | SolidCraft contributors | small-slot icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/small/interference.svg | SolidCraft contributors | small-slot icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/small/iso_analysis.svg | SolidCraft contributors | small-slot icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/small/joint.svg | SolidCraft contributors | small-slot icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/small/pattern.svg | SolidCraft contributors | small-slot icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/small/section.svg | SolidCraft contributors | small-slot icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/workspace/ws_animate.svg | SolidCraft contributors | workspace icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/polygon_circumscribed.svg | SolidCraft contributors | original sketch variant icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/polygon_edge.svg | SolidCraft contributors | original sketch variant icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/slot_overall.svg | SolidCraft contributors | original sketch variant icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/slot_center.svg | SolidCraft contributors | original sketch variant icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/arc_slot_center.svg | SolidCraft contributors | original sketch variant icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/sketch_chamfer_angle.svg | SolidCraft contributors | original sketch variant icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/sketch_chamfer_two_distances.svg | SolidCraft contributors | original sketch variant icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/gear.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/rack_pinion.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/screw.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/cam.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/trace.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/agent_chat.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/normal.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/infinite.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/pattern_flip.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/pattern_center.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/reach.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/cut.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/compare.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/web.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/replace_face.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/bounding_solid.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/delete_face.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/snap_fit.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/contact_sets.svg | SolidCraft contributors | original contact icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/contact_all.svg | SolidCraft contributors | original contact icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/contact_off.svg | SolidCraft contributors | original contact icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/contact_new.svg | SolidCraft contributors | original contact icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/axis_through_cylinder.svg | SolidCraft contributors | original construction icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/axis_normal_to_face.svg | SolidCraft contributors | original construction icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/axis_two_planes.svg | SolidCraft contributors | original construction icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/axis_two_points.svg | SolidCraft contributors | original construction icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/axis_edge.svg | SolidCraft contributors | original construction icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/point_vertex.svg | SolidCraft contributors | original construction icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/point_two_edges.svg | SolidCraft contributors | original construction icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/point_three_planes.svg | SolidCraft contributors | original construction icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/point_center.svg | SolidCraft contributors | original construction icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/point_edge_plane.svg | SolidCraft contributors | original construction icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/point_along_path.svg | SolidCraft contributors | original construction icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/plane_midplane.svg | SolidCraft contributors | original construction icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/plane_two_edges.svg | SolidCraft contributors | original construction icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/plane_three_points.svg | SolidCraft contributors | original construction icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/plane_tangent.svg | SolidCraft contributors | original construction icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/plane_along_path.svg | SolidCraft contributors | original construction icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/plane_perpendicular.svg | SolidCraft contributors | original construction icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/workspace/ws_design.svg | SolidCraft contributors | workspace icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/workspace/ws_drawing.svg | SolidCraft contributors | workspace icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/workspace/ws_render.svg | SolidCraft contributors | workspace icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/references.toml | SolidCraft contributors | original icon authoring or review tool resource | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/tools/author/bases.py | SolidCraft contributors | original icon authoring or review tool resource | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/tools/author/new_icon.py | SolidCraft contributors | original icon authoring or review tool resource | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/tools/review/index.html | SolidCraft contributors | original icon authoring or review tool resource | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/tools/review/guide.html | SolidCraft contributors | original icon authoring or review tool resource | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/tools/review/review.css | SolidCraft contributors | original icon authoring or review tool resource | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/tools/review/review.js | SolidCraft contributors | original icon authoring or review tool resource | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/tools/icon_palette.py | SolidCraft contributors | Original shared semantic icon palette resolver for repository tools | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/tools/icon_status.py | SolidCraft contributors | icon lint, status page or preview tool (standard-library Python), original SolidCraft code | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/tools/lint_icons.py | SolidCraft contributors | icon lint, status page or preview tool (standard-library Python), original SolidCraft code | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/tools/preview.py | SolidCraft contributors | icon lint, status page or preview tool (standard-library Python), original SolidCraft code | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/tools/review_state.py | SolidCraft contributors | icon review state helper (standard-library Python), original SolidCraft code | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/requested_icons.txt | SolidCraft contributors | Runtime icon requests collected by the headless menu audit, original SolidCraft data | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/review.json | SolidCraft contributors | icon review state (accepted icons and notes), original SolidCraft data | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/tools/author/lib.py | SolidCraft contributors | icon authoring script (standard-library Python), original SolidCraft code | MIT OR Apache-2.0 |
|
||||
| crates/look/icons/design/svg/model/compute.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/configuration_table.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/conic.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/constrainer.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/construction.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/convert_sheet.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/copy.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/curvature_comb.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/curvature_map.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/cylinder.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/decal.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/delete.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/dimension.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/dots.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/draft.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/draft_analysis.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/drive.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/dxf.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/edge_continuity.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/edit.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/ellipse.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/emboss.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/environment_map.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/explode.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/export.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/extend.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/extrude.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/eye.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/fastener.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/fillet.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/filter.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/finish.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/fit_section.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/flange.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/flat.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/fold.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/folder.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/graph.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/hem.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/hole.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/import.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/include.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/inspect.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/interference.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/intersect.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/intersection_curve.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/iso_analysis.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/iso_curve.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/joint.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/joint_origin.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/library.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/line.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/line_mid.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/lip.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/list.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/loft.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/material.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/measure.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/min_radius.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/mirror.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/motion_link.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/move.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/new.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/offset.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/offset_face.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/offset_surface.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/open.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/origin.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/params.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/paste.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/patch.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/pattern.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/pattern_circ.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/pattern_path.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/pattern_rect.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/perforate.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/pipe.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/silhouette.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/assistant.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/agent_link.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/offset_two_sides.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/offset_symmetric.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/import_tray.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/export_tray.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/send.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/stop.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/shield.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/status_recovery.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/frame_member.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/render_environment.svg | SolidCraft contributors | original Studio icon master (64 grid): dome with a grey cube inside | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/style_shaded.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/style_wireframe.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/style_hidden_edges.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/style_translucent.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/select_faces_edges.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/select_bodies.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/select_features.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/select_parts.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/select_components.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/select_sketch.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/display.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/grid.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/ground_shadow.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/ambient_occlusion.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/placeholder.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/plane.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/plane_angle.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/plastic_assign.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/plastic_rule.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/play.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/point.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/polygon.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/presspull.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/project.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/project_surface.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/rect.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/rect3.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/rect_center.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/rect_rounded.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/refold.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/rename.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/render_image.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/render_scene.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/reorder.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/rest.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/restore.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/reverse_normal.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/revert.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/revolve.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/rib.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/rigid_group.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/rollback.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/ruled.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/scale.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/section.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/select.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/sheet.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/sheet_rules.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/shell.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/sketch.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/sketch_chamfer.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/sketch_fillet.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/sketch_mirror.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/slot.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/snap.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/sphere.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/spline.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/spline_cv.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/split_body.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/split_face.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/spun.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/star.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/status_error.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/status_warning.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/stitch.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/suppress.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/surface.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/svg.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/sweep.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/text.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/thicken.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/thread.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/torus.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/trim.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/unfold.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/unstitch.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/untrim.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/update.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/zebra.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/small/as_built.svg | SolidCraft contributors | small-slot icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/small/component.svg | SolidCraft contributors | small-slot icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/small/curvature_comb.svg | SolidCraft contributors | small-slot icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/small/interference.svg | SolidCraft contributors | small-slot icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/small/iso_analysis.svg | SolidCraft contributors | small-slot icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/small/joint.svg | SolidCraft contributors | small-slot icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/small/pattern.svg | SolidCraft contributors | small-slot icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/small/section.svg | SolidCraft contributors | small-slot icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/workspace/ws_animate.svg | SolidCraft contributors | workspace icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/polygon_circumscribed.svg | SolidCraft contributors | original sketch variant icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/polygon_edge.svg | SolidCraft contributors | original sketch variant icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/slot_overall.svg | SolidCraft contributors | original sketch variant icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/slot_center.svg | SolidCraft contributors | original sketch variant icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/arc_slot_center.svg | SolidCraft contributors | original sketch variant icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/sketch_chamfer_angle.svg | SolidCraft contributors | original sketch variant icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/sketch_chamfer_two_distances.svg | SolidCraft contributors | original sketch variant icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/gear.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/rack_pinion.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/screw.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/cam.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/trace.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/agent_chat.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/normal.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/infinite.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/pattern_flip.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/pattern_center.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/reach.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/cut.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/compare.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/web.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/replace_face.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/bounding_solid.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/delete_face.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/snap_fit.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/contact_sets.svg | SolidCraft contributors | original contact icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/contact_all.svg | SolidCraft contributors | original contact icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/contact_off.svg | SolidCraft contributors | original contact icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/contact_new.svg | SolidCraft contributors | original contact icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/axis_through_cylinder.svg | SolidCraft contributors | original construction icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/axis_normal_to_face.svg | SolidCraft contributors | original construction icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/axis_two_planes.svg | SolidCraft contributors | original construction icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/axis_two_points.svg | SolidCraft contributors | original construction icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/axis_edge.svg | SolidCraft contributors | original construction icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/point_vertex.svg | SolidCraft contributors | original construction icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/point_two_edges.svg | SolidCraft contributors | original construction icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/point_three_planes.svg | SolidCraft contributors | original construction icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/point_center.svg | SolidCraft contributors | original construction icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/point_edge_plane.svg | SolidCraft contributors | original construction icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/point_along_path.svg | SolidCraft contributors | original construction icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/plane_midplane.svg | SolidCraft contributors | original construction icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/plane_two_edges.svg | SolidCraft contributors | original construction icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/plane_three_points.svg | SolidCraft contributors | original construction icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/plane_tangent.svg | SolidCraft contributors | original construction icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/plane_along_path.svg | SolidCraft contributors | original construction icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/plane_perpendicular.svg | SolidCraft contributors | original construction icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/workspace/ws_design.svg | SolidCraft contributors | workspace icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/workspace/ws_drawing.svg | SolidCraft contributors | workspace icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/workspace/ws_render.svg | SolidCraft contributors | workspace icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/references.toml | SolidCraft contributors | original icon authoring or review tool resource | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/tools/author/bases.py | SolidCraft contributors | original icon authoring or review tool resource | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/tools/author/new_icon.py | SolidCraft contributors | original icon authoring or review tool resource | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/tools/review/index.html | SolidCraft contributors | original icon authoring or review tool resource | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/tools/review/guide.html | SolidCraft contributors | original icon authoring or review tool resource | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/tools/review/review.css | SolidCraft contributors | original icon authoring or review tool resource | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/tools/review/review.js | SolidCraft contributors | original icon authoring or review tool resource | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/tools/icon_palette.py | SolidCraft contributors | Original shared semantic icon palette resolver for repository tools | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/tools/icon_status.py | SolidCraft contributors | icon lint, status page or preview tool (standard-library Python), original SolidCraft code | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/tools/lint_icons.py | SolidCraft contributors | icon lint, status page or preview tool (standard-library Python), original SolidCraft code | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/tools/preview.py | SolidCraft contributors | icon lint, status page or preview tool (standard-library Python), original SolidCraft code | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/tools/review_state.py | SolidCraft contributors | icon review state helper (standard-library Python), original SolidCraft code | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/requested_icons.txt | SolidCraft contributors | Runtime icon requests collected by the headless menu audit, original SolidCraft data | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/review.json | SolidCraft contributors | icon review state (accepted icons and notes), original SolidCraft data | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/tools/author/lib.py | SolidCraft contributors | icon authoring script (standard-library Python), original SolidCraft code | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
|
||||
| docs/book/src/og.png | SolidCraft contributors | copy of assets/branding/web/source/og.png staged by cargo xtask book (gitignored) | MIT OR Apache-2.0 |
|
||||
| docs/sponsors/blacksmith-ci-powered.png | Blacksmith (blacksmith.sh) | "CI powered by Blacksmith" sponsor banner supplied by Blacksmith for the sponsorship credit; used only to credit the sponsor, not part of the application | © Blacksmith, used with permission |
|
||||
| assets/icons/ui/design/svg/model/path_flange.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| crates/look/icons/design/svg/model/path_flange.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| docs/book/src/generated/hem.png | SolidCraft contributors | rendered by `cargo xtask book` (`solidcraft-cli snapshot docs/book/scripts/hem.json`; gitignored), original sheet metal demonstration | MIT OR Apache-2.0 |
|
||||
| docs/book/scripts/hem.json | SolidCraft contributors | original parametric recipe for an 80 × 50 mm sheet with an 8 mm returned edge, authored for the command guide | MIT OR Apache-2.0 |
|
||||
| assets/styles/ui/themes/clay.json | SolidCraft contributors | original SolidCraft theme file (Clay, light): warm paper palette chosen for SolidCraft | MIT OR Apache-2.0 |
|
||||
| assets/styles/ui/themes/clay-dark.json | SolidCraft contributors | original SolidCraft theme file (Clay Dark): warm charcoal palette chosen for SolidCraft | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/cone.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| crates/look/themes/clay.json | SolidCraft contributors | original SolidCraft theme file (Clay, light): warm paper palette chosen for SolidCraft | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/themes/clay-dark.json | SolidCraft contributors | original SolidCraft theme file (Clay Dark): warm charcoal palette chosen for SolidCraft | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/cone.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| assets/locales/ar.json | Abdullah (A-AL-ANAZI) | Original Arabic translation of SolidCraft's English catalog; no commercial CAD text used | MIT OR Apache-2.0 |
|
||||
| assets/locales/he.json | SolidCraft contributors | Original Hebrew translation of SolidCraft's English catalog; no commercial CAD text used | MIT OR Apache-2.0 |
|
||||
| assets/styles/ui/themes/cga.json | SolidCraft contributors | original SolidCraft theme file using the 16 colours of the IBM Color Graphics Adapter (black, cyan, magenta, and white of its high-intensity palette 1 for the interface) | MIT OR Apache-2.0 |
|
||||
| assets/styles/ui/themes/1-bit.json | SolidCraft contributors | original SolidCraft theme file | MIT OR Apache-2.0 |
|
||||
| assets/styles/ui/themes/1-bit-dark.json | SolidCraft contributors | original SolidCraft theme file | MIT OR Apache-2.0 |
|
||||
| crates/look/themes/cga.json | SolidCraft contributors | original SolidCraft theme file using the 16 colours of the IBM Color Graphics Adapter (black, cyan, magenta, and white of its high-intensity palette 1 for the interface) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/themes/1-bit.json | SolidCraft contributors | original SolidCraft theme file | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/themes/1-bit-dark.json | SolidCraft contributors | original SolidCraft theme file | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| `assets/locales/pending/navbar-customisation.json` | SolidCraft contributors | Original navigation bar editor translations | MIT OR Apache-2.0 |
|
||||
| `assets/locales/pending/navbar-slots.json` | SolidCraft contributors | Original navigation slot translations | MIT OR Apache-2.0 |
|
||||
| assets/locales/bs.json | Tarik Sijercic (tsijercic1) | Original Bosnian translation of SolidCraft's English catalog; no commercial CAD text used | MIT OR Apache-2.0 |
|
||||
| assets/locales/hr.json | Tarik Sijercic (tsijercic1) | Original Croatian translation of SolidCraft's English catalog; no commercial CAD text used | MIT OR Apache-2.0 |
|
||||
| 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 |
|
||||
| crates/look/icons/design/svg/model/finish_edit.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| `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 |
|
||||
| crates/look/icons/design/svg/model/feature_group.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/mesh_body.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/timeline_play.svg | SolidCraft contributors | Original history playback icon; canonical grey_cube base and original action cue | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/timeline_stop.svg | SolidCraft contributors | Original history playback icon; canonical grey_cube base and original action cue | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/flat/status_pin.svg | SolidCraft contributors | Original analytic pin icon for persistent viewport results | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| assets/locales/pending/render-wear.json | SolidCraft contributors | Original UI labels and translations | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/equation_curve.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| crates/look/icons/design/svg/model/equation_curve.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| assets/locales/pending/sketch-recent-snap.json | SolidCraft contributors | Original preference messages for the recent centre and midpoint snap | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/construction_line.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/construction_line_horizontal.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/construction_line_vertical.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/construction_line_angle.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/construction_line_parallel.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/construction_line_perpendicular.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/construction_line_tangent_external.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/construction_line_tangent_at.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/construction_line_tangent_two.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/construction_line_bisector.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| crates/look/icons/design/svg/model/construction_line.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/construction_line_horizontal.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/construction_line_vertical.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/construction_line_angle.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/construction_line_parallel.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/construction_line_perpendicular.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/construction_line_tangent_external.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/construction_line_tangent_at.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/construction_line_tangent_two.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/construction_line_bisector.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| docs/book/src/generated/equation-circle.png | SolidCraft contributors | rendered by `cargo xtask book` (`solidcraft-cli snapshot docs/book/scripts/equation-circle.json`; gitignored) | MIT OR Apache-2.0 |
|
||||
| docs/book/src/generated/equation-flower.png | SolidCraft contributors | rendered by `cargo xtask book` (`solidcraft-cli snapshot docs/book/scripts/equation-flower.json`; gitignored) | MIT OR Apache-2.0 |
|
||||
| docs/book/src/generated/equation-involute.png | SolidCraft contributors | rendered by `cargo xtask book` (`solidcraft-cli snapshot docs/book/scripts/equation-involute.json`; gitignored) | MIT OR Apache-2.0 |
|
||||
@@ -653,9 +654,9 @@ Original SolidCraft drawings, Open for owner review; no runtime assignments.
|
||||
| docs/book/src/generated/equation-parabola.png | SolidCraft contributors | rendered by `cargo xtask book` (`solidcraft-cli snapshot docs/book/scripts/equation-parabola.json`; gitignored) | MIT OR Apache-2.0 |
|
||||
| docs/book/src/generated/equation-spiral.png | SolidCraft contributors | rendered by `cargo xtask book` (`solidcraft-cli snapshot docs/book/scripts/equation-spiral.json`; gitignored) | MIT OR Apache-2.0 |
|
||||
| docs/book/src/generated/equation-wave.png | SolidCraft contributors | rendered by `cargo xtask book` (`solidcraft-cli snapshot docs/book/scripts/equation-wave.json`; gitignored) | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/print_face.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
|
||||
| crates/look/icons/design/svg/model/print_face.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| assets/locales/fi.json | SolidCraft contributors | Original Finnish translation of SolidCraft's English catalog, AI-assisted (Claude Code) clean-room from the English and not yet reviewed line by line by a native speaker; no commercial CAD text used | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/model/plane_axis_point.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
|
||||
| crates/look/icons/design/svg/model/plane_axis_point.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| docs/design/preferences/figures/aa-2x.dark.svg | SolidCraft contributors | original SolidCraft artwork drawn for the Preferences redesign (tracker #9863), extracted from the design board as a standalone SVG | MIT OR Apache-2.0 |
|
||||
| docs/design/preferences/figures/aa-2x.light.svg | SolidCraft contributors | original SolidCraft artwork drawn for the Preferences redesign (tracker #9863), extracted from the design board as a standalone SVG | MIT OR Apache-2.0 |
|
||||
| docs/design/preferences/figures/aa-4x.dark.svg | SolidCraft contributors | original SolidCraft artwork drawn for the Preferences redesign (tracker #9863), extracted from the design board as a standalone SVG | MIT OR Apache-2.0 |
|
||||
@@ -779,20 +780,20 @@ Original SolidCraft drawings, Open for owner review; no runtime assignments.
|
||||
| docs/design/preferences/figures/view-shadow.dark.svg | SolidCraft contributors | original SolidCraft artwork drawn for the Preferences redesign (tracker #9863), extracted from the design board as a standalone SVG | MIT OR Apache-2.0 |
|
||||
| docs/design/preferences/figures/view-shadow.light.svg | SolidCraft contributors | original SolidCraft artwork drawn for the Preferences redesign (tracker #9863), extracted from the design board as a standalone SVG | MIT OR Apache-2.0 |
|
||||
| `assets/locales/pending/sketch-offset-instances.json` | SolidCraft contributors | Original offset instance-count label and translations | MIT OR Apache-2.0 |
|
||||
| assets/icons/ui/design/svg/flat/settings_profile.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original analytic head and shoulder geometry for settings profiles | MIT OR Apache-2.0 |
|
||||
| crates/look/icons/design/svg/flat/settings_profile.svg | SolidCraft contributors | single-colour application/navigation icon master (64 grid), original analytic head and shoulder geometry for settings profiles | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| tests/kernel-cases/import/4561-convert-box-mesh-with-a-zero-area-triangle/box-degenerate.stl | SolidCraft contributors | synthetic ASCII STL written by hand: a box with one zero-area triangle, for the kernel regression case of tangency-labs/solidcraft#4561 | MIT OR Apache-2.0 |
|
||||
| assets/locales/pending/theme-blur-ui.json | SolidCraft contributors | Original blur controls, notices and translations | MIT OR Apache-2.0 |
|
||||
| crates/ui-egui/tests/fixtures/theme-blur.json | SolidCraft contributors | Original theme for blur option scenarios and manager review | MIT OR Apache-2.0 |
|
||||
| assets/locales/ka.json | David Machakhelidze (devius) | Original Georgian translation of SolidCraft's English catalog, written with Claude Code from the meaning of each English string; terminology and doubtful strings decided by a native Georgian speaker; no commercial CAD text used | MIT OR Apache-2.0 |
|
||||
| assets/branding/logo/solidcraft-mark.svg | SolidCraft contributors | static SolidCraft mark: the five faces and gradients of assets/icons/app/macos/source/SolidCraft.icon/Assets/03-solid-blue-cutout.svg (the final frame of assets/styles/web/loading-logo.svg), cropped to the mark's bounds; original artwork | MIT OR Apache-2.0 |
|
||||
| assets/branding/logo/solidcraft-mark-mono-black.svg | SolidCraft contributors | one-colour (black) version of assets/branding/logo/solidcraft-mark.svg, same paths; original artwork | MIT OR Apache-2.0 |
|
||||
| assets/branding/logo/solidcraft-mark-mono-white.svg | SolidCraft contributors | one-colour (white) version of assets/branding/logo/solidcraft-mark.svg, same paths; original artwork | MIT OR Apache-2.0 |
|
||||
| assets/branding/logo/solidcraft-mark-512.png | SolidCraft contributors | transparent 512 px render of assets/branding/logo/solidcraft-mark.svg (cairosvg); original artwork | MIT OR Apache-2.0 |
|
||||
| assets/branding/logo/solidcraft-mark-1024.png | SolidCraft contributors | transparent 1024 px render of assets/branding/logo/solidcraft-mark.svg (cairosvg); original artwork | MIT OR Apache-2.0 |
|
||||
| assets/branding/logo/solidcraft-mark-2048.png | SolidCraft contributors | transparent 2048 px render of assets/branding/logo/solidcraft-mark.svg (cairosvg); original artwork | MIT OR Apache-2.0 |
|
||||
| assets/branding/logo/solidcraft-wordmark.svg | SolidCraft contributors | the name SolidCraft set like the loading logo's wordmark (bold, +0.02 em tracking, #15499e) in IBM Plex Sans Bold from assets/fonts/ibm-plex-sans (SIL OFL 1.1, IBM Corp.), outlined to paths; no font file is embedded | MIT OR Apache-2.0 |
|
||||
| assets/branding/logo/solidcraft-lockup-horizontal.svg | SolidCraft contributors | assets/branding/logo/solidcraft-mark.svg beside assets/branding/logo/solidcraft-wordmark.svg, in the proportions of assets/branding/web/source/og.png; original artwork | MIT OR Apache-2.0 |
|
||||
| assets/styles/ui/themes/onyx.json | SolidCraft contributors | original Onyx stone-grey palette, option overlays and semantic icon-role mapping; existing SolidCraft artwork is unchanged | MIT OR Apache-2.0 |
|
||||
| assets/branding/logo/solidcraft-mark.svg | SolidCraft contributors | static SolidCraft mark: the five faces and gradients of assets/icons/app/macos/source/SolidCraft.icon/Assets/03-solid-blue-cutout.svg (the final frame of assets/styles/web/loading-logo.svg), cropped to the mark's bounds; original artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| assets/branding/logo/solidcraft-mark-mono-black.svg | SolidCraft contributors | one-colour (black) version of assets/branding/logo/solidcraft-mark.svg, same paths; original artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| assets/branding/logo/solidcraft-mark-mono-white.svg | SolidCraft contributors | one-colour (white) version of assets/branding/logo/solidcraft-mark.svg, same paths; original artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| assets/branding/logo/solidcraft-mark-512.png | SolidCraft contributors | transparent 512 px render of assets/branding/logo/solidcraft-mark.svg (cairosvg); original artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| assets/branding/logo/solidcraft-mark-1024.png | SolidCraft contributors | transparent 1024 px render of assets/branding/logo/solidcraft-mark.svg (cairosvg); original artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| assets/branding/logo/solidcraft-mark-2048.png | SolidCraft contributors | transparent 2048 px render of assets/branding/logo/solidcraft-mark.svg (cairosvg); original artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| assets/branding/logo/solidcraft-wordmark.svg | SolidCraft contributors | the name SolidCraft set like the loading logo's wordmark (bold, +0.02 em tracking, #15499e) in IBM Plex Sans Bold from crates/look/fonts/ibm-plex-sans (SIL OFL 1.1, IBM Corp.), outlined to paths; no font file is embedded | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| assets/branding/logo/solidcraft-lockup-horizontal.svg | SolidCraft contributors | assets/branding/logo/solidcraft-mark.svg beside assets/branding/logo/solidcraft-wordmark.svg, in the proportions of assets/branding/web/source/og.png; original artwork | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/themes/onyx.json | SolidCraft contributors | original Onyx stone-grey palette, option overlays and semantic icon-role mapping; existing SolidCraft artwork is unchanged | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| docs/book/src/media/ui-tour/window.png | SolidCraft contributors | screenshot of SolidCraft 0.29.0 itself (`solidcraft --sample`, default dark theme, software renderer, 1280x800) with original numbered callouts (digits set in DejaVu Sans Bold), captured with examples/demo/doc_shots.py | MIT OR Apache-2.0 |
|
||||
| docs/book/src/media/ui-tour/navigate.mp4 | SolidCraft contributors | original screen recording of the actual SolidCraft 0.29.0 English desktop UI (`--sample`, default dark theme, software renderer) orbiting, panning and zooming, with the original drawn pointer of examples/demo/overlay.py and labels set in DejaVu Sans Bold, captured with examples/demo/doc_shots.py | MIT OR Apache-2.0 |
|
||||
| assets/locales/pending/sketch-tool-hints.json | carlymx | Original sketch tool hints and engine error translations | MIT OR Apache-2.0 |
|
||||
|
||||
+8
-4
@@ -321,7 +321,7 @@ 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
|
||||
Built-in themes need only a JSON file in `crates/look/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`
|
||||
@@ -509,11 +509,15 @@ The user guide's screenshots and short clips (`docs/book/src/media/`) are captur
|
||||
app by `examples/demo/doc_shots.py`, one function per figure. Each run starts a fresh app with its
|
||||
own settings, so your preferences never show. When a change makes a figure out of date, run
|
||||
`python3 examples/demo/doc_shots.py <page or shot>` (it needs Xvfb, ffmpeg, Pillow and a release
|
||||
build) and commit the new file. A new figure is a new function there, an ATTRIBUTION row in
|
||||
`attribution/pending/`, and a `<video>` (clips) or image link on the page. Keep a still under
|
||||
build) and commit the new file. Stills come in both themes: `--light` makes `<name>.light.png`,
|
||||
and the page shows the one that matches the book's theme (an `<img class="dark-ui">` and an
|
||||
`<img class="light-ui">`). A new figure is a new function there, an ATTRIBUTION row in
|
||||
`attribution/pending/`, and a `<video>` (clips) or the image pair on the page. Keep a still under
|
||||
about 250 KB and a clip under about 1 MB.
|
||||
|
||||
## Licence
|
||||
|
||||
By contributing you agree that your contribution is licensed as MIT OR Apache-2.0, like the rest
|
||||
of SolidCraft. SolidCraft isn't affiliated with any CAD vendor; product names are trademarks of their owners (see NOTICE).
|
||||
of SolidCraft. A contribution to the brand and interface (`crates/ui-kit`, `crates/look`,
|
||||
`crates/theme`, `assets/branding`, `assets/icons/app`) is licensed under
|
||||
[LICENSE-BRAND](LICENSE-BRAND), which lets the maintainers also license it as MIT OR Apache-2.0. SolidCraft isn't affiliated with any CAD vendor; product names are trademarks of their owners (see NOTICE).
|
||||
|
||||
Generated
+50
-13
@@ -4234,6 +4234,16 @@ dependencies = [
|
||||
"thiserror 2.0.21",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "solidcore-step"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"solidcore",
|
||||
"solidcore-convert",
|
||||
"solidcore-ops",
|
||||
"solidcore-record",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "solidcore-tess"
|
||||
version = "0.1.0"
|
||||
@@ -4275,6 +4285,7 @@ dependencies = [
|
||||
"solidcraft-control",
|
||||
"solidcraft-engine",
|
||||
"solidcraft-gpu",
|
||||
"solidcraft-look",
|
||||
"solidcraft-space-mouse",
|
||||
"solidcraft-theme",
|
||||
"solidcraft-ui-egui",
|
||||
@@ -4477,16 +4488,28 @@ dependencies = [
|
||||
"serde_json",
|
||||
"solidcore-ops",
|
||||
"solidcore-record",
|
||||
"solidcore-step",
|
||||
"solidcore-tess",
|
||||
"solidcraft-geom",
|
||||
"solidcraft-profile",
|
||||
"solidcraft-smlib",
|
||||
"solidcraft-step",
|
||||
"spade",
|
||||
"thiserror 2.0.21",
|
||||
"web-time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "solidcraft-look"
|
||||
version = "0.40.0-rc.3"
|
||||
dependencies = [
|
||||
"egui",
|
||||
"log",
|
||||
"solidcraft-theme",
|
||||
"solidcraft-ui-kit",
|
||||
"tiny-skia",
|
||||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "solidcraft-mcp"
|
||||
version = "0.40.0-rc.3"
|
||||
@@ -4574,16 +4597,6 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "solidcraft-step"
|
||||
version = "0.40.0-rc.3"
|
||||
dependencies = [
|
||||
"solidcore-ops",
|
||||
"solidcore-record",
|
||||
"solidcraft-geom",
|
||||
"solidcraft-profile",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "solidcraft-testkit"
|
||||
version = "0.40.0-rc.3"
|
||||
@@ -4609,7 +4622,6 @@ dependencies = [
|
||||
"log",
|
||||
"lopdf",
|
||||
"minisign-verify",
|
||||
"muda",
|
||||
"nix 0.31.3",
|
||||
"pollster 0.4.0",
|
||||
"proc-macro2",
|
||||
@@ -4624,8 +4636,10 @@ dependencies = [
|
||||
"solidcraft-control-egui",
|
||||
"solidcraft-engine",
|
||||
"solidcraft-gpu",
|
||||
"solidcraft-look",
|
||||
"solidcraft-space-mouse",
|
||||
"solidcraft-theme",
|
||||
"solidcraft-ui-kit",
|
||||
"solidcraft-ui-registry",
|
||||
"solidcraft-ui-text",
|
||||
"solidcraft-viewport",
|
||||
@@ -4633,13 +4647,35 @@ dependencies = [
|
||||
"solidcraft-viewport-gpu",
|
||||
"syn 2.0.119",
|
||||
"tiny-skia",
|
||||
"toml",
|
||||
"ttf-parser",
|
||||
"web-time",
|
||||
"winreg",
|
||||
"zip",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "solidcraft-ui-kit"
|
||||
version = "0.40.0-rc.3"
|
||||
dependencies = [
|
||||
"arboard",
|
||||
"egui",
|
||||
"egui-wgpu",
|
||||
"image",
|
||||
"log",
|
||||
"muda",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"solidcraft-color",
|
||||
"solidcraft-theme",
|
||||
"solidcraft-ui-registry",
|
||||
"solidcraft-ui-text",
|
||||
"solidcraft-viewport-egui",
|
||||
"solidcraft-viewport-gpu",
|
||||
"syn 2.0.119",
|
||||
"tiny-skia",
|
||||
"web-time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "solidcraft-ui-registry"
|
||||
version = "0.40.0-rc.3"
|
||||
@@ -4708,6 +4744,7 @@ dependencies = [
|
||||
"serde_json",
|
||||
"solidcraft-control",
|
||||
"solidcraft-engine",
|
||||
"solidcraft-look",
|
||||
"solidcraft-ui-egui",
|
||||
"solidcraft-ui-text",
|
||||
"url",
|
||||
|
||||
+4
-1
@@ -21,7 +21,6 @@ solidcraft-profile = { path = "crates/profile" }
|
||||
solidcraft-sketch = { path = "crates/sketch" }
|
||||
solidcraft-kernel = { path = "crates/kernel" }
|
||||
solidcraft-smlib = { path = "crates/smlib" }
|
||||
solidcraft-step = { path = "crates/step" }
|
||||
solidcraft-render = { path = "crates/render" }
|
||||
solidcraft-dynamics = { path = "crates/dynamics" }
|
||||
solidcraft-gpu = { path = "crates/gpu" }
|
||||
@@ -29,6 +28,8 @@ solidcraft-doc = { path = "crates/doc" }
|
||||
solidcraft-io = { path = "crates/io" }
|
||||
solidcraft-engine = { path = "crates/engine" }
|
||||
solidcraft-ui-egui = { path = "crates/ui-egui" }
|
||||
solidcraft-ui-kit = { path = "crates/ui-kit" }
|
||||
solidcraft-look = { path = "crates/look" }
|
||||
solidcraft-ui-registry = { path = "crates/ui-registry" }
|
||||
solidcraft-color = { path = "crates/color" }
|
||||
solidcraft-ui-text = { path = "crates/ui-text" }
|
||||
@@ -53,6 +54,8 @@ solidcore-record = { path = "solidcore/crates/solidcore-record" }
|
||||
# The modelling layer (solidcore's layers §1, "Ops"): the record-level calls SolidCraft makes into the
|
||||
# kernel, converting through solidcore-convert.
|
||||
solidcore-ops = { path = "solidcore/crates/solidcore-ops" }
|
||||
# STEP import and export (vendored with solidcore): the Part 21 parser is solidcore-record's.
|
||||
solidcore-step = { path = "solidcore/crates/solidcore-step" }
|
||||
# Geometry made drawable (solidcore's layers §3): the one mesher, SolidCraft's, moved into the
|
||||
# subtree (RFC 0003, item 1.1), with the display mesh and its levels of detail, the types
|
||||
# SolidCraft's meshes are. Vendored with solidcore, in the same subtree.
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
SolidCraft Brand and Interface Licence
|
||||
|
||||
Copyright (c) 2026 the SolidCraft maintainers.
|
||||
|
||||
SolidCraft's code that models, imports, exports and computes geometry is open source under the MIT
|
||||
License or the Apache License 2.0 (LICENSE-MIT, LICENSE-APACHE). This licence covers something
|
||||
different: how SolidCraft looks and feels. That is its brand. A CAD program can be built from
|
||||
SolidCraft's open code; it should not look like SolidCraft unless the maintainers have agreed.
|
||||
|
||||
1. What this licence covers ("the Brand Material")
|
||||
|
||||
a. The UI kit, `crates/ui-kit` (solidcraft-ui-kit): the code and the design of SolidCraft's
|
||||
controls, panels, menus, ribbon, app bar, history bar, navigation bar, view compass,
|
||||
Preferences window, start page and window chrome.
|
||||
b. The look, `crates/look` (solidcraft-look): the interface icon masters and their artwork,
|
||||
the code-drawn glyphs, and the built-in themes.
|
||||
c. The theme, `crates/theme` (solidcraft-theme): the design tokens, colour palettes, accent
|
||||
ramps, sizes and spacing that give SolidCraft its appearance.
|
||||
d. The SolidCraft name, logo, app icon and brand kit (`assets/branding`, `assets/icons/app`).
|
||||
|
||||
Third-party material inside these folders keeps its own licence, listed in ATTRIBUTION.md.
|
||||
In particular the IBM Plex fonts are under the SIL Open Font License 1.1, and nothing here
|
||||
limits what that licence allows.
|
||||
|
||||
2. What you may do without asking
|
||||
|
||||
a. Read, build, run and modify the Brand Material as part of SolidCraft itself, including
|
||||
your own builds and forks of SolidCraft used for development, testing, learning or
|
||||
contributing back.
|
||||
b. Contribute changes to the Brand Material through the SolidCraft repository.
|
||||
c. Show SolidCraft, with its look, in reviews, tutorials, articles, videos and teaching.
|
||||
|
||||
3. What needs the maintainers' written permission first
|
||||
|
||||
a. Using any Brand Material in another program, product, service or library, including
|
||||
linking to the UI kit, the look or the theme from software that is not SolidCraft.
|
||||
b. Distributing the Brand Material, or a modified version of it, other than as part of
|
||||
SolidCraft.
|
||||
c. Distributing a fork or modified build of SolidCraft to others under the SolidCraft name,
|
||||
logo or app icon, or with a look that could be taken for SolidCraft's.
|
||||
d. Using the SolidCraft name, logo or app icon to name, promote or endorse anything else.
|
||||
|
||||
To ask, open an issue at https://github.com/tangency-labs/solidcraft or contact the
|
||||
maintainers there. Permission is given in writing and may come with conditions.
|
||||
|
||||
4. Contributions
|
||||
|
||||
By contributing to the Brand Material you agree that the maintainers may license your
|
||||
contribution under this licence, and under the MIT License or the Apache License 2.0, at
|
||||
their choice.
|
||||
|
||||
5. Earlier versions
|
||||
|
||||
Versions of SolidCraft published before this licence took effect stay under the licences
|
||||
they were published with.
|
||||
|
||||
6. No warranty
|
||||
|
||||
The Brand Material is provided "as is", without warranty of any kind, express or implied,
|
||||
including the warranties of merchantability, fitness for a particular purpose and
|
||||
non-infringement. In no event shall the maintainers or contributors be liable for any
|
||||
claim, damages or other liability arising from the Brand Material or its use.
|
||||
@@ -3,6 +3,15 @@ Copyright (c) 2026 SolidCraft contributors.
|
||||
Licensed under the MIT License or the Apache License, Version 2.0, at your option
|
||||
(LICENSE-MIT, LICENSE-APACHE).
|
||||
|
||||
Brand and interface
|
||||
|
||||
SolidCraft's brand and interface are not under MIT OR Apache-2.0. The UI kit (crates/ui-kit), the
|
||||
look (crates/look: the interface icons, glyphs and built-in themes), the theme (crates/theme: the
|
||||
design tokens and palettes), and the SolidCraft name, logo, app icon and brand kit are under the
|
||||
SolidCraft Brand and Interface Licence (LICENSE-BRAND). They may be used, changed and contributed
|
||||
to as part of SolidCraft; using them in anything else needs the maintainers' written permission.
|
||||
Third-party fonts in those folders keep their own licences.
|
||||
|
||||
Third-party material
|
||||
|
||||
Software dependencies are listed in Cargo.lock; their licences are in THIRD-PARTY-LICENSES.txt
|
||||
|
||||
@@ -133,6 +133,12 @@ MIT OR Apache-2.0, at your option. Developed under the
|
||||
[clean-room contribution rules](AGENTS.md); third-party code and assets retain their
|
||||
documented licences and attribution.
|
||||
|
||||
SolidCraft's brand and interface are licensed separately, under
|
||||
[LICENSE-BRAND](LICENSE-BRAND): the UI kit, the look (interface icons, glyphs, built-in themes),
|
||||
the theme's design tokens and palettes, and the SolidCraft name, logo and app icon. Use them freely
|
||||
as part of SolidCraft. Using them in another program or product needs the maintainers' written
|
||||
permission first.
|
||||
|
||||
SolidCraft is independent. Behaviour is designed from public documentation, general CAD
|
||||
conventions and user feedback. Reference tests use analytic values and open-source tools.
|
||||
SolidCraft is not affiliated with, sponsored by or endorsed by Autodesk, Dassault Systèmes, PTC,
|
||||
|
||||
@@ -24,6 +24,8 @@ profile = ["solidcraft-engine/profile"]
|
||||
solidcraft-engine = { workspace = true }
|
||||
solidcraft-control = { workspace = true }
|
||||
solidcraft-ui-egui = { workspace = true }
|
||||
# SolidCraft's look (icons, glyphs, built-in themes), installed at startup.
|
||||
solidcraft-look = { workspace = true }
|
||||
solidcraft-ui-text = { workspace = true }
|
||||
egui = { workspace = true }
|
||||
log = { workspace = true }
|
||||
|
||||
@@ -1246,7 +1246,7 @@ mod web {
|
||||
pub fn start() {
|
||||
eframe::WebLogger::init(log::LevelFilter::Info).ok();
|
||||
solidcraft_ui_egui::i18n::install();
|
||||
solidcraft_ui_egui::icon_svg::install();
|
||||
solidcraft_look::install_tables();
|
||||
solidcraft_ui_egui::workspace::install_tabs();
|
||||
solidcraft_ui_egui::navigation_slots::install();
|
||||
wasm_bindgen_futures::spawn_local(async {
|
||||
|
||||
@@ -44,8 +44,10 @@ const UPDATE_TIMEOUT_MS = 20000;
|
||||
const COMPLETE = "build-complete";
|
||||
/** The entry that marks a build replaced by a newer worker. */
|
||||
const RETIRED = "build-retired";
|
||||
/** A page remembered this recently may still be loading (not yet listed among the clients). */
|
||||
const PAGE_LOADING_MS = 30 * 1000;
|
||||
/** A page remembered this recently may still be loading (not yet listed among the clients). A slow
|
||||
* device can take minutes between the launch's answer and the page appearing; a live page's record is
|
||||
* kept for as long as it is listed. */
|
||||
const PAGE_LOADING_MS = 10 * 60 * 1000;
|
||||
|
||||
const url = (file) => new URL(file, self.registration.scope).href;
|
||||
const has = (name, entry) => caches.match(url(entry), { cacheName: name }).then(Boolean);
|
||||
@@ -102,10 +104,13 @@ async function started(id, build) {
|
||||
await (await caches.open(PAGES)).put(pageEntry(id), new Response(record));
|
||||
}
|
||||
|
||||
/** The build a page started; a page started before it was remembered gets this worker's. */
|
||||
/**
|
||||
* The build a page started, or null when it was not remembered. Never this worker's build instead:
|
||||
* after an update that is another build than the page's, and its files would be mixed into the page.
|
||||
*/
|
||||
async function startedBy(id) {
|
||||
const response = id ? await caches.match(pageEntry(id), { cacheName: PAGES }) : null;
|
||||
return response ? (await response.json()).build : CACHE;
|
||||
return response ? (await response.json()).build : null;
|
||||
}
|
||||
|
||||
/** The builds open pages use (pages closed since are forgotten). */
|
||||
@@ -148,6 +153,10 @@ self.addEventListener("activate", (event) => {
|
||||
}
|
||||
await sweep();
|
||||
await self.clients.claim();
|
||||
// Pages open when the worker first takes over came from the network, and get their files from it.
|
||||
for (const client of await self.clients.matchAll({ includeUncontrolled: true })) {
|
||||
if (!(await startedBy(client.id).catch(() => null))) await started(client.id, NETWORK).catch(() => {});
|
||||
}
|
||||
})(),
|
||||
);
|
||||
});
|
||||
@@ -221,7 +230,12 @@ async function launchOrKept(event) {
|
||||
|
||||
/** A page's files come from the build it started, else the network. */
|
||||
async function asset(event) {
|
||||
const build = await startedBy(event.clientId).catch(() => CACHE);
|
||||
const build = await startedBy(event.clientId).catch(() => null);
|
||||
// A page whose build is not known, or whose build's copy is gone, would get another build's files
|
||||
// (a mixed page that never starts). It fails visibly instead: reloading starts a whole build.
|
||||
if (!build || (build !== NETWORK && !(await caches.has(build)))) {
|
||||
return new Response("This page's version of the app is no longer kept. Reload the page.", { status: 503, headers: { "Content-Type": "text/plain" } });
|
||||
}
|
||||
const kept = build === NETWORK ? null : await caches.match(event.request, { cacheName: build, ignoreSearch: true });
|
||||
return kept || fetch(event.request);
|
||||
}
|
||||
|
||||
@@ -37,6 +37,8 @@ solidcraft-control = { workspace = true }
|
||||
# The D3D12 shader compiler the window starts with (#6756).
|
||||
solidcraft-gpu = { workspace = true }
|
||||
solidcraft-ui-egui = { workspace = true }
|
||||
# SolidCraft's look (icons, glyphs, built-in themes), installed at startup.
|
||||
solidcraft-look = { workspace = true }
|
||||
solidcraft-ui-text = { workspace = true }
|
||||
solidcraft-theme = { workspace = true }
|
||||
solidcraft-space-mouse = { workspace = true }
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
//! with what SolidCraft's requests mean ([`SolidCraft`]).
|
||||
|
||||
use std::net::TcpListener;
|
||||
use std::sync::mpsc::{Receiver, Sender, channel};
|
||||
use std::sync::mpsc::{Sender, channel};
|
||||
use std::sync::{Arc, OnceLock};
|
||||
|
||||
use serde_json::{Value, json};
|
||||
@@ -12,6 +12,7 @@ use solidcraft_control::{ControlRequest, auth};
|
||||
use solidcraft_engine::MAX_LINE;
|
||||
use solidcraft_engine::control_auth::APP;
|
||||
use solidcraft_engine::control_pending;
|
||||
use solidcraft_ui_egui::control_switch;
|
||||
|
||||
/// The token files this launch wrote (its control port, the agent chat's endpoint) and the
|
||||
/// token in each, removed when the app ends unless another launch has written the file since.
|
||||
@@ -85,40 +86,60 @@ pub fn remove_token_file() {
|
||||
/// The port the app's own channel listens on and its token, for removing the discovery file at exit.
|
||||
static APP_PORT: std::sync::Mutex<Option<(u16, String)>> = std::sync::Mutex::new(None);
|
||||
|
||||
pub fn start(listen_on: auth::Listen, ctx: egui::Context) -> Receiver<ControlRequest> {
|
||||
/// Open the app's control channel (at launch, or turned on in the settings): its listener, its
|
||||
/// token file and the discovery file. Stopping it removes both files again.
|
||||
pub fn start(listen_on: auth::Listen, ctx: egui::Context) -> Result<control_switch::Started, control_switch::StartError> {
|
||||
use control_switch::StartError;
|
||||
let (tx, rx) = channel::<ControlRequest>();
|
||||
// Every connection must show the token before anything runs (docs/control-protocol.md).
|
||||
match APP.env_token().or_else(server::new_token) {
|
||||
Some(token) => {
|
||||
let listener = match listen_on {
|
||||
auth::Listen::Exact(port) => TcpListener::bind(("127.0.0.1", port)),
|
||||
auth::Listen::Default => auth::bind_with_fallback(APP.default_port, auth::PORT_TRIES),
|
||||
};
|
||||
match listener {
|
||||
Ok(l) => {
|
||||
if let Some(port) = listen_on_listener(l, token.clone(), tx, ctx, false) {
|
||||
if matches!(listen_on, auth::Listen::Default) {
|
||||
solidcraft_engine::note!(
|
||||
"solidcraft: control channel on the default port 127.0.0.1:{port} (Preferences > Assistant turns it off)"
|
||||
);
|
||||
}
|
||||
// The discovery file: where `solidcraft-cli mcp` finds this app with no arguments.
|
||||
match APP.write_current_port(port) {
|
||||
Ok(_) => {
|
||||
if let Ok(mut p) = APP_PORT.lock() {
|
||||
*p = Some((port, token));
|
||||
}
|
||||
}
|
||||
Err(e) => solidcraft_engine::note!("solidcraft: could not write the control discovery file ({e})"),
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => solidcraft_engine::note!("solidcraft: control server failed to bind 127.0.0.1: {e}"),
|
||||
let Some(token) = APP.env_token().or_else(server::new_token) else {
|
||||
solidcraft_engine::note!("solidcraft: control server not started: no random token available");
|
||||
return Err(StartError::Failed("no random token available".into()));
|
||||
};
|
||||
let listener = match listen_on {
|
||||
auth::Listen::Exact(port) => TcpListener::bind(("127.0.0.1", port)),
|
||||
auth::Listen::Default => auth::bind_with_fallback(APP.default_port, auth::PORT_TRIES),
|
||||
};
|
||||
let listener = listener.map_err(|e| {
|
||||
solidcraft_engine::note!("solidcraft: control server failed to bind 127.0.0.1: {e}");
|
||||
match (listen_on, e.kind()) {
|
||||
// In use; Windows reports a port another program holds exclusively as denied.
|
||||
(auth::Listen::Exact(port), std::io::ErrorKind::AddrInUse | std::io::ErrorKind::PermissionDenied) => StartError::PortTaken(port),
|
||||
(auth::Listen::Default, std::io::ErrorKind::AddrInUse | std::io::ErrorKind::PermissionDenied) => StartError::PortTaken(APP.default_port),
|
||||
_ => StartError::Failed(e.to_string()),
|
||||
}
|
||||
})?;
|
||||
let (port, stop) =
|
||||
listen_on_listener(listener, token.clone(), tx, ctx, false).ok_or_else(|| StartError::Failed("the listener did not start".into()))?;
|
||||
if matches!(listen_on, auth::Listen::Default) {
|
||||
solidcraft_engine::note!("solidcraft: control channel on the default port 127.0.0.1:{port} (Preferences > Assistant turns it off)");
|
||||
}
|
||||
// The discovery file: where `solidcraft-cli mcp` finds this app with no arguments.
|
||||
match APP.write_current_port(port) {
|
||||
Ok(_) => {
|
||||
if let Ok(mut p) = APP_PORT.lock() {
|
||||
*p = Some((port, token.clone()));
|
||||
}
|
||||
}
|
||||
None => solidcraft_engine::note!("solidcraft: control server not started: no random token available"),
|
||||
Err(e) => solidcraft_engine::note!("solidcraft: could not write the control discovery file ({e})"),
|
||||
}
|
||||
rx
|
||||
let stop = Box::new(move || {
|
||||
stop.stop();
|
||||
if let Ok(mut p) = APP_PORT.lock()
|
||||
&& p.as_ref().is_some_and(|(held, _)| *held == port)
|
||||
{
|
||||
*p = None;
|
||||
}
|
||||
APP.remove_current_port(port, &token);
|
||||
if let Some(path) = APP.token_path(port) {
|
||||
auth::remove_token_file(&path, &token);
|
||||
if let Ok(mut files) = TOKEN_FILES.lock() {
|
||||
files.retain(|(p, _)| *p != path);
|
||||
}
|
||||
}
|
||||
solidcraft_engine::note!("solidcraft: control channel on 127.0.0.1:{port} closed");
|
||||
});
|
||||
Ok(control_switch::Started { port, requests: rx, stop })
|
||||
}
|
||||
|
||||
/// The agent chat's own endpoint for its agent's MCP server (docs/agent-chat.md): a free loopback
|
||||
@@ -137,12 +158,19 @@ pub fn listen_agent(tx: Sender<ControlRequest>, ctx: egui::Context) -> Option<u1
|
||||
return None;
|
||||
}
|
||||
};
|
||||
listen_on_listener(listener, token, tx, ctx, true)
|
||||
// The chat's endpoint lives as long as the app.
|
||||
listen_on_listener(listener, token, tx, ctx, true).map(|(port, _)| port)
|
||||
}
|
||||
|
||||
/// Serve `listener` (loopback) with `token`; the port it listens on.
|
||||
/// Serve `listener` (loopback) with `token`; the port it listens on and how to stop it.
|
||||
/// `patient`: every request may wait as long as a batch (a person decides on it).
|
||||
fn listen_on_listener(listener: TcpListener, token: String, tx: Sender<ControlRequest>, ctx: egui::Context, patient: bool) -> Option<u16> {
|
||||
fn listen_on_listener(
|
||||
listener: TcpListener,
|
||||
token: String,
|
||||
tx: Sender<ControlRequest>,
|
||||
ctx: egui::Context,
|
||||
patient: bool,
|
||||
) -> Option<(u16, server::Stop)> {
|
||||
let port = listener.local_addr().ok()?.port();
|
||||
match APP.token_path(port) {
|
||||
Some(path) => match APP.write_token_file(&path, &token) {
|
||||
@@ -164,8 +192,8 @@ fn listen_on_listener(listener: TcpListener, token: String, tx: Sender<ControlRe
|
||||
)
|
||||
}
|
||||
}
|
||||
match hub(ctx).listen(listener, token, tx, patient) {
|
||||
Ok(()) => Some(port),
|
||||
match hub(ctx).listen_stoppable(listener, token, tx, patient) {
|
||||
Ok(stop) => Some((port, stop)),
|
||||
Err(e) => {
|
||||
solidcraft_engine::note!("solidcraft: control server not started: {e}");
|
||||
None
|
||||
|
||||
+160
-21
@@ -87,6 +87,8 @@ struct App {
|
||||
solve: SolveApp,
|
||||
/// The settings folder whose start marker the first frame clears (`startup::started`).
|
||||
starting: Option<std::path::PathBuf>,
|
||||
/// A newly selected API is confirmed only once the first frame has been presented.
|
||||
backend_attempt: Option<(std::path::PathBuf, startup::BackendAttempt)>,
|
||||
/// Frames begun; the second one means the first was drawn (startup is over).
|
||||
frames: u32,
|
||||
/// Started over the control channel: the window doesn't ask for the foreground.
|
||||
@@ -215,6 +217,12 @@ impl eframe::App for App {
|
||||
solidcraft_ui_egui::ai_connect::begin(&mut self.solve);
|
||||
solidcraft_ui_egui::agent_chat::begin(&mut self.solve);
|
||||
}
|
||||
if let Some((path, attempt)) = self.backend_attempt.take()
|
||||
&& let Err(reason) = startup::confirm_backend_start(&path, &attempt)
|
||||
{
|
||||
log::warn!("graphics: could not confirm the startup choice: {reason}");
|
||||
self.solve.set_status(reason, true);
|
||||
}
|
||||
if let Some(dir) = self.starting.take() {
|
||||
startup::started(&dir);
|
||||
}
|
||||
@@ -341,10 +349,17 @@ impl Drop for App {
|
||||
// never return (#9044).
|
||||
device_lost::end();
|
||||
}
|
||||
// An update asked to restart into the new version or to run its installer.
|
||||
// Restart only after eframe has flushed settings. Graphics restarts also reopen
|
||||
// the saved designs collected by the normal quit flow.
|
||||
let graphics_restart = solidcraft_ui_egui::update::take_graphics_restart(&mut self.solve);
|
||||
if let Some((program, args)) = solidcraft_ui_egui::update::take_launch(&mut self.solve) {
|
||||
let mut command = std::process::Command::new(&program);
|
||||
command.args(&args);
|
||||
let mut command = if graphics_restart {
|
||||
graphics_restart_command(&program, &args, &self.solve.preferences.open_designs)
|
||||
} else {
|
||||
let mut command = std::process::Command::new(&program);
|
||||
command.args(&args);
|
||||
command
|
||||
};
|
||||
#[cfg(windows)]
|
||||
{
|
||||
use std::os::windows::process::CommandExt;
|
||||
@@ -360,6 +375,62 @@ impl Drop for App {
|
||||
}
|
||||
}
|
||||
|
||||
/// A UI restart applies the saved API instead of inheriting this session's recovery
|
||||
/// overrides. Explicit developer overrides remain authoritative.
|
||||
fn graphics_restart_command(program: &std::path::Path, args: &[String], designs: &[String]) -> std::process::Command {
|
||||
let mut command = std::process::Command::new(program);
|
||||
command.args(args).args(designs);
|
||||
for variable in [
|
||||
startup::RETRY_BACKEND_ENV,
|
||||
startup::FALLBACK_NOTE_ENV,
|
||||
startup::RENDERER_ENV,
|
||||
startup::SAFE_MODE_ENV,
|
||||
device_lost::LOST_ENV,
|
||||
device_lost::REASON_ENV,
|
||||
] {
|
||||
command.env_remove(variable);
|
||||
}
|
||||
command
|
||||
}
|
||||
|
||||
/// Re-enter an AppImage through its outer executable only when this process actually lives
|
||||
/// in that image's mount. An inherited APPIMAGE from another application is not our launcher.
|
||||
fn graphics_restart_program(
|
||||
exe: Option<&std::path::Path>,
|
||||
appimage: Option<&std::ffi::OsStr>,
|
||||
appdir: Option<&std::ffi::OsStr>,
|
||||
is_file: impl Fn(&std::path::Path) -> bool,
|
||||
) -> Option<std::path::PathBuf> {
|
||||
let exe = exe?;
|
||||
if let (Some(image), Some(directory)) = (appimage, appdir) {
|
||||
let image = std::path::Path::new(image);
|
||||
let directory = std::path::Path::new(directory);
|
||||
if image.is_absolute() && directory.is_absolute() && exe.starts_with(directory) && is_file(image) {
|
||||
return Some(image.to_path_buf());
|
||||
}
|
||||
}
|
||||
Some(exe.to_path_buf())
|
||||
}
|
||||
|
||||
/// Keep launch-scoped settings through a UI restart. Safe mode and the sample are one-shot;
|
||||
/// original file arguments are replaced by the current saved tabs at shutdown.
|
||||
fn graphics_restart_args(args: impl IntoIterator<Item = String>) -> Vec<String> {
|
||||
let mut retained = Vec::new();
|
||||
let mut args = args.into_iter();
|
||||
while let Some(argument) = args.next() {
|
||||
match argument.as_str() {
|
||||
"--control" | "--theme-file" | "--max-file-size" => {
|
||||
if let Some(value) = args.next() {
|
||||
retained.extend([argument, value]);
|
||||
}
|
||||
}
|
||||
value if value.starts_with("--max-file-size=") => retained.push(argument),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
retained
|
||||
}
|
||||
|
||||
/// The window's graphics device, watched for its loss.
|
||||
struct LostWatch {
|
||||
lost: eframe::egui_wgpu::DeviceLost,
|
||||
@@ -569,6 +640,15 @@ fn services(cc: &eframe::CreationContext<'_>, folder: &DialogFolder) -> Services
|
||||
Box::pin(async move { folder.answer(future.await) })
|
||||
})),
|
||||
graphics_adapters: Vec::new(),
|
||||
graphics_backend: None,
|
||||
graphics_backend_override: std::env::var(startup::WGPU_BACKEND_ENV).is_ok_and(|v| !v.trim().is_empty()),
|
||||
graphics_restart: graphics_restart_program(
|
||||
std::env::current_exe().ok().as_deref(),
|
||||
std::env::var_os("APPIMAGE").as_deref(),
|
||||
std::env::var_os("APPDIR").as_deref(),
|
||||
std::path::Path::is_file,
|
||||
)
|
||||
.map(|program| (program, graphics_restart_args(std::env::args().skip(1)))),
|
||||
graphics_path: graphics_path().map(|p| p.to_string_lossy().to_string()),
|
||||
window_system: window_system_now(),
|
||||
// Linux: the desktop's dark or light setting, which the window is not told on every
|
||||
@@ -832,6 +912,12 @@ fn restore_preferences(app: &mut SolveApp, stored_ui: Option<&str>, saved_graphi
|
||||
|
||||
/// Restore startup choices after loading the separately saved UI preferences.
|
||||
fn restore_graphics_preferences(app: &mut SolveApp, saved: Option<&serde_json::Value>) {
|
||||
// Preserve legacy comma lists until the user explicitly selects a different API.
|
||||
app.preferences.graphics_backend = saved
|
||||
.and_then(|v| v.get("backend").and_then(serde_json::Value::as_str))
|
||||
.filter(|choice| !choice.trim().is_empty())
|
||||
.unwrap_or("auto")
|
||||
.to_string();
|
||||
app.preferences.graphics_adapter = saved.and_then(|v| v.get("adapter").and_then(serde_json::Value::as_str)).unwrap_or_default().to_string();
|
||||
// graphics.json chooses the window before app.ron is loaded. Reflect that saved choice,
|
||||
// not the current session's window system (which an environment override may change).
|
||||
@@ -843,11 +929,6 @@ fn restore_graphics_preferences(app: &mut SolveApp, saved: Option<&serde_json::V
|
||||
.to_string();
|
||||
}
|
||||
|
||||
/// The graphics backend preference (`graphics.json`'s `backend`: `auto`, `dx12`, `vulkan`, `gl`).
|
||||
fn backend_preference() -> Option<String> {
|
||||
graphics().and_then(|v| v.get("backend").and_then(serde_json::Value::as_str).map(str::to_string))
|
||||
}
|
||||
|
||||
/// The viewport scene's sample count, by the rule the web app shares
|
||||
/// (`solidcraft_ui_egui::gpu::scene_samples`).
|
||||
fn scene_samples(backend: eframe::wgpu::Backend, samples: u32, supported: &[u32]) -> u32 {
|
||||
@@ -934,7 +1015,7 @@ fn main() -> eframe::Result {
|
||||
objc2_foundation::NSProcessInfo::processInfo().setProcessName(objc2_foundation::ns_string!("SolidCraft"));
|
||||
mark("main");
|
||||
solidcraft_ui_egui::i18n::install();
|
||||
solidcraft_ui_egui::icon_svg::install();
|
||||
solidcraft_look::install_tables();
|
||||
solidcraft_ui_egui::workspace::install_tabs();
|
||||
solidcraft_ui_egui::navigation_slots::install();
|
||||
// On OCLP-patched Macs, wgpu picks a Metal Shading Language standard that the system's
|
||||
@@ -1016,7 +1097,27 @@ fn main() -> eframe::Result {
|
||||
safe_mode = true;
|
||||
notes.push(format!("The last {failed_starts} launches stopped before the window opened, so this one is in safe mode."));
|
||||
}
|
||||
let cpu_renderer = safe_mode || startup::cpu_renderer_env(std::env::var(startup::RENDERER_ENV).ok().as_deref());
|
||||
let mut cpu_renderer = safe_mode || startup::cpu_renderer_env(std::env::var(startup::RENDERER_ENV).ok().as_deref());
|
||||
// Persist the one-start guard before any adapter, device or depth-format probe.
|
||||
// Recovery launches and explicit overrides must not consume a pending UI choice.
|
||||
let backend_override = std::env::var(startup::WGPU_BACKEND_ENV).is_ok_and(|v| !v.trim().is_empty());
|
||||
let retry_backend = std::env::var(startup::RETRY_BACKEND_ENV).ok();
|
||||
let backend_path = settings.as_ref().map(|dir| dir.join("graphics.json"));
|
||||
let backend_launch = match backend_path
|
||||
.as_ref()
|
||||
.map(|path| startup::prepare_backend_start(path, !cpu_renderer && !backend_override && retry_backend.is_none()))
|
||||
.transpose()
|
||||
{
|
||||
Ok(launch) => launch.unwrap_or_default(),
|
||||
Err(reason) => {
|
||||
// A choice that could not be guarded must not load the requested driver.
|
||||
cpu_renderer = true;
|
||||
notes.push(reason);
|
||||
startup::BackendLaunch::default()
|
||||
}
|
||||
};
|
||||
let backend_attempt = backend_path.zip(backend_launch.attempt);
|
||||
let backend_note = backend_launch.note;
|
||||
// The launch before this one closed because its graphics device was lost (`App::watch_device`).
|
||||
let after_loss = device_lost::recent(std::env::var(device_lost::LOST_ENV).ok().as_deref(), device_lost::now_secs());
|
||||
if after_loss {
|
||||
@@ -1029,14 +1130,14 @@ fn main() -> eframe::Result {
|
||||
if safe_mode {
|
||||
notes.push("Safe mode: default settings (yours are kept for the next normal start), no recovery offer, software rendering.".into());
|
||||
}
|
||||
let fallback_note = std::env::var(startup::FALLBACK_NOTE_ENV).ok().map(|s| s.chars().take(4096).collect::<String>());
|
||||
let fallback_note = std::env::var(startup::FALLBACK_NOTE_ENV).ok().map(|s| s.chars().take(4096).collect::<String>()).or(backend_note);
|
||||
if let Some(note) = &fallback_note {
|
||||
log::warn!("{note}");
|
||||
solidcraft_engine::note!("SolidCraft: {note}");
|
||||
notes.push(note.clone());
|
||||
}
|
||||
let saved_samples = if safe_mode { None } else { msaa() };
|
||||
let wgpu_options = wgpu_options(cpu_renderer, if safe_mode { None } else { backend_preference() }.as_deref());
|
||||
let wgpu_options = wgpu_options(cpu_renderer, if safe_mode { None } else { backend_launch.backend.as_deref() });
|
||||
let depth_bits = if !safe_mode && startup::float_depth_everywhere(&wgpu_options) { FLOAT_DEPTH_BITS } else { DEPTH_BITS };
|
||||
// Crashes leave a report in the crash folder (solidcraft_engine::crash, docs/crash-reports.md).
|
||||
let crashed = solidcraft_engine::crash::default_dir()
|
||||
@@ -1117,6 +1218,7 @@ fn main() -> eframe::Result {
|
||||
let created = std::sync::Arc::new(std::sync::atomic::AtomicBool::new(false));
|
||||
let created_in_app = created.clone();
|
||||
let starting = settings.clone();
|
||||
let attempt_in_app = backend_attempt.clone();
|
||||
// A panic on the window's thread ends the app without `on_exit`; this disconnects from the
|
||||
// 3D mouse driver then too.
|
||||
#[cfg(target_os = "macos")]
|
||||
@@ -1181,6 +1283,13 @@ fn main() -> eframe::Result {
|
||||
})
|
||||
.collect();
|
||||
let info = rs.adapter.get_info();
|
||||
app.services.graphics_backend = match info.backend {
|
||||
eframe::wgpu::Backend::Vulkan => Some("vulkan"),
|
||||
eframe::wgpu::Backend::Dx12 => Some("dx12"),
|
||||
eframe::wgpu::Backend::Gl => Some("gl"),
|
||||
eframe::wgpu::Backend::Metal => Some("metal"),
|
||||
_ => None,
|
||||
};
|
||||
if !app.preferences.graphics_adapter.is_empty() && !info.name.eq_ignore_ascii_case(app.preferences.graphics_adapter.as_str()) {
|
||||
solidcraft_engine::note!(
|
||||
"SolidCraft graphics: preferred adapter {:?} was not used; using {:?} instead",
|
||||
@@ -1211,12 +1320,11 @@ fn main() -> eframe::Result {
|
||||
));
|
||||
}
|
||||
mark("viewport pipelines");
|
||||
// `--control`/the environment name a port; otherwise the preference (on by default)
|
||||
// opens the default one (docs/control-protocol.md).
|
||||
if let Some(listen_on) = solidcraft_control::auth::plan(control_port, app.preferences.agent_control) {
|
||||
let rx = control_server::start(listen_on, cc.egui_ctx.clone());
|
||||
app = app.with_control(rx);
|
||||
}
|
||||
// `--control`/the environment name a port for this run; otherwise the preference (off
|
||||
// by default) opens its port, and turning it off or on later takes effect at once
|
||||
// (docs/control-protocol.md).
|
||||
let ctx = cc.egui_ctx.clone();
|
||||
solidcraft_ui_egui::control_switch::launch(&mut app, Box::new(move |listen| control_server::start(listen, ctx.clone())), control_port);
|
||||
// The agent chat's MCP bridge reaches the app through an endpoint of its own, started
|
||||
// on a free port the first time the chat connects (docs/agent-chat.md).
|
||||
let ctx = cc.egui_ctx.clone();
|
||||
@@ -1313,6 +1421,7 @@ fn main() -> eframe::Result {
|
||||
prefs_writer: PrefsWriter::read(app.prefs()),
|
||||
solve: app,
|
||||
starting,
|
||||
backend_attempt: attempt_in_app,
|
||||
frames: 0,
|
||||
take_focus_unwanted: control_port.is_some(),
|
||||
come_forward: come_forward::ComeForward::default(),
|
||||
@@ -1328,7 +1437,9 @@ fn main() -> eframe::Result {
|
||||
);
|
||||
control_server::remove_token_file();
|
||||
match result {
|
||||
Err(e) if !created.load(std::sync::atomic::Ordering::SeqCst) => no_window(e, cpu_renderer, started, settings.as_deref()),
|
||||
Err(e) if !created.load(std::sync::atomic::Ordering::SeqCst) => {
|
||||
no_window(e, cpu_renderer, started, settings.as_deref(), backend_attempt.as_ref())
|
||||
}
|
||||
r => r,
|
||||
}
|
||||
}
|
||||
@@ -1347,7 +1458,10 @@ fn startup_step(step: &'static str, detail: &str) {
|
||||
/// backends come from `startup::choose_backends` (on Windows D3D12 first, and only the backend
|
||||
/// in use is started); `preference` is `graphics.json`'s `backend`.
|
||||
fn wgpu_options(cpu: bool, preference: Option<&str>) -> eframe::egui_wgpu::WgpuConfiguration {
|
||||
let mut options = eframe::egui_wgpu::WgpuConfiguration::default();
|
||||
// One frame in flight, as eframe's own default (`NativeOptions::default`): egui-wgpu's
|
||||
// `WgpuConfiguration::default()` is HIGH_THROUGHPUT (two frames queued), which added a frame
|
||||
// of input-to-display latency to every pan, orbit and drag.
|
||||
let mut options = eframe::egui_wgpu::WgpuConfiguration::default().with_surface_config(eframe::egui_wgpu::SurfaceConfig::LOW_LATENCY);
|
||||
if let eframe::egui_wgpu::WgpuSetup::CreateNew(setup) = &mut options.wgpu_setup {
|
||||
let env_set = std::env::var(startup::WGPU_BACKEND_ENV).is_ok_and(|v| !v.trim().is_empty());
|
||||
// A retry applies only to this launch. WGPU_BACKEND always has priority.
|
||||
@@ -1378,7 +1492,13 @@ fn wgpu_options(cpu: bool, preference: Option<&str>) -> eframe::egui_wgpu::WgpuC
|
||||
|
||||
/// A failed renderer returns here before app creation. A fresh process avoids reusing winit's
|
||||
/// event loop or a failed device; each retry advances through the APIs, then software once.
|
||||
fn no_window(error: eframe::Error, tried_cpu: bool, failed: eframe::wgpu::Backends, settings: Option<&std::path::Path>) -> eframe::Result {
|
||||
fn no_window(
|
||||
error: eframe::Error,
|
||||
tried_cpu: bool,
|
||||
failed: eframe::wgpu::Backends,
|
||||
settings: Option<&std::path::Path>,
|
||||
backend_attempt: Option<&(std::path::PathBuf, startup::BackendAttempt)>,
|
||||
) -> eframe::Result {
|
||||
log::error!("the window could not open: {error}");
|
||||
solidcraft_engine::note!("SolidCraft: the window could not open: {error}");
|
||||
// This failure was handled, so neither the marker nor the journal should call it a crash.
|
||||
@@ -1386,6 +1506,25 @@ fn no_window(error: eframe::Error, tried_cpu: bool, failed: eframe::wgpu::Backen
|
||||
startup::started(dir);
|
||||
}
|
||||
solidcraft_engine::crash::end_session();
|
||||
// A rejected UI choice goes back to its previous API before ordinary fallback.
|
||||
// This is separate from startup::started: a handled failure is not confirmation.
|
||||
if let Some((path, attempt)) = backend_attempt {
|
||||
match startup::rollback_backend_start(path, attempt) {
|
||||
Ok(()) => {
|
||||
if let Ok(exe) = std::env::current_exe() {
|
||||
let note = startup::backend_reverted_note(&attempt.requested, &attempt.previous);
|
||||
let mut command = std::process::Command::new(exe);
|
||||
command.args(std::env::args_os().skip(1)).env_remove(startup::RETRY_BACKEND_ENV).env(startup::FALLBACK_NOTE_ENV, note);
|
||||
match command.status() {
|
||||
Ok(status) if status.success() => return Ok(()),
|
||||
Ok(_) => return Err(error),
|
||||
Err(reason) => log::error!("could not restart with the previous graphics API: {reason}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(reason) => log::warn!("could not restore the previous graphics API: {reason}"),
|
||||
}
|
||||
}
|
||||
let explicit = std::env::var(startup::WGPU_BACKEND_ENV).is_ok_and(|v| !v.trim().is_empty());
|
||||
if let Some(next) = startup::fallback_backend(cfg!(target_os = "windows"), explicit, tried_cpu, failed)
|
||||
&& let Ok(exe) = std::env::current_exe()
|
||||
|
||||
@@ -2592,11 +2592,15 @@ mod tests {
|
||||
let reader = Running::start(driver, fake.clone());
|
||||
reader.reads("spacenavd");
|
||||
// Still not readable, over two waits: the daemon read goes on, one connection, a few probes.
|
||||
let slept = std::time::Instant::now();
|
||||
std::thread::sleep(Duration::from_millis(700));
|
||||
let waited = slept.elapsed();
|
||||
assert_eq!(reader.key().as_deref(), Some("spacenavd"), "{driver:?}");
|
||||
assert_eq!(fake.world().connects, 1, "{driver:?}: the daemon read was not restarted for a device that still cannot be read");
|
||||
let opens = fake.world().opens;
|
||||
assert!(opens <= 4, "{driver:?}: {opens} tries in 700 ms with a 300 ms wait");
|
||||
// A loaded machine can sleep far past 700 ms: bound the tries by the time that really passed.
|
||||
let allowed = 4 + (waited.as_millis().saturating_sub(700) / 300) as u32;
|
||||
assert!(opens <= allowed, "{driver:?}: {opens} tries in {waited:?} with a 300 ms wait");
|
||||
// The permission is fixed.
|
||||
fake.world().openable = true;
|
||||
reader.reads(&Source::Hid(Some(IDS)).key());
|
||||
|
||||
@@ -114,6 +114,158 @@ pub fn started(dir: &Path) {
|
||||
let _ = std::fs::remove_file(dir.join(MARKER));
|
||||
}
|
||||
|
||||
/// A saved backend change that this launch is trying. Keep this value until the first
|
||||
/// frame is presented, so only this launch's matching attempt can be confirmed or reverted.
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct BackendAttempt {
|
||||
pub requested: String,
|
||||
pub previous: String,
|
||||
}
|
||||
|
||||
/// The backend to use before creating any graphics device, with any pending recovery notice.
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq)]
|
||||
pub struct BackendLaunch {
|
||||
pub backend: Option<String>,
|
||||
pub attempt: Option<BackendAttempt>,
|
||||
pub note: Option<String>,
|
||||
}
|
||||
|
||||
type GraphicsSettings = serde_json::Map<String, serde_json::Value>;
|
||||
const BACKEND_TRIAL: &str = "backend_trial";
|
||||
const MAX_BACKEND_PREFERENCE_BYTES: usize = 256;
|
||||
|
||||
/// Read only object-shaped settings. A missing or empty file means defaults; other failures
|
||||
/// are reported so the caller can use its safe renderer without overwriting unreadable data.
|
||||
fn read_backend_settings(path: &Path) -> Result<GraphicsSettings, String> {
|
||||
let text = match std::fs::read_to_string(path) {
|
||||
Ok(text) => text,
|
||||
Err(error) if error.kind() == std::io::ErrorKind::NotFound => return Ok(GraphicsSettings::new()),
|
||||
Err(error) => return Err(format!("could not read graphics settings: {error}")),
|
||||
};
|
||||
if text.trim().is_empty() {
|
||||
return Ok(GraphicsSettings::new());
|
||||
}
|
||||
serde_json::from_str(&text).map_err(|error| format!("could not read graphics settings: {error}"))
|
||||
}
|
||||
|
||||
/// The attempt marker and backend are written together: a crash must leave a whole old or
|
||||
/// new record, never a selected API whose recovery data was only partly written.
|
||||
fn write_backend_settings(path: &Path, graphics: &GraphicsSettings) -> Result<(), String> {
|
||||
let bytes = serde_json::to_vec(graphics).map_err(|error| format!("could not encode graphics settings: {error}"))?;
|
||||
solidcraft_engine::io::safe_write::write_atomic(path, &bytes, false).map_err(|error| format!("could not save graphics settings: {error}"))
|
||||
}
|
||||
|
||||
/// UI choices are single API names. The previous value remains verbatim, including legacy
|
||||
/// comma lists and blanks, because startup already knows how to interpret those preferences.
|
||||
fn backend_trial(graphics: &GraphicsSettings) -> Option<(BackendAttempt, bool)> {
|
||||
let trial = graphics.get(BACKEND_TRIAL)?.as_object()?;
|
||||
let requested = trial.get("requested")?.as_str()?;
|
||||
if !matches!(requested, "auto" | "dx12" | "vulkan" | "gl" | "metal") {
|
||||
return None;
|
||||
}
|
||||
let previous = trial.get("previous")?.as_str()?;
|
||||
if previous.len() > MAX_BACKEND_PREFERENCE_BYTES {
|
||||
return None;
|
||||
}
|
||||
let started = trial.get("started")?.as_bool()?;
|
||||
Some((BackendAttempt { requested: requested.into(), previous: previous.into() }, started))
|
||||
}
|
||||
|
||||
/// Describe a restored choice using the same catalog as the Graphics preferences page.
|
||||
pub(super) fn backend_reverted_note(requested: &str, previous: &str) -> String {
|
||||
let requested = solidcraft_ui_egui::prefs::graphics_backend_label(requested);
|
||||
let previous = solidcraft_ui_egui::prefs::graphics_backend_label(previous);
|
||||
solidcraft_ui_text::format("prefs.graphics_api_start_reverted", &[("requested", &requested), ("previous", &previous)])
|
||||
}
|
||||
|
||||
/// Prepare a UI-selected API before any adapter is opened. Safe mode, an explicit environment
|
||||
/// override and process-local fallback launches pass `false` and leave the attempt untouched.
|
||||
/// An interrupted attempt restores its previous API. A new attempt is returned only after its
|
||||
/// started marker reaches disk; any I/O error must make the caller avoid the requested API.
|
||||
pub fn prepare_backend_start(path: &Path, allow_trial: bool) -> Result<BackendLaunch, String> {
|
||||
prepare_backend_launch(read_backend_settings(path)?, allow_trial, |graphics| write_backend_settings(path, graphics))
|
||||
}
|
||||
|
||||
/// Separate the state transition from persistence so a refused marker write is testable
|
||||
/// without depending on the test user's filesystem permissions.
|
||||
fn prepare_backend_launch(
|
||||
mut graphics: GraphicsSettings,
|
||||
allow_trial: bool,
|
||||
save: impl FnOnce(&GraphicsSettings) -> Result<(), String>,
|
||||
) -> Result<BackendLaunch, String> {
|
||||
let backend = graphics.get("backend").and_then(serde_json::Value::as_str).map(str::to_string);
|
||||
let mut launch = BackendLaunch { backend, ..Default::default() };
|
||||
if !allow_trial || !graphics.contains_key(BACKEND_TRIAL) {
|
||||
return Ok(launch);
|
||||
}
|
||||
let parsed = backend_trial(&graphics);
|
||||
let requested = graphics.get(BACKEND_TRIAL).and_then(|trial| trial.get("requested")).and_then(serde_json::Value::as_str);
|
||||
if requested.is_some() && requested != launch.backend.as_deref() {
|
||||
// Another edit replaced the selected API; stale recovery data cannot undo that edit.
|
||||
graphics.remove(BACKEND_TRIAL);
|
||||
} else if let Some((attempt, started)) = parsed {
|
||||
if attempt.requested == attempt.previous {
|
||||
graphics.remove(BACKEND_TRIAL);
|
||||
} else if started {
|
||||
graphics.insert("backend".into(), serde_json::Value::String(attempt.previous.clone()));
|
||||
graphics.remove(BACKEND_TRIAL);
|
||||
launch.backend = Some(attempt.previous.clone());
|
||||
launch.note = Some(backend_reverted_note(&attempt.requested, &attempt.previous));
|
||||
} else {
|
||||
let trial = graphics
|
||||
.get_mut(BACKEND_TRIAL)
|
||||
.and_then(serde_json::Value::as_object_mut)
|
||||
.ok_or_else(|| "graphics backend attempt changed before it could start".to_string())?;
|
||||
trial.insert("started".into(), serde_json::Value::Bool(true));
|
||||
launch.attempt = Some(attempt);
|
||||
}
|
||||
} else {
|
||||
// A damaged guard must not turn a protected API into an unguarded attempt. Prefer its
|
||||
// intact previous value; otherwise use Automatic, preserving the other graphics keys.
|
||||
let previous = graphics
|
||||
.get(BACKEND_TRIAL)
|
||||
.and_then(|trial| trial.get("previous"))
|
||||
.and_then(serde_json::Value::as_str)
|
||||
.filter(|value| value.len() <= MAX_BACKEND_PREFERENCE_BYTES)
|
||||
.unwrap_or("auto")
|
||||
.to_string();
|
||||
launch.note = Some(backend_reverted_note(launch.backend.as_deref().unwrap_or("auto"), &previous));
|
||||
graphics.insert("backend".into(), serde_json::Value::String(previous.clone()));
|
||||
graphics.remove(BACKEND_TRIAL);
|
||||
launch.backend = Some(previous);
|
||||
}
|
||||
save(&graphics)?;
|
||||
Ok(launch)
|
||||
}
|
||||
|
||||
/// Only a matching, started attempt still owning the saved backend may change recovery state.
|
||||
/// A newer preference edit is left alone, including a newly pending attempt at the same API.
|
||||
fn finish_backend_start(path: &Path, attempt: &BackendAttempt, revert: bool) -> Result<(), String> {
|
||||
let mut graphics = read_backend_settings(path)?;
|
||||
let matches = backend_trial(&graphics).is_some_and(|(saved, started)| started && saved == *attempt)
|
||||
&& graphics.get("backend").and_then(serde_json::Value::as_str) == Some(attempt.requested.as_str());
|
||||
if !matches {
|
||||
return Ok(());
|
||||
}
|
||||
graphics.remove(BACKEND_TRIAL);
|
||||
if revert {
|
||||
graphics.insert("backend".into(), serde_json::Value::String(attempt.previous.clone()));
|
||||
}
|
||||
write_backend_settings(path, &graphics)
|
||||
}
|
||||
|
||||
/// Keep a backend only after the window has presented its first frame. Handled startup
|
||||
/// failures must call `rollback_backend_start` instead, even if the ordinary crash marker clears.
|
||||
pub fn confirm_backend_start(path: &Path, attempt: &BackendAttempt) -> Result<(), String> {
|
||||
finish_backend_start(path, attempt, false)
|
||||
}
|
||||
|
||||
/// A handled window-start failure restores the previous backend before the host retries.
|
||||
/// Reading fresh settings and matching the attempt avoids erasing a later preference edit.
|
||||
pub fn rollback_backend_start(path: &Path, attempt: &BackendAttempt) -> Result<(), String> {
|
||||
finish_backend_start(path, attempt, true)
|
||||
}
|
||||
|
||||
/// The software adapter among `adapters` (WARP on Windows, lavapipe or llvmpipe elsewhere), else
|
||||
/// the first one that can draw to `surface`.
|
||||
pub fn pick_cpu_adapter(adapters: &[eframe::wgpu::Adapter], surface: Option<&eframe::wgpu::Surface<'_>>) -> Result<eframe::wgpu::Adapter, String> {
|
||||
@@ -486,6 +638,284 @@ mod tests {
|
||||
assert!(settings_directory(Some(file.as_os_str()), Some(default)).is_err());
|
||||
}
|
||||
|
||||
// These restart contracts apply to Windows and macOS as well as Linux.
|
||||
#[test]
|
||||
fn graphics_restart_applies_saved_choices_and_reopens_saved_designs() {
|
||||
use std::ffi::OsStr;
|
||||
let program = std::env::current_exe().unwrap();
|
||||
let designs = vec!["/saved/first design.sc".to_string(), "/saved/second.sc".to_string()];
|
||||
let command = crate::graphics_restart_command(&program, &[], &designs);
|
||||
assert_eq!(command.get_program(), program.as_os_str());
|
||||
assert_eq!(command.get_args().collect::<Vec<_>>(), designs.iter().map(OsStr::new).collect::<Vec<_>>());
|
||||
let changes: std::collections::BTreeMap<_, _> = command.get_envs().collect();
|
||||
for variable in [
|
||||
crate::startup::RETRY_BACKEND_ENV,
|
||||
crate::startup::FALLBACK_NOTE_ENV,
|
||||
crate::startup::RENDERER_ENV,
|
||||
crate::startup::SAFE_MODE_ENV,
|
||||
crate::device_lost::LOST_ENV,
|
||||
crate::device_lost::REASON_ENV,
|
||||
] {
|
||||
assert_eq!(changes.get(OsStr::new(variable)), Some(&None), "{variable}");
|
||||
}
|
||||
assert!(!changes.contains_key(OsStr::new(crate::startup::WGPU_BACKEND_ENV)));
|
||||
assert!(!changes.contains_key(OsStr::new("SOLIDCRAFT_SETTINGS_DIR")));
|
||||
assert!(!changes.contains_key(OsStr::new("WGPU_ADAPTER_NAME")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn graphics_restart_uses_an_appimage_only_from_its_own_existing_mount() {
|
||||
use crate::graphics_restart_program;
|
||||
use std::ffi::OsStr;
|
||||
let root = std::env::temp_dir().join("solidcraft-graphics-restart-fixture");
|
||||
let appdir = root.join("mount");
|
||||
let mounted = appdir.join("usr").join("bin").join("solidcraft");
|
||||
let image = root.join("SolidCraft.AppImage");
|
||||
let outside = root.join("source").join("solidcraft");
|
||||
let looks_similar = root.join("mount-other").join("solidcraft");
|
||||
let exists = |path: &std::path::Path| path == image;
|
||||
assert_eq!(graphics_restart_program(Some(&mounted), Some(image.as_os_str()), Some(appdir.as_os_str()), exists), Some(image.clone()));
|
||||
for executable in [&outside, &looks_similar] {
|
||||
assert_eq!(
|
||||
graphics_restart_program(Some(executable), Some(image.as_os_str()), Some(appdir.as_os_str()), exists),
|
||||
Some(executable.to_path_buf()),
|
||||
"a launcher inherited from another process is ignored"
|
||||
);
|
||||
}
|
||||
for (appimage, directory) in [
|
||||
(None, Some(appdir.as_os_str())),
|
||||
(Some(image.as_os_str()), None),
|
||||
(Some(OsStr::new("")), Some(appdir.as_os_str())),
|
||||
(Some(image.as_os_str()), Some(OsStr::new(""))),
|
||||
(Some(OsStr::new("relative.AppImage")), Some(appdir.as_os_str())),
|
||||
] {
|
||||
assert_eq!(graphics_restart_program(Some(&mounted), appimage, directory, exists), Some(mounted.clone()));
|
||||
}
|
||||
assert_eq!(
|
||||
graphics_restart_program(Some(&mounted), Some(image.as_os_str()), Some(appdir.as_os_str()), |_| false),
|
||||
Some(mounted.clone()),
|
||||
"a missing outer image cannot replace the running executable"
|
||||
);
|
||||
assert_eq!(graphics_restart_program(None, Some(image.as_os_str()), Some(appdir.as_os_str()), exists), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn graphics_restart_keeps_launch_options_and_uses_the_current_saved_tabs() {
|
||||
let original = [
|
||||
"--safe-mode",
|
||||
"--control",
|
||||
"7878",
|
||||
"original design.sc",
|
||||
"--theme-file",
|
||||
"a theme.json",
|
||||
"--sample",
|
||||
"--max-file-size",
|
||||
"2GB",
|
||||
"other-original.sc",
|
||||
"--max-file-size=3GB",
|
||||
];
|
||||
let args = crate::graphics_restart_args(original.into_iter().map(str::to_string));
|
||||
assert_eq!(args, ["--control", "7878", "--theme-file", "a theme.json", "--max-file-size", "2GB", "--max-file-size=3GB"]);
|
||||
let program = std::env::current_exe().unwrap();
|
||||
let designs = ["current saved.sc".to_string()];
|
||||
let command = crate::graphics_restart_command(&program, &args, &designs);
|
||||
assert_eq!(
|
||||
command.get_args().map(|value| value.to_string_lossy().into_owned()).collect::<Vec<_>>(),
|
||||
["--control", "7878", "--theme-file", "a theme.json", "--max-file-size", "2GB", "--max-file-size=3GB", "current saved.sc"]
|
||||
);
|
||||
for missing_value in ["--control", "--theme-file", "--max-file-size"] {
|
||||
assert!(crate::graphics_restart_args([missing_value.to_string()]).is_empty());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn startup_graphics_api_is_authoritative_over_stale_ui_preferences() {
|
||||
use serde_json::json;
|
||||
for choice in ["auto", "vulkan", "dx12", "metal", "gl", "dx12,vulkan"] {
|
||||
for safe in [false, true] {
|
||||
let mut app = crate::SolveApp::new(crate::Session::default(), crate::Services::default());
|
||||
let stored = json!({"preferences":{"graphics_backend":"gl"}}).to_string();
|
||||
let saved = json!({"backend":choice});
|
||||
crate::restore_preferences(&mut app, Some(&stored), Some(&saved), safe);
|
||||
assert_eq!(app.preferences.graphics_backend, choice);
|
||||
}
|
||||
}
|
||||
let mut app = crate::SolveApp::new(crate::Session::default(), crate::Services::default());
|
||||
app.preferences.graphics_backend = "vulkan".into();
|
||||
crate::restore_graphics_preferences(&mut app, None);
|
||||
assert_eq!(app.preferences.graphics_backend, "auto");
|
||||
}
|
||||
fn backend_settings(path: &Path) -> serde_json::Value {
|
||||
serde_json::from_str(&std::fs::read_to_string(path).unwrap()).unwrap()
|
||||
}
|
||||
|
||||
fn pending_backend(previous: &str) -> serde_json::Value {
|
||||
serde_json::json!({
|
||||
"backend": "vulkan",
|
||||
"backend_trial": {"requested": "vulkan", "previous": previous, "started": false},
|
||||
"msaa": 8,
|
||||
"adapter": "Saved GPU",
|
||||
"window_system": "x11",
|
||||
"future_setting": {"enabled": true}
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn backend_start_marks_the_attempt_before_selection_and_keeps_it_after_a_presented_frame() {
|
||||
let dir = scratch("backend-confirm");
|
||||
let path = dir.join("graphics.json");
|
||||
let original = pending_backend("auto");
|
||||
std::fs::write(&path, original.to_string()).unwrap();
|
||||
|
||||
let launch = prepare_backend_start(&path, true).unwrap();
|
||||
assert_eq!(launch.backend.as_deref(), Some("vulkan"));
|
||||
assert!(launch.note.is_none());
|
||||
let attempt = launch.attempt.unwrap();
|
||||
assert_eq!(attempt, BackendAttempt { requested: "vulkan".into(), previous: "auto".into() });
|
||||
let mut started = original.clone();
|
||||
started["backend_trial"]["started"] = serde_json::json!(true);
|
||||
assert_eq!(backend_settings(&path), started, "selection is returned only after the started marker is durable");
|
||||
|
||||
confirm_backend_start(&path, &attempt).unwrap();
|
||||
let mut kept = original;
|
||||
kept.as_object_mut().unwrap().remove(BACKEND_TRIAL);
|
||||
assert_eq!(backend_settings(&path), kept, "confirmation changes no other graphics preferences");
|
||||
let next = prepare_backend_start(&path, true).unwrap();
|
||||
assert_eq!(next.backend.as_deref(), Some("vulkan"));
|
||||
assert!(next.attempt.is_none() && next.note.is_none());
|
||||
let _ = std::fs::remove_dir_all(dir);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn interrupted_backend_start_restores_the_exact_previous_choice_once() {
|
||||
solidcraft_ui_egui::i18n::install();
|
||||
let _language = solidcraft_ui_text::scope("en");
|
||||
let dir = scratch("backend-interrupted");
|
||||
let path = dir.join("graphics.json");
|
||||
for (previous, label) in [("auto", "Automatic"), (" dx12, vulkan ", " dx12, vulkan "), ("", "Automatic")] {
|
||||
let mut expected = pending_backend(previous);
|
||||
std::fs::write(&path, expected.to_string()).unwrap();
|
||||
assert!(prepare_backend_start(&path, true).unwrap().attempt.is_some());
|
||||
|
||||
// A process crash leaves the started marker; the next normal launch rolls back.
|
||||
let recovered = prepare_backend_start(&path, true).unwrap();
|
||||
assert_eq!(recovered.backend.as_deref(), Some(previous));
|
||||
assert!(recovered.attempt.is_none());
|
||||
assert_eq!(
|
||||
recovered.note,
|
||||
Some(format!("The previous start with Vulkan did not open the window. SolidCraft restored {label}.")),
|
||||
"recovery describes both APIs using their displayed names"
|
||||
);
|
||||
expected["backend"] = serde_json::json!(previous);
|
||||
expected.as_object_mut().unwrap().remove(BACKEND_TRIAL);
|
||||
assert_eq!(backend_settings(&path), expected, "only the attempted API is reverted");
|
||||
assert!(prepare_backend_start(&path, true).unwrap().note.is_none(), "the notice is not repeated");
|
||||
}
|
||||
let _ = std::fs::remove_dir_all(dir);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn safe_override_and_fallback_launches_leave_backend_attempts_untouched() {
|
||||
let dir = scratch("backend-bypass");
|
||||
let path = dir.join("graphics.json");
|
||||
assert_eq!(prepare_backend_start(&path, true).unwrap(), BackendLaunch::default());
|
||||
assert!(!path.exists(), "default startup does not create a settings file");
|
||||
for started in [false, true] {
|
||||
let mut saved = pending_backend("dx12");
|
||||
saved["backend_trial"]["started"] = serde_json::json!(started);
|
||||
let bytes = serde_json::to_vec_pretty(&saved).unwrap();
|
||||
std::fs::write(&path, &bytes).unwrap();
|
||||
let launch = prepare_backend_start(&path, false).unwrap();
|
||||
assert_eq!(launch.backend.as_deref(), Some("vulkan"));
|
||||
assert!(launch.attempt.is_none() && launch.note.is_none());
|
||||
assert_eq!(std::fs::read(&path).unwrap(), bytes, "even an interrupted attempt waits for a normal launch");
|
||||
}
|
||||
let _ = std::fs::remove_dir_all(dir);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn backend_start_rollback_and_confirmation_cannot_overwrite_a_newer_choice() {
|
||||
let dir = scratch("backend-ownership");
|
||||
let path = dir.join("graphics.json");
|
||||
let saved = pending_backend("dx12");
|
||||
std::fs::write(&path, saved.to_string()).unwrap();
|
||||
let attempt = prepare_backend_start(&path, true).unwrap().attempt.unwrap();
|
||||
rollback_backend_start(&path, &attempt).unwrap();
|
||||
let mut reverted = saved.clone();
|
||||
reverted["backend"] = serde_json::json!("dx12");
|
||||
reverted.as_object_mut().unwrap().remove(BACKEND_TRIAL);
|
||||
assert_eq!(backend_settings(&path), reverted, "handled failure restores the last working preference");
|
||||
|
||||
for newer in [
|
||||
serde_json::json!({"backend": "gl"}),
|
||||
serde_json::json!({"backend": "vulkan", "backend_trial": {"previous": "dx12", "requested": "vulkan", "started": false}}),
|
||||
serde_json::json!({"backend": "vulkan", "backend_trial": {"previous": "auto", "requested": "vulkan", "started": true}}),
|
||||
serde_json::json!({"backend": "gl", "backend_trial": {"previous": "dx12", "requested": "vulkan", "started": true}}),
|
||||
] {
|
||||
let bytes = serde_json::to_vec_pretty(&newer).unwrap();
|
||||
std::fs::write(&path, &bytes).unwrap();
|
||||
confirm_backend_start(&path, &attempt).unwrap();
|
||||
rollback_backend_start(&path, &attempt).unwrap();
|
||||
assert_eq!(std::fs::read(&path).unwrap(), bytes, "stale launch state cannot consume another preference");
|
||||
}
|
||||
let _ = std::fs::remove_dir_all(dir);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn malformed_backend_guards_use_the_previous_api_or_automatic_without_touching_other_settings() {
|
||||
let dir = scratch("backend-malformed");
|
||||
let path = dir.join("graphics.json");
|
||||
for (trial, expected_backend) in [
|
||||
(serde_json::json!(null), "auto"),
|
||||
(serde_json::json!(42), "auto"),
|
||||
(serde_json::json!({}), "auto"),
|
||||
(serde_json::json!({"requested": "vulkan", "previous": "dx12"}), "dx12"),
|
||||
(serde_json::json!({"requested": "vulkan", "previous": "dx12", "started": "yes"}), "dx12"),
|
||||
(serde_json::json!({"requested": "vulkan", "previous": "x".repeat(257), "started": false}), "auto"),
|
||||
] {
|
||||
let mut saved = pending_backend("auto");
|
||||
saved["backend_trial"] = trial;
|
||||
std::fs::write(&path, saved.to_string()).unwrap();
|
||||
let launch = prepare_backend_start(&path, true).unwrap();
|
||||
assert_eq!(launch.backend.as_deref(), Some(expected_backend));
|
||||
assert!(launch.attempt.is_none());
|
||||
saved["backend"] = serde_json::json!(expected_backend);
|
||||
saved.as_object_mut().unwrap().remove(BACKEND_TRIAL);
|
||||
assert_eq!(backend_settings(&path), saved);
|
||||
}
|
||||
|
||||
let mut saved = pending_backend("auto");
|
||||
saved["backend"] = serde_json::json!("gl");
|
||||
std::fs::write(&path, saved.to_string()).unwrap();
|
||||
let launch = prepare_backend_start(&path, true).unwrap();
|
||||
assert_eq!(launch.backend.as_deref(), Some("gl"), "a stale marker cannot replace a newer API");
|
||||
assert!(launch.attempt.is_none() && launch.note.is_none());
|
||||
saved.as_object_mut().unwrap().remove(BACKEND_TRIAL);
|
||||
assert_eq!(backend_settings(&path), saved);
|
||||
let _ = std::fs::remove_dir_all(dir);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_backend_attempt_is_never_returned_when_its_marker_cannot_be_saved() {
|
||||
for started in [false, true] {
|
||||
let mut saved = pending_backend("dx12");
|
||||
saved["backend_trial"]["started"] = serde_json::json!(started);
|
||||
let graphics = saved.as_object().unwrap().clone();
|
||||
let error = prepare_backend_launch(graphics, true, |_| Err("fixture: write refused".into())).unwrap_err();
|
||||
assert_eq!(error, "fixture: write refused", "no selected backend escapes a failed transition");
|
||||
}
|
||||
|
||||
let dir = scratch("backend-unreadable");
|
||||
let path = dir.join("graphics.json");
|
||||
for damaged in ["{", "[]", "null"] {
|
||||
std::fs::write(&path, damaged).unwrap();
|
||||
assert!(prepare_backend_start(&path, true).is_err());
|
||||
assert_eq!(std::fs::read_to_string(&path).unwrap(), damaged, "unreadable settings are never overwritten");
|
||||
}
|
||||
assert!(prepare_backend_start(&dir, true).is_err(), "a filesystem read failure is reported");
|
||||
let _ = std::fs::remove_dir_all(dir);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn intel_macs_start_without_indirect_call_validation() {
|
||||
use eframe::wgpu::InstanceFlags as F;
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
Read `assets/README.md` before changing media, fonts, artwork or their consumers.
|
||||
For **any UI icon, icon assignment or review-tool change**, also read
|
||||
`assets/icons/ui/AGENTS.md` and `assets/icons/ui/STYLE_GUIDE.md` before editing.
|
||||
`crates/look/icons/AGENTS.md` and `crates/look/icons/STYLE_GUIDE.md` before editing.
|
||||
These files are the specification; chat history and old previews are not required.
|
||||
|
||||
- Keep one editable authority per resource. UI SVGs are masters, not exports of a
|
||||
|
||||
@@ -70,4 +70,10 @@ meetup. If you publish a fork or a modified build, give it its own name and logo
|
||||
don't mistake it for SolidCraft.
|
||||
|
||||
The wordmark is set in IBM Plex Sans Bold (SIL Open Font License 1.1, the interface font in
|
||||
`assets/fonts/ibm-plex-sans/`) and outlined, so you don't need the font to print it.
|
||||
`crates/look/fonts/ibm-plex-sans/`) and outlined, so you don't need the font to print it.
|
||||
|
||||
## Licence
|
||||
|
||||
The SolidCraft name, logo and brand kit are under the SolidCraft Brand and Interface Licence
|
||||
([LICENSE-BRAND](../../LICENSE-BRAND)). Using them for anything other than SolidCraft needs the
|
||||
maintainers' written permission first.
|
||||
|
||||
+129
-1
@@ -265,6 +265,7 @@
|
||||
"Edge": "Aresta",
|
||||
"Edges": "Arestes",
|
||||
"Edit": "Editar",
|
||||
"Edit Holes": "Editar forats",
|
||||
"Edit Profile Sketch": "Editar el bocet del perfil",
|
||||
"Edit shortcuts": "Editar les dreceres",
|
||||
"Enable rule": "Activar la regla",
|
||||
@@ -976,6 +977,7 @@
|
||||
"browser.calibrate_click_a": "Feu clic a la imatge per al punt A, o escriviu-ne les coordenades.",
|
||||
"browser.calibrate_click_b": "Feu clic a la imatge per al punt B, o escriviu-ne les coordenades.",
|
||||
"browser.calibrate_title": "Calibrar: {name}",
|
||||
"browser.canvas_locked": "El llenç està bloquejat. Desbloquegeu-lo primer.",
|
||||
"browser.capture_many": "S'han mogut {count} components, però no s'han capturat les seves posicions.",
|
||||
"browser.capture_note": "Capturar la posició conserva la posició nova; Revertir la posició restaura l'anterior.",
|
||||
"browser.capture_one": "S'ha mogut un component, però no s'ha capturat la seva posició.",
|
||||
@@ -1205,6 +1207,7 @@
|
||||
"cmd.material_properties_directional": "Mòdul elàstic direccional",
|
||||
"cmd.material_properties_validate": "Validar les dades del material físic",
|
||||
"cmd.mesh_convert": "Convertir la malla",
|
||||
"cmd.model_body_features": "Llistar les operacions del cos",
|
||||
"cmd.model_edges": "Llistar les arestes",
|
||||
"cmd.model_faces": "Llistar les cares",
|
||||
"cmd.model_threads": "Llistar les roscas",
|
||||
@@ -1233,8 +1236,11 @@
|
||||
"cmd.panel.dismiss": "Descartar la vista prèvia del panell",
|
||||
"cmd.panel.float": "Panell flotant",
|
||||
"cmd.panel.focus": "Enfocar el panell",
|
||||
"cmd.panel.focus.next": "Enfocar el panell següent",
|
||||
"cmd.panel.focus.previous": "Enfocar el panell anterior",
|
||||
"cmd.panel.list": "Llistar els panells",
|
||||
"cmd.panel.move": "Moure el panell",
|
||||
"cmd.panel.move.next_zone": "Moure el panell a la zona següent",
|
||||
"cmd.panel.native_close": "Tornar a acoblar la secció de panell nativa",
|
||||
"cmd.panel.open": "Obrir el panell",
|
||||
"cmd.panel.peek": "Vista prèvia d'un panell contret",
|
||||
@@ -1242,6 +1248,12 @@
|
||||
"cmd.panel.reset_pair": "Restablir el divisor del panell",
|
||||
"cmd.panel.resize": "Redimensionar la secció del panell",
|
||||
"cmd.panel.resize_pair": "Redimensionar el divisor del panell",
|
||||
"cmd.panel.sash.down": "Redimensionar el divisor del panell cap avall",
|
||||
"cmd.panel.sash.left": "Redimensionar el divisor del panell cap a l'esquerra",
|
||||
"cmd.panel.sash.reset": "Restablir el divisor del panell enfocat",
|
||||
"cmd.panel.sash.right": "Redimensionar el divisor del panell cap a la dreta",
|
||||
"cmd.panel.sash.up": "Redimensionar el divisor del panell cap amunt",
|
||||
"cmd.panel.toggle": "Alternar el panell enfocat",
|
||||
"cmd.parameters_add": "Afegir un paràmetre d'usuari",
|
||||
"cmd.parameters_change": "Canviar paràmetres",
|
||||
"cmd.parameters_comment": "Comentar el paràmetre",
|
||||
@@ -1365,6 +1377,7 @@
|
||||
"cmd.sketch.construction_line.tangent_external": "Tangent per un punt exterior",
|
||||
"cmd.sketch.construction_line.tangent_two": "Tangent comuna",
|
||||
"cmd.sketch.construction_line.vertical": "Línia de construcció vertical",
|
||||
"cmd.sketch.replace": "Substituir el bocet",
|
||||
"cmd.sketch_arc3d": "Arc 3D",
|
||||
"cmd.sketch_arc_center_point": "Arc de centre i punt",
|
||||
"cmd.sketch_arc_tangent": "Arc tangent",
|
||||
@@ -1496,6 +1509,7 @@
|
||||
"cmd.timeline_stop": "Aturar l'historial",
|
||||
"cmd.timeline_suppress": "Suprimir l'operació",
|
||||
"cmd.ui.assistant": "Alternar l'Assistent",
|
||||
"cmd.ui.palette": "Cercar ordres",
|
||||
"cmd.view.navigator": "Navegador de vistes personalitzat",
|
||||
"cmd.view.render_browser": "Explorador de render",
|
||||
"cmd.view.render_dock": "Moure l'acoblament del render",
|
||||
@@ -2015,6 +2029,7 @@
|
||||
"help.view.visual_style": "Canvia com es dibuixa el model: sombrejat amb o sense arestes, filferro, o amb arestes ocultes. Feu servir filferro per veure-hi a dins, i sombrejat per a un aspecte net.",
|
||||
"history.sketch_under_constrained": "Restricció insuficient ({count} graus de llibertat)",
|
||||
"history.sketch_under_constrained_one": "Restricció insuficient ({count} grau de llibertat)",
|
||||
"hole_folder.applies_to": "Els canvis s'apliquen als {count} forats de {folder}; cadascun conserva la seva posició.",
|
||||
"hole_presets.confirm_delete": "Confirmar l'eliminació",
|
||||
"hole_presets.delete": "Eliminar",
|
||||
"hole_presets.delete_prompt": "Voleu eliminar aquest preajust personal? Els forats existents no canvien.",
|
||||
@@ -2417,6 +2432,7 @@
|
||||
"parts.dimension.width": "Amplada",
|
||||
"parts.family.bearing": "Rodament rígid de boles (envolupant)",
|
||||
"parts.family.button_head_cap_screw": "Cargol de cap botó",
|
||||
"parts.family.countersunk_socket_screw": "Cargol avellanat amb hexàgon interior",
|
||||
"parts.family.dowel_pin": "Passador cilíndric",
|
||||
"parts.family.hex_bolt": "Cargol de cap hexagonal",
|
||||
"parts.family.hex_cap_screw_inch": "Cargol de cap hexagonal (polzades)",
|
||||
@@ -2515,6 +2531,8 @@
|
||||
"prefs.bottom_centre": "Baix al centre",
|
||||
"prefs.bottom_right": "Baix a la dreta",
|
||||
"prefs.browser": "Explorador",
|
||||
"prefs.browser_body_features": "Operacions sota els cossos",
|
||||
"prefs.browser_body_features_note": "Cada cos de l'explorador es desplega sobre les operacions de la línia de temps que el van construir, en l'ordre de la línia de temps.",
|
||||
"prefs.browser_components_open": "Els components comencen oberts",
|
||||
"prefs.browser_components_open_note": "Cada component de l'explorador comença obert, com abans, en lloc de tancat fins que l'obriu.",
|
||||
"prefs.browser_eye_left": "Ull al costat de la fletxa de plegat",
|
||||
@@ -2555,7 +2573,11 @@
|
||||
"prefs.design_tools.degrees": "Graus",
|
||||
"prefs.design_tools.double_click_help": "O per editar-ne un de vinculat al seu lloc.",
|
||||
"prefs.design_tools.ghost": "Mostrar com un fantasma la posició anterior de les peces mogudes",
|
||||
"prefs.design_tools.hole_group": "Agrupar els forats creats junts",
|
||||
"prefs.design_tools.hole_group_help": "Els forats creats alhora comparteixen una carpeta a l'historial, tancada al principi; obriu-la per editar un forat per separat.",
|
||||
"prefs.design_tools.hole_moves_help": "Tornar a triar la cara mou el forat en lloc d'eliminar-lo.",
|
||||
"prefs.design_tools.hole_several": "Diversos forats en una cara",
|
||||
"prefs.design_tools.hole_several_help": "Fer clic en un altre punt d'una cara afegeix un altre forat; fer clic en un forat el treu.",
|
||||
"prefs.design_tools.hole_snaps_help": "El centre d'una cara i els centres de les seves arestes rodones.",
|
||||
"prefs.design_tools.imported_files": "Fitxers importats",
|
||||
"prefs.design_tools.note": "Nota",
|
||||
@@ -2637,6 +2659,8 @@
|
||||
"prefs.history": "Historial",
|
||||
"prefs.history_bar_groups": "Plegar la barra Historial en grups",
|
||||
"prefs.history_bar_groups_note": "En un historial llarg, una sèrie d'operacions d'un mateix component es plega en una fitxa, i les carpetes d'operacions comencen plegades. Un ensamblatge STEP inserit va a una carpeta Grup. Desactivat, es mostra cada operació, les carpetes comencen obertes i no es crea cap carpeta.",
|
||||
"prefs.history_folder_kind_icon": "Icona de carpeta segons les seves operacions",
|
||||
"prefs.history_folder_kind_icon_note": "Una carpeta de l'historial les operacions de la qual són totes del mateix tipus mostra la seva icona.",
|
||||
"prefs.history_group_joints": "Agrupar les unions a l'historial",
|
||||
"prefs.history_group_joints_note": "Dues o més unions es mostren com un botó amb el seu nombre, i en fer clic es mostra cadascuna. Desactivat, es mostra cada unió.",
|
||||
"prefs.history_origin_bodies": "Mostrar l'origen i els cossos a dalt",
|
||||
@@ -2742,6 +2766,7 @@
|
||||
"prefs.origin_plane_names": "Noms dels plans d'origen",
|
||||
"prefs.origin_plane_names_note": "Noms que es mostren a l'explorador, als diàlegs i a les llistes. {top} és XY, {front} és XZ i {right} és YZ, amb Z cap amunt. Les ordres, els scripts i els dissenys desats mantenen XY, XZ i YZ.",
|
||||
"prefs.overall_speed": "Velocitat general",
|
||||
"prefs.panel_layout.recovery": "No s'han pogut restaurar les disposicions de panells desades. Les dades desades es conserven; Clàssic continua disponible.",
|
||||
"prefs.parameter_list_rows": "Files de la llista de paràmetres",
|
||||
"prefs.parameter_list_rows_tip": "El nombre de paràmetres que la fletxa avall llista en un quadre d'expressió buit.",
|
||||
"prefs.persistent_ribbon_pressed": "Ressaltar les ordres actives de la cinta",
|
||||
@@ -2803,6 +2828,8 @@
|
||||
"prefs.remember_dialog_values.help": "Desactivat de manera predeterminada. Si s'activa, quan una ordre acaba correctament, els seus valors i opcions segurs es reutilitzen la propera vegada que obriu la mateixa ordre, fins que es tanqui SolidCraft.",
|
||||
"prefs.render_legacy_image_defaults": "Fer servir els valors d'imatge anteriors de Render",
|
||||
"prefs.render_legacy_image_defaults_help": "Manté el flux manual anterior: les configuracions noves fan servir el rasteritzat de CPU, el ray tracing de CPU conserva el mostreig fix i els resultats renderitzats s'obren a mà. En entrar a Render es reenquadra, es canvien les preses sense restaurar-ne les càmeres i es fa servir l'enquadrament i la navegació anteriors. Es desactiva la vista prèvia automàtica de la imatge en directe. Les configuracions desades no canvien.",
|
||||
"prefs.render_legacy_memory_admission": "Fer servir les comprovacions de memòria de renderitzat anteriors",
|
||||
"prefs.render_legacy_memory_admission_help": "Permet els renderitzats natius dins dels pressupostos fixos de memòria compartida i de l'amfitrió encara que la seva estimació superi la RAM disponible. Els límits del dispositiu i les comprovacions d'assignació es continuen aplicant.",
|
||||
"prefs.render_previous_geometry_budget": "Fer servir el pressupost de geometria anterior de la previsualització del renderitzat",
|
||||
"prefs.render_previous_geometry_budget_help": "Restaura el límit fix anterior (512 MiB a l'escriptori de 64 bits, 128 MiB a la resta) en lloc del pressupost basat en el dispositiu.",
|
||||
"prefs.reports_saved": "{n} desats",
|
||||
@@ -2829,6 +2856,8 @@
|
||||
"prefs.select_other_hidden": "Seleccionar geometria oculta amb Seleccionar-ne un altre",
|
||||
"prefs.select_other_hidden_help": "Activat: inclou cossos, bocets i arestes ocults o ocluïts a prop del punter. Desactivat: usa la llista original de geometria visible sota el punter.",
|
||||
"prefs.selecting": "Selecció",
|
||||
"prefs.shared_panel_layout": "Fer servir la disposició de panells compartida",
|
||||
"prefs.shared_panel_layout_help": "Mostra l'explorador, l'historial i l'assistent existents en panells movibles. El canvi s'aplica en aplicar les preferències.",
|
||||
"prefs.shift": "Majúscules",
|
||||
"prefs.shift_add_ctrl_toggle": "El Majúscules només afegeix; Ctrl/Cmd alterna",
|
||||
"prefs.shift_add_note": "Activat: el Majúscules afegeix i Ctrl/Cmd alterna. Desactivat (predeterminat): tots dos alternen.",
|
||||
@@ -2851,6 +2880,8 @@
|
||||
"prefs.sketch.drawing": "Dibuix",
|
||||
"prefs.sketch.ellipse_axes": "Dibuixar les el·lipses amb els seus eixos",
|
||||
"prefs.sketch.ellipse_axes_note": "Els eixos major i menor com a línies de construcció, per poder acotar els semieixos i els eixos. Desactivat: només l'el·lipse, i D a sobre seu dóna el radi menor allà on es tiri el valor, dibuixat i etiquetat R com abans.",
|
||||
"prefs.sketch.escape_twice_finishes": "Doble Esc acaba el bocet",
|
||||
"prefs.sketch.escape_twice_finishes_note": "Dues pulsacions ràpides d'Esc acaben el bocet. Desactivat: Esc només cancel·la l'eina o la selecció, i el bocet només s'acaba amb Acabar el bocet.",
|
||||
"prefs.sketch.exit_keep": "Mantenir",
|
||||
"prefs.sketch.exit_previous": "Tornar a la vista anterior",
|
||||
"prefs.sketch.exit_unless_rotated": "Tret que s'hagi girat",
|
||||
@@ -3193,8 +3224,10 @@
|
||||
"render.category_paint": "Pintura",
|
||||
"render.category_plastic": "Plàstic",
|
||||
"render.category_wood": "Fusta",
|
||||
"render.caustics_area_lights": "Càustiques de llums d'àrea",
|
||||
"render.caustics_depth": "Profunditat del camí de càustiques",
|
||||
"render.caustics_enable": "Càustiques de vidre amb llums puntuals i direccionals",
|
||||
"render.caustics_environment": "Càustiques de l'entorn",
|
||||
"render.caustics_help": "El nombre de fotons controla el soroll i la feina. El radi de captació canvia detall nítid per una estimació més suau. La CPU necessita il·luminació indirecta.",
|
||||
"render.caustics_path_required": "Les càustiques de CPU necessiten il·luminació indirecta.",
|
||||
"render.caustics_photons": "Fotons",
|
||||
@@ -3371,7 +3404,7 @@
|
||||
"render.cpu_opaque_required": "El ray tracing de CPU necessita un fons opac. Desactiveu Fons transparent per continuar.",
|
||||
"render.cpu_options_pending": "Aquest panell de CPU encara no pot editar l'emissió, els efectes de superfície, el vidre ni l'anisotropia. Esborreu aquestes opcions de l'API abans de fer-lo servir.",
|
||||
"render.cpu_path_depth": "Profunditat del camí",
|
||||
"render.cpu_path_help": "Afegeix rebots de llum entre superfícies opaques i a través de formes de vidre admeses. Requereix renderitzat progressiu i ombres traçades. La profunditat del camí compta superfícies ombrejades, límits de vidre i esdeveniments de dispersió, començant pel primer impacte (1–16). La profunditat 1 dona il·luminació directa sobre superfícies opaques; els valors més alts permeten més rebots o creuaments de vidre i poden trigar més. Desactiveu la il·luminació indirecta per fer servir reflexos personalitzats o anisotropia.",
|
||||
"render.cpu_path_help": "Afegeix rebots de llum entre superfícies opaques i a través de formes de vidre admeses. Requereix renderitzat progressiu i ombres traçades. La profunditat del camí compta superfícies ombrejades, límits de vidre i esdeveniments de dispersió, començant pel primer impacte (1–64). La profunditat 1 dona il·luminació directa sobre superfícies opaques; els valors més alts permeten més rebots o creuaments de vidre i poden trigar més. Desactiveu la il·luminació indirecta per fer servir reflexos personalitzats o anisotropia.",
|
||||
"render.cpu_path_lighting": "Il·luminació indirecta",
|
||||
"render.cpu_path_optics_reason": "Es conserven els vostres ajustos. Desactiveu la il·luminació indirecta per fer servir reflexos personalitzats o anisotropia.",
|
||||
"render.cpu_point": "Llum puntual",
|
||||
@@ -3411,6 +3444,12 @@
|
||||
"render.cpu_subsurface_denoise_reason": "La dispersió subsuperficial de CPU necessita la reducció de soroll desactivada. Es conserven els vostres ajustos.",
|
||||
"render.cpu_subsurface_help": "La dispersió redirigeix la llum dins del vidre tancat. Les taxes positives necessiten il·luminació indirecta amb la reducció de soroll desactivada. La taxa és de col·lisions per mm; 0 no afegeix dispersió. Un biaix de fase positiu afavoreix les direccions cap endavant; un de negatiu, les cap enrere.",
|
||||
"render.cpu_summary": "Ray tracing de CPU · reflexos · HDR · llums direccionals i puntuals",
|
||||
"render.cpu_threads": "Processos de CPU",
|
||||
"render.cpu_threads_auto": "Automàtic",
|
||||
"render.cpu_threads_custom": "Personalitzat",
|
||||
"render.cpu_threads_help": "Automàtic fa servir els processos de CPU disponibles. Un procés s'executa en sèrie. Més processos poden necessitar més memòria.",
|
||||
"render.cpu_threads_single": "Un",
|
||||
"render.cpu_threads_web": "El renderitzat al navegador fa servir un procés cooperatiu. Es conserva l'elecció de processos desada per a l'escriptori.",
|
||||
"render.cpu_transparent_help": "El PNG transparent treu el fons i conserva la cobertura de les vores. L'opacitat del cos i de la cara ha de mantenir-se al 100 %.",
|
||||
"render.cpu_volume_enable_path": "Activar la il·luminació indirecta",
|
||||
"render.cpu_volume_enable_path_plan": "Ray tracing de CPU · profunditat {depth} · {spp} mostres/píxel · llavor {seed} · ombres traçades. Conserva l'atmosfera definida i el pressupost d'imatge.",
|
||||
@@ -3419,6 +3458,40 @@
|
||||
"render.cpu_volume_method_incompatible": "Aquests ajustos de llum, mostreig o atmosfera no es poden transferir a aquest mètode. Es conserven els vostres ajustos.",
|
||||
"render.cpu_volume_path_required": "Activeu la il·luminació indirecta per fer servir l'atmosfera de CPU.",
|
||||
"render.cpu_warm_cool": "Càlid i fred",
|
||||
"render.denoise_class_background": "Omès: fons",
|
||||
"render.denoise_class_coverage": "Omès: cobertura parcial",
|
||||
"render.denoise_class_degenerate": "Omès: camí degenerat",
|
||||
"render.denoise_class_depth": "Omès: límit de profunditat del camí",
|
||||
"render.denoise_class_emitter": "Omès: emissor de llum",
|
||||
"render.denoise_class_exit": "Omès: sortida incompatible",
|
||||
"render.denoise_class_identity": "Omès: límit d'identitat de guia",
|
||||
"render.denoise_class_lens": "Omès: profunditat de camp",
|
||||
"render.denoise_class_material": "Omès: material no admès",
|
||||
"render.denoise_class_nested": "Omès: medi imbricat",
|
||||
"render.denoise_class_optical": "Elegible: superfície refractada",
|
||||
"render.denoise_class_reflection": "Omès: punt final reflectant",
|
||||
"render.denoise_class_surface": "Elegible: superfície",
|
||||
"render.denoise_class_tir": "Omès: reflexió total interna",
|
||||
"render.denoise_class_transmission": "Omès: transmissió addicional",
|
||||
"render.denoise_class_unavailable": "Omès: sense guia",
|
||||
"render.denoise_class_volume": "Omès: dispersió de volum",
|
||||
"render.denoise_diagnostics_counts": "Elegibles: {eligible} · Omessos: {skipped}",
|
||||
"render.denoise_diagnostics_enable": "Recollir el diagnòstic de reducció de soroll",
|
||||
"render.denoise_diagnostics_grid": "Recomptes de píxels amb la mida interna {width} × {height}.",
|
||||
"render.denoise_diagnostics_help": "Recull els recomptes de píxels elegibles i omesos fins i tot amb la reducció de soroll desactivada. Els recomptes fan servir la mida interna de renderitzat; la màscara fa servir la mida de sortida.",
|
||||
"render.denoise_diagnostics_title": "Diagnòstic de reducció de soroll",
|
||||
"render.denoise_export_mask": "Exportar la màscara PNG",
|
||||
"render.denoise_firefly": "Suprimir els píxels brillants aïllats",
|
||||
"render.denoise_format_mask": "Màscara PNG",
|
||||
"render.denoise_mask_copy_help": "Exporteu la màscara de reducció de soroll com a PNG o torneu a la imatge renderitzada per copiar-la.",
|
||||
"render.denoise_mask_unavailable": "Activeu el diagnòstic de reducció de soroll i renderitzeu una imatge per inspeccionar-ne la màscara.",
|
||||
"render.denoise_optical_filter": "Filtrar miralls i vidre",
|
||||
"render.denoise_optical_filter_help": "Filtra la llum reflectida i transmesa elegible. Desactiveu-ho per reduir el soroll només a les superfícies opaques.",
|
||||
"render.denoise_passes": "Passades del filtre",
|
||||
"render.denoise_settings_help": "Més passades suavitzen una àrea més gran. La intensitat controla quant filtra cada passada. Els camins òptics no admesos no es filtren.",
|
||||
"render.denoise_strength": "Intensitat de la reducció de soroll",
|
||||
"render.denoise_view_image": "Imatge renderitzada",
|
||||
"render.denoise_view_mask": "Màscara de reducció de soroll",
|
||||
"render.diag_bodies": "Cossos visibles",
|
||||
"render.diag_job_details": "Detalls del treball capturat",
|
||||
"render.diag_last_check": "Última comprovació prèvia",
|
||||
@@ -3973,6 +4046,8 @@
|
||||
"render.material_transient": "Sobreescriptures òptiques temporals d'aquesta pestanya del document. No es desen al disseny, a la configuració de renderitzat ni a la biblioteca de materials.",
|
||||
"render.material_v_up": "La coordenada V apunta cap amunt a la imatge",
|
||||
"render.material_weight": "Pes del recobriment (0–1)",
|
||||
"render.metal_energy_compensation": "Recuperar la reflectància del metall rugós",
|
||||
"render.metal_energy_compensation_help": "Compensa la llum perduda entre les microfacetes del metall rugós. El renderitzat per CPU necessita il·luminació indirecta.",
|
||||
"render.method_cpu": "Ray tracing de CPU",
|
||||
"render.method_gpu": "Path tracing de GPU",
|
||||
"render.method_limit_raster": "El raster fa servir la vista prèvia d'estudi opaca fixa. Trieu un mètode de ray tracing explícit per als controls òptics compatibles.",
|
||||
@@ -4101,6 +4176,8 @@
|
||||
"render.quality_denoise_on": "Reducció de soroll: Activada",
|
||||
"render.quality_draft": "Esborrany",
|
||||
"render.quality_high": "Alt",
|
||||
"render.quality_legacy_samples": "Valor desat: {samples} spp. Les seleccions noves es limiten a {maximum} spp.",
|
||||
"render.quality_preset_limit": "Aquest preajust supera el límit de selecció de 16384 spp. Trieu un nombre de mostres de fins a 16384.",
|
||||
"render.quality_projection_help": "Aquesta revisió només canvia la resolució, el pressupost de mostres, la profunditat del camí, la llavor i la reducció de soroll. Els altres ajustos es conserven; el pressupost no certifica la convergència.",
|
||||
"render.quality_review": "Revisar el pressupost de mostres",
|
||||
"render.quality_summary": "{width} × {height} · {samples} mostres · profunditat {depth} · llavor {seed} · {denoise}",
|
||||
@@ -4248,6 +4325,7 @@
|
||||
"render.show_shots_label": "Mostrar la tira de preses",
|
||||
"render.size_4k": "4K",
|
||||
"render.size_4k_uhd": "4K UHD",
|
||||
"render.size_8k_uhd": "8K UHD",
|
||||
"render.size_custom": "Personalitzat…",
|
||||
"render.size_full_hd": "Full HD",
|
||||
"render.size_hd": "HD",
|
||||
@@ -4410,6 +4488,11 @@
|
||||
"render.subsurface_enable": "Recorregut aleatori de dispersió interior",
|
||||
"render.subsurface_help": "Només dielèctrics tancats. La dispersió i l'absorció RGB són coeficients separats per mm. Els camins es dispersen dins de la geometria real i després es refracten o reflecteixen a la frontera. Desactiveu la transmissió recta d'ombres, la reducció de soroll de superfície i el volum exterior; feu servir un estrat de Fresnel. No és un shader de difusió, una graella de densitat ni un material mesurat. Els medis densos poden necessitar més mostres i profunditat de camí.",
|
||||
"render.subsurface_rate": "Taxa de col·lisions de dispersió",
|
||||
"render.supersampling": "Supermostreig",
|
||||
"render.supersampling_dimensions": "Renderitza {width} × {height} i redueix a {output_width} × {output_height}. Fa servir el quàdruple de píxels.",
|
||||
"render.supersampling_help": "Renderitzeu al doble d'amplada i alçada i després reduïu-ho en llum lineal. La mida de sortida no canvia.",
|
||||
"render.supersampling_off": "Desactivat",
|
||||
"render.supersampling_x2": "2×",
|
||||
"render.surface_import.author": "Autor",
|
||||
"render.surface_import.busy": "S'està important la imatge…",
|
||||
"render.surface_import.complete": "Trieu una imatge i introduïu-ne l'autor, la font i la llicència.",
|
||||
@@ -4423,6 +4506,8 @@
|
||||
"render.surface_import.saved_cpu": "Deseu els mapes per fer-los servir amb el renderitzat de CPU.",
|
||||
"render.surface_import.source": "Font",
|
||||
"render.surface_import.title": "Importar una imatge",
|
||||
"render.texture_filtering": "Filtrar el detall de les textures",
|
||||
"render.texture_filtering_help": "Fa servir nivells mip i filtratge anisotròpic per reduir l'aliasing de les textures en reduir-les. Consumeix més memòria; desactivat manté el filtratge anterior.",
|
||||
"render.tone_aces_fitted": "ACES ajustat",
|
||||
"render.tone_reinhard": "Reinhard",
|
||||
"render.transmission_scope": "El vidre de GPU admet medis disjunts certificats. No s'ofereixen medis imbricats sense restriccions ni un estimador de transmissió sense soroll.",
|
||||
@@ -5517,6 +5602,7 @@
|
||||
"ui.heading_plastic": "PLÀSTIC",
|
||||
"ui.heading_position": "POSICIÓ",
|
||||
"ui.heading_prepare": "PREPARAR",
|
||||
"ui.heading_press_pull": "PRÉMER I ESTIRAR",
|
||||
"ui.heading_rectangular_pattern": "PATRÓ RECTANGULAR",
|
||||
"ui.heading_revolve": "REVOLUCIÓ",
|
||||
"ui.heading_right": "DRETA",
|
||||
@@ -5653,6 +5739,8 @@
|
||||
"ui.mesh_format_3mf": "3MF",
|
||||
"ui.mesh_format_3mf_tagged": "3MF amb etiquetes de cara",
|
||||
"ui.mesh_format_stl": "STL",
|
||||
"ui.mesh_import_origin": "Moure a l'origen",
|
||||
"ui.mesh_import_origin_tip": "Centra la malla en X i Y amb la base a Z = 0. Si està desactivat, la malla conserva les coordenades desades al fitxer.",
|
||||
"ui.minor_radius": "Radi menor",
|
||||
"ui.mirror": "Simetria",
|
||||
"ui.mirror_line": "Línia de simetria",
|
||||
@@ -5757,6 +5845,42 @@
|
||||
"ui.panel_host.surface": "Panell",
|
||||
"ui.panel_host.tab": "Pestanya del panell",
|
||||
"ui.panel_host.tabs": "Totes les pestanyes",
|
||||
"ui.panel_layout.applied": "S'ha aplicat {name} a {workspace}",
|
||||
"ui.panel_layout.cancel": "Cancel·lar",
|
||||
"ui.panel_layout.confirm_replace": "Voleu substituir «{name}»?",
|
||||
"ui.panel_layout.copy": "Copiar",
|
||||
"ui.panel_layout.current": "Disposició actual",
|
||||
"ui.panel_layout.custom": "Personalitzada",
|
||||
"ui.panel_layout.custom_hint": "S'han mogut panells des de {name}.",
|
||||
"ui.panel_layout.details": "Detalls",
|
||||
"ui.panel_layout.layout_workspace": "Espai de treball de disposició",
|
||||
"ui.panel_layout.page_defaults_hint": "Restableix els ajustos d'aquesta pàgina. L'organització dels panells i les disposicions desades es conserven.",
|
||||
"ui.panel_layout.panel_layout": "Disposició de panells",
|
||||
"ui.panel_layout.panel_style": "Estil de panells",
|
||||
"ui.panel_layout.replace": "Substituir la disposició",
|
||||
"ui.panel_layout.replace_current": "Substituir per l'actual",
|
||||
"ui.panel_layout.replace_short": "Substituir",
|
||||
"ui.panel_layout.reset": "Restablir l'espai de treball",
|
||||
"ui.panel_layout.reset_hint": "Restableix {workspace} a la seva disposició predeterminada. Les disposicions desades es conserven.",
|
||||
"ui.panel_layout.reset_short": "Restablir",
|
||||
"ui.panel_layout.restore_failed": "No s'ha pogut restaurar la vostra disposició",
|
||||
"ui.panel_layout.save": "Desar la disposició",
|
||||
"ui.panel_layout.save_as": "Desar com a",
|
||||
"ui.panel_layout.save_as_tile": "Desar com a…",
|
||||
"ui.panel_layout.selected": "seleccionada",
|
||||
"ui.panel_layout.suggested_name": "Disposició {n}",
|
||||
"ui.panel_layout.try_again": "Torneu-ho a provar",
|
||||
"ui.panel_layout.validation.builtin": "Les disposicions integrades no es poden canviar",
|
||||
"ui.panel_layout.validation.duplicate": "Ja teniu aquest nom",
|
||||
"ui.panel_layout.validation.empty": "Introduïu un nom",
|
||||
"ui.panel_layout.validation.full": "64 de 64 desades. Trieu-ne una per substituir-la.",
|
||||
"ui.panel_layout.validation.invalid": "Feu servir d'1 a 64 caràcters, sense caràcters de control",
|
||||
"ui.panel_layout.workspace.classic": "Clàssic",
|
||||
"ui.panel_layout.workspace.modelling": "Modelatge",
|
||||
"ui.panel_layout.workspace.render": "Renderitzat",
|
||||
"ui.panel_layout.workspace.review": "Revisió",
|
||||
"ui.panel_layout.workspace.sketch": "Bocet",
|
||||
"ui.panel_layout.your_layout": "la vostra disposició",
|
||||
"ui.parallel": "Paral·lel",
|
||||
"ui.parameters": "Paràmetres",
|
||||
"ui.part_size_needs_a_part": "Seleccioneu una peça normalitzada inserida (un cargol, una femella, una volandera o un passador) per canviar-ne la mida. Per fer un cos més gran o més petit, feu servir Escala.",
|
||||
@@ -5822,6 +5946,8 @@
|
||||
"ui.profiles": "Perfils",
|
||||
"ui.project": "Projectar",
|
||||
"ui.project_face_edges_sketch": "Projectar arestes de cares als bocets nous",
|
||||
"ui.project_references_construction": "Projectar les referències com a geometria de construcció",
|
||||
"ui.project_references_construction_note": "Projectar, Intersecar, Incloure geometria 3D i les arestes de cara d'un bocet nou sobre una cara creen geometria de construcció: referències sobre les quals dibuixar, excloses dels perfils. Continuen vinculades al model.",
|
||||
"ui.properties": "Propietats",
|
||||
"ui.properties.copy_matrix": "Copiar la matriu",
|
||||
"ui.properties.first_moments": "Primers moments",
|
||||
@@ -5865,6 +5991,8 @@
|
||||
"ui.renderer": "Motor de renderitzat",
|
||||
"ui.repeat": "Repetir",
|
||||
"ui.repeat_nothing": "Encara no hi ha res a repetir: inicieu una eina o un diàleg primer.",
|
||||
"ui.replace_sketch.from_file": "Des d'un fitxer de disseny…",
|
||||
"ui.replace_sketch.no_sketches": "Aquest disseny no té cap bocet per reutilitzar",
|
||||
"ui.replace_with_link_done": "Les còpies ja són col·locacions del disseny vinculat.",
|
||||
"ui.report_a_bug": "Notificar un error",
|
||||
"ui.report_characters_left_one": "Queda {count} caràcter",
|
||||
|
||||
@@ -931,7 +931,7 @@
|
||||
"ai.http.confirm": "Allow for this endpoint",
|
||||
"ai.http.warning": "The API key and conversation will be sent unencrypted. Anyone with access to the network may read or change them. Use this only on a network you trust.",
|
||||
"ai.prefs.allow_control": "Let AI agents connect",
|
||||
"ai.prefs.allow_control_note": "A local channel (MCP). Nothing leaves this computer.\n\nOpens a control channel on this computer only (127.0.0.1, port 27878 or the next free one). A program that connects must also show a secret token that only your user account can read, made fresh at every start. Takes effect the next time SolidCraft starts. Off: nothing listens unless you start SolidCraft with --control.",
|
||||
"ai.prefs.allow_control_note": "A local channel (MCP). Nothing leaves this computer.\n\nOpens a control channel on this computer only (127.0.0.1, on the port below; 27878 takes the next free one when it is in use). A program that connects must also show a secret token that only your user account can read, made fresh at every start. Takes effect at once. Off: nothing listens unless you start SolidCraft with --control.",
|
||||
"ai.prefs.availability": "Availability",
|
||||
"ai.prefs.background_commands": "Run slow commands in the background",
|
||||
"ai.prefs.connect_apps": "Add SolidCraft to AI apps",
|
||||
@@ -5041,7 +5041,7 @@
|
||||
"ui.agent_chat_permission": "The agent asks to run: {title}",
|
||||
"ui.agent_chat_pick": "Agent",
|
||||
"ui.agent_chat_pick_context": "Pick context",
|
||||
"ui.agent_chat_pick_context_tip": "Choose faces, edges, features and bodies in the model for the agent to look at, then press OK",
|
||||
"ui.agent_chat_pick_context_tip": "Choose faces, edges, features and bodies in the model, then press OK: they are put into the message as a pill where the cursor is (typing @ does the same)",
|
||||
"ui.agent_chat_placeholder": "Ask the agent to change the design…",
|
||||
"ui.agent_chat_placeholder_busy": "Queue a message for when the agent is done (Ctrl+Enter: send now)",
|
||||
"ui.agent_chat_pop_out": "Open in its own window, which you can move to another screen",
|
||||
|
||||
+265
-265
@@ -1704,189 +1704,189 @@
|
||||
"from the rule": "de la regla",
|
||||
"help.apache": "Licencia Apache 2.0",
|
||||
"help.appearance.assign": "Da a los cuerpos, caras o componentes seleccionados un color o un aspecto de material, con",
|
||||
"help.assembly.bom": "Lists the parts of the design or a component with their counts, by part number, and can save the list as CSV or JSON. Use it as the parts list for ordering and assembly.",
|
||||
"help.assembly.bom": "Lista las piezas del diseño o de un componente con sus cantidades, por número de pieza, y puede guardar la lista como CSV o JSON. Úsalo como lista de piezas para pedidos y ensamblaje.",
|
||||
"help.attributions": "Atribuciones (ATTRIBUTION.md)",
|
||||
"help.build": "Versión {version} · commit {commit} · compilada el {date}",
|
||||
"help.canvas.decal": "Places an image on a planar face of the model, like a sticker. Use it to show a label, logo or printed pattern on a part.",
|
||||
"help.canvas.edit": "Changes a canvas: its position, size, angle, opacity, mirroring, visibility or name. Use it to line up a reference image with the sketch you trace over it.",
|
||||
"help.canvas.insert": "Places a PNG or JPEG image on a plane or face as a see-through reference. Use it to trace a photo or drawing in a sketch, with the image scaled to a known size.",
|
||||
"help.component.break_link": "Cuts a linked component loose from its design file, keeping its bodies as they are. Use it when the part should no longer follow changes to the original file.",
|
||||
"help.component.capture_position": "Keeps the positions of parts you moved by hand, so they become where those parts are. Use it after dragging parts into place that no joint holds.",
|
||||
"help.component.create": "Adds a new, empty component to the design, inside the active component unless you choose another parent. Use it to give a new part of an assembly its own place for bodies and sketches.",
|
||||
"help.canvas.decal": "Coloca una imagen sobre una cara plana del modelo, como una pegatina. Úsalo para mostrar una etiqueta, un logotipo o un dibujo impreso en una pieza.",
|
||||
"help.canvas.edit": "Cambia un lienzo: su posición, tamaño, ángulo, opacidad, simetría, visibilidad o nombre. Úsalo para alinear una imagen de referencia con el boceto que dibujas sobre ella.",
|
||||
"help.canvas.insert": "Coloca una imagen PNG o JPEG en un plano o una cara como referencia translúcida. Úsalo para calcar una foto o un dibujo en un boceto, con la imagen escalada a un tamaño conocido.",
|
||||
"help.component.break_link": "Desvincula un componente enlazado de su archivo de diseño y conserva sus cuerpos tal como están. Úsalo cuando la pieza ya no deba seguir los cambios del archivo original.",
|
||||
"help.component.capture_position": "Conserva las posiciones de las piezas que moviste a mano, de modo que pasan a ser donde están ahora. Úsalo tras arrastrar a su sitio piezas que ninguna unión sujeta.",
|
||||
"help.component.create": "Añade un componente nuevo y vacío al diseño, dentro del componente activo salvo que elijas otro padre. Úsalo para dar a una pieza nueva de un ensamblaje su propio lugar para cuerpos y bocetos.",
|
||||
"help.component.finish_edit": "Guarda la pieza que estás editando en contexto, vuelve a su ensamblaje y actualiza el",
|
||||
"help.component.from_bodies": "Turns each selected body into a component of its own, named after the body. Use it when a design built as loose bodies should become an assembly whose parts can be joined and moved.",
|
||||
"help.component.insert_design": "Inserts another saved design as a component linked to its file, with its solid bodies placed as they are there. Use it to reuse a part in an assembly and pick up later changes with Update Links.",
|
||||
"help.component.properties": "Shows the volume, mass, centre of mass and moments of inertia of a component, using its bodies' materials. Use it to check weight and balance of an assembly.",
|
||||
"help.component.revert_position": "Puts parts you moved by hand back where they were, dropping moves that were not captured. Use it to undo trial moves in an assembly.",
|
||||
"help.component.update_links": "Reads the linked design files again and replaces bodies where they changed. Use it after editing a part that this assembly uses.",
|
||||
"help.config.configure": "Adds parameters, features, materials or appearances as columns of the configuration table. Use it to build variants of one design, such as sizes of a part.",
|
||||
"help.config.preview": "Checks that a row of the configuration table rebuilds, without changing the design or its history. Use it before switching to a variant you are not sure of.",
|
||||
"help.config.rules": "Shows the rules of the configuration table, its rows and which row is active. Use it to see how the variants of a design are set up.",
|
||||
"help.config.table": "Shows the configuration table: one row per variant, one column per parameter or feature, and whether the design still matches the active row. Use it to review the variants of a design.",
|
||||
"help.component.from_bodies": "Convierte cada cuerpo seleccionado en un componente propio, con el nombre del cuerpo. Úsalo cuando un diseño hecho con cuerpos sueltos deba pasar a ser un ensamblaje cuyas piezas se puedan unir y mover.",
|
||||
"help.component.insert_design": "Inserta otro diseño guardado como componente vinculado a su archivo, con sus cuerpos sólidos colocados como están allí. Úsalo para reutilizar una pieza en un ensamblaje y recoger los cambios posteriores con Actualizar vínculos.",
|
||||
"help.component.properties": "Muestra el volumen, la masa, el centro de masa y los momentos de inercia de un componente, según los materiales de sus cuerpos. Úsalo para comprobar el peso y el equilibrio de un ensamblaje.",
|
||||
"help.component.revert_position": "Devuelve a su sitio las piezas que moviste a mano y descarta los movimientos que no se capturaron. Úsalo para deshacer movimientos de prueba en un ensamblaje.",
|
||||
"help.component.update_links": "Vuelve a leer los archivos de diseño vinculados y reemplaza los cuerpos que cambiaron. Úsalo después de editar una pieza que usa este ensamblaje.",
|
||||
"help.config.configure": "Añade parámetros, operaciones, materiales o aspectos como columnas de la tabla de configuración. Úsalo para crear variantes de un diseño, como tamaños de una pieza.",
|
||||
"help.config.preview": "Comprueba que una fila de la tabla de configuración se reconstruye, sin cambiar el diseño ni su historial. Úsalo antes de cambiar a una variante de la que no estés seguro.",
|
||||
"help.config.rules": "Muestra las reglas de la tabla de configuración, sus filas y cuál está activa. Úsalo para ver cómo están definidas las variantes de un diseño.",
|
||||
"help.config.table": "Muestra la tabla de configuración: una fila por variante, una columna por parámetro u operación, y si el diseño sigue coincidiendo con la fila activa. Úsalo para revisar las variantes de un diseño.",
|
||||
"help.connect_note": "Reinicia cada asistente para que cargue el servidor de SolidCraft. Cada archivo se guardó como .bak antes de modificarlo.",
|
||||
"help.connect_title": "Conectar asistentes de IA",
|
||||
"help.construct.axis.edge": "Creates a construction axis along a straight edge or sketch line. Use it as the axis for a revolve, a circular pattern or a joint.",
|
||||
"help.construct.axis.normal_to_face": "Creates a construction axis through a point, square to a face. Use it as an axis that stands straight out of a surface.",
|
||||
"help.construct.axis.through_cylinder": "Creates a construction axis through the centre of a cylinder, cone or torus face, or a circular edge. Use it to turn or pattern features around a round part.",
|
||||
"help.construct.axis.two_planes": "Creates a construction axis where two planes or flat faces meet. Use it when the axis you need is the line between two faces.",
|
||||
"help.construct.axis.two_points": "Creates a construction axis through two points, vertices or sketch points. Use it for an axis that runs between two known positions.",
|
||||
"help.construct.plane.along_path": "Creates a construction plane square to an edge or curve, at a position along it. Use it to sketch a profile for a sweep or a section of a path.",
|
||||
"help.construct.axis.edge": "Crea un eje de construcción a lo largo de una arista recta o de una línea de boceto. Úsalo como eje de una revolución, un patrón circular o una unión.",
|
||||
"help.construct.axis.normal_to_face": "Crea un eje de construcción que pasa por un punto, perpendicular a una cara. Úsalo como un eje que sale recto de una superficie.",
|
||||
"help.construct.axis.through_cylinder": "Crea un eje de construcción por el centro de una cara cilíndrica, cónica o toroidal, o de una arista circular. Úsalo para girar o repetir operaciones alrededor de una pieza redonda.",
|
||||
"help.construct.axis.two_planes": "Crea un eje de construcción donde se cortan dos planos o caras planas. Úsalo cuando el eje que necesitas sea la línea entre dos caras.",
|
||||
"help.construct.axis.two_points": "Crea un eje de construcción por dos puntos, vértices o puntos de boceto. Úsalo para un eje que va entre dos posiciones conocidas.",
|
||||
"help.construct.plane.along_path": "Crea un plano de construcción perpendicular a una arista o curva, en una posición a lo largo de ella. Úsalo para dibujar el perfil de un barrido o una sección de una trayectoria.",
|
||||
"help.construct.plane.at_angle": "Crea un plano de construcción girado un ángulo respecto a un plano o cara, alrededor de un eje o arista. Activa «Usar solo la dirección del eje» para proyectar el eje sobre la base y pivotar alrededor de un punto de ese plano (el origen de la base cuando no se elige ninguno). Úsalo para bocetos inclinados, como un soporte angular.",
|
||||
"help.construct.plane.axis_point": "Creates a construction plane containing an axis and a point off that axis. Pick an origin or construction axis, a straight edge or sketch line, then a vertex, sketch point or construction point. A point on the axis cannot define a unique plane.",
|
||||
"help.construct.plane.midplane": "Creates a construction plane halfway between two planes or flat faces, or bisecting them where they meet at an angle. Use it as a symmetry plane for mirroring.",
|
||||
"help.construct.plane.offset": "Creates a construction plane parallel to a plane or flat face, at a distance or through a point. Use it to sketch at a set height above a face.",
|
||||
"help.construct.plane.perpendicular": "Creates a construction plane that holds a line or edge and stands square to a plane or face. Use it to sketch upright on a model along an edge.",
|
||||
"help.construct.plane.tangent": "Creates a construction plane that touches a cylinder, cone, sphere or torus at a point. Use it to sketch on the side of a round part.",
|
||||
"help.construct.plane.three_points": "Creates a construction plane through three points. Use it for a plane set by positions on the model, such as three corners.",
|
||||
"help.construct.plane.two_edges": "Creates a construction plane through two straight edges or lines that lie in one plane. Use it for a plane across a part, such as through two opposite edges.",
|
||||
"help.construct.point.along_path": "Creates a construction point at a position along an edge or curve. Use it as a reference partway along a path.",
|
||||
"help.construct.point.center": "Creates a construction point at the centre of a circular edge, sketch circle or arc, sphere or torus. Use it as a reference for holes, axes and joints.",
|
||||
"help.construct.point.edge_plane": "Creates a construction point where an edge or line passes through a plane or flat face. Use it to mark where a path crosses a plane.",
|
||||
"help.construct.point.three_planes": "Creates a construction point where three planes or flat faces meet. Use it as a corner reference, even where the model has no vertex.",
|
||||
"help.construct.point.two_edges": "Creates a construction point where two edges or lines meet, or come closest. Use it as a reference at a virtual corner.",
|
||||
"help.construct.point.vertex": "Creates a construction point on a vertex or sketch point. Use it as a reference that stays when the sketch or body around it is hidden.",
|
||||
"help.contact.check": "Lists the pairs of parts in contact sets that pass through each other in their current position. Use it to find collisions before you drive joints or run a motion study.",
|
||||
"help.contact.create": "Groups two or more parts into a contact set, whose bodies are kept from passing through each other while joints move. Use it for parts that should stop when they touch, such as a lever against its stop.",
|
||||
"help.contact.disable_all": "Turns contact off, so driven joints and motion studies no longer stop where parts touch. Use it to move parts freely again, or to keep a large assembly responsive.",
|
||||
"help.contact.edit": "Changes a contact set: the parts it holds, its name, or whether it is suppressed; it can also delete the set. Use it to adjust which parts are kept from passing through each other.",
|
||||
"help.contact.enable_all": "Puts every part of the assembly into one contact set, so no two parts can pass through each other while joints move. Use it for a quick check of a whole mechanism.",
|
||||
"help.contact.enable_sets": "Turns contact on for the contact sets you defined, so driven joints and motion studies stop where their parts would pass through each other. Use it to bring your sets back after turning contact off.",
|
||||
"help.contact.list": "Lists the contact sets of the design, the parts in each one and whether contact is on. Use it to check how contact is set up before you drive the assembly.",
|
||||
"help.document.inspect": "Shows an overview of the design: its components, bodies, sketches, features and parameters. Use it to get your bearings in a design you did not build yourself.",
|
||||
"help.document.units": "Changes the units the design shows lengths in, such as mm or inches. The geometry keeps its size; only the display and plain numbers follow.",
|
||||
"help.edit.checkpoint": "Remembers the design, the active sketch and the undo history as they are now. Use it before trying something risky that you may want to go back from.",
|
||||
"help.edit.restore_checkpoint": "Goes back to a checkpoint, undo history included. Use it to drop everything done since the checkpoint in one step.",
|
||||
"help.explode.create": "Creates an exploded view that pushes the parts away from the assembly's centre, or by the moves you set. Use it to show how an assembly goes together, for instructions or presentations.",
|
||||
"help.construct.plane.axis_point": "Crea un plano de construcción que contiene un eje y un punto fuera de ese eje. Elige un origen o un eje de construcción, una arista recta o una línea de boceto, y después un vértice, un punto de boceto o un punto de construcción. Un punto del eje no define un plano único.",
|
||||
"help.construct.plane.midplane": "Crea un plano de construcción a medio camino entre dos planos o caras planas, o que los biseca donde se encuentran en ángulo. Úsalo como plano de simetría para un espejo.",
|
||||
"help.construct.plane.offset": "Crea un plano de construcción paralelo a un plano o una cara plana, a una distancia o por un punto. Úsalo para dibujar a una altura fija sobre una cara.",
|
||||
"help.construct.plane.perpendicular": "Crea un plano de construcción que contiene una línea o arista y es perpendicular a un plano o una cara. Úsalo para dibujar en vertical sobre un modelo a lo largo de una arista.",
|
||||
"help.construct.plane.tangent": "Crea un plano de construcción que toca un cilindro, cono, esfera o toro en un punto. Úsalo para dibujar en el lado de una pieza redonda.",
|
||||
"help.construct.plane.three_points": "Crea un plano de construcción por tres puntos. Úsalo para un plano definido por posiciones del modelo, como tres esquinas.",
|
||||
"help.construct.plane.two_edges": "Crea un plano de construcción por dos aristas rectas o líneas que están en un mismo plano. Úsalo para un plano que cruza una pieza, por ejemplo por dos aristas opuestas.",
|
||||
"help.construct.point.along_path": "Crea un punto de construcción en una posición a lo largo de una arista o curva. Úsalo como referencia a mitad de una trayectoria.",
|
||||
"help.construct.point.center": "Crea un punto de construcción en el centro de una arista circular, un círculo o arco de boceto, una esfera o un toro. Úsalo como referencia para agujeros, ejes y uniones.",
|
||||
"help.construct.point.edge_plane": "Crea un punto de construcción donde una arista o línea atraviesa un plano o una cara plana. Úsalo para marcar dónde una trayectoria cruza un plano.",
|
||||
"help.construct.point.three_planes": "Crea un punto de construcción donde se encuentran tres planos o caras planas. Úsalo como referencia de esquina, incluso donde el modelo no tiene vértice.",
|
||||
"help.construct.point.two_edges": "Crea un punto de construcción donde se cortan dos aristas o líneas, o donde están más cerca. Úsalo como referencia en una esquina virtual.",
|
||||
"help.construct.point.vertex": "Crea un punto de construcción sobre un vértice o un punto de boceto. Úsalo como referencia que permanece cuando se oculta el boceto o el cuerpo que lo rodea.",
|
||||
"help.contact.check": "Lista los pares de piezas de los conjuntos de contacto que se atraviesan en su posición actual. Úsalo para encontrar colisiones antes de accionar uniones o ejecutar un estudio de movimiento.",
|
||||
"help.contact.create": "Agrupa dos o más piezas en un conjunto de contacto, cuyos cuerpos no pueden atravesarse mientras las uniones se mueven. Úsalo para piezas que deben detenerse al tocarse, como una palanca contra su tope.",
|
||||
"help.contact.disable_all": "Desactiva el contacto, de modo que las uniones accionadas y los estudios de movimiento ya no se detienen donde las piezas se tocan. Úsalo para mover las piezas con libertad o para mantener ágil un ensamblaje grande.",
|
||||
"help.contact.edit": "Cambia un conjunto de contacto: las piezas que contiene, su nombre o si está desactivado; también puede eliminar el conjunto. Úsalo para ajustar qué piezas no pueden atravesarse.",
|
||||
"help.contact.enable_all": "Pone todas las piezas del ensamblaje en un único conjunto de contacto, de modo que ningún par de piezas se atraviese mientras las uniones se mueven. Úsalo para una comprobación rápida de todo un mecanismo.",
|
||||
"help.contact.enable_sets": "Activa el contacto de los conjuntos de contacto que definiste, de modo que las uniones accionadas y los estudios de movimiento se detienen donde sus piezas se atravesarían. Úsalo para recuperar tus conjuntos tras desactivar el contacto.",
|
||||
"help.contact.list": "Lista los conjuntos de contacto del diseño, las piezas de cada uno y si el contacto está activado. Úsalo para comprobar cómo está configurado el contacto antes de accionar el ensamblaje.",
|
||||
"help.document.inspect": "Muestra un resumen del diseño: sus componentes, cuerpos, bocetos, operaciones y parámetros. Úsalo para orientarte en un diseño que no construiste tú.",
|
||||
"help.document.units": "Cambia las unidades en que el diseño muestra las longitudes, como mm o pulgadas. La geometría mantiene su tamaño; solo cambian la visualización y los números sin unidad.",
|
||||
"help.edit.checkpoint": "Recuerda el diseño, el boceto activo y el historial de deshacer tal como están ahora. Úsalo antes de probar algo arriesgado de lo que quizá quieras volver.",
|
||||
"help.edit.restore_checkpoint": "Vuelve a un punto de control, historial de deshacer incluido. Úsalo para descartar de una vez todo lo hecho desde el punto de control.",
|
||||
"help.explode.create": "Crea una vista explosionada que aleja las piezas del centro del ensamblaje, o según los movimientos que indiques. Úsalo para mostrar cómo se monta un ensamblaje, en instrucciones o presentaciones.",
|
||||
"help.face.delete": "Elimina las caras seleccionadas y deja que las caras vecinas cierren el hueco, o deja",
|
||||
"help.file.insert_mesh": "Adds a 3MF, STL, OBJ, PLY or glTF file to the design as mesh bodies in a new component. Use it to place a downloaded or scanned model beside your design as a reference.",
|
||||
"help.file.insert_step": "Adds a STEP, IGES, FreeCAD or Rhino file to the design as solid bodies in a new component; an assembly's parts become nested components. Use it to bring in models from suppliers or other CAD programs.",
|
||||
"help.file.save_mesh": "Saves bodies as an STL, 3MF or OBJ mesh, with the smoothness of curved faces you choose. Use it to prepare parts for 3D printing or for programs that read meshes.",
|
||||
"help.file.send_to_slicer": "Saves the selected bodies as a 3MF file and opens it in the slicer you choose. Use it to go from the model to printing in one step.",
|
||||
"help.file.insert_mesh": "Añade un archivo 3MF, STL, OBJ, PLY o glTF al diseño como cuerpos de malla en un componente nuevo. Úsalo para colocar un modelo descargado o escaneado junto a tu diseño como referencia.",
|
||||
"help.file.insert_step": "Añade un archivo STEP, IGES, FreeCAD o Rhino al diseño como cuerpos sólidos en un componente nuevo; las piezas de un ensamblaje pasan a ser componentes anidados. Úsalo para traer modelos de proveedores o de otros programas de CAD.",
|
||||
"help.file.save_mesh": "Guarda cuerpos como una malla STL, 3MF u OBJ, con la suavidad de las caras curvas que elijas. Úsalo para preparar piezas para la impresión 3D o para programas que leen mallas.",
|
||||
"help.file.send_to_slicer": "Guarda los cuerpos seleccionados como un archivo 3MF y lo abre en el laminador que elijas. Úsalo para pasar del modelo a la impresión en un solo paso.",
|
||||
"help.font_details": "La interfaz utiliza las fuentes integradas de egui (Ubuntu Light y Hack, bajo las licencias Ubuntu Font Licence y MIT/Bitstream Vera; Noto Emoji y la fuente de iconos emoji, bajo OFL y MIT). El texto de los bocetos utiliza Liberation Sans (SIL OFL 1.1). El paquete opcional de fuentes de The Crafting Apps, craft-fonts (BIZ UDPGothic, Shippori Mincho, BIZ UDMincho, Noto Sans CJK SC, Noto Sans Arabic; SIL OFL 1.1), no se incluye en las compilaciones de SolidCraft.",
|
||||
"help.fonts": "Fuentes",
|
||||
"help.frame.member": "Places a profile, such as a tube or an aluminium extrusion, along the lines of a frame sketch, one member per line. Use it to build frames, racks and welded structures.",
|
||||
"help.inspect.accessibility": "Colours the faces a tool can reach from one direction, and those it cannot. Use it to check a part for machining or moulding from that side.",
|
||||
"help.inspect.center_of_mass": "Shows the centre of mass of bodies, each on its own and all together, at uniform density. Use it to check balance and where a part will tip.",
|
||||
"help.inspect.colored_components": "Gives each component its own temporary colour, without changing appearances. Use it to tell the parts of an assembly apart at a glance.",
|
||||
"help.inspect.compare": "Compares two bodies and shows where one has material the other does not, with volume and deviation. Use it to check a changed or imported part against the original.",
|
||||
"help.inspect.continuity": "Checks how smoothly faces meet along their edges: gaps, kinks or curvature jumps, and shades the seams. Use it to find where surfaces do not join cleanly.",
|
||||
"help.inspect.curvature_comb": "Draws combs along curves, edges or faces whose teeth show how strongly they bend. Use it to spot flat spots, kinks and uneven curvature.",
|
||||
"help.inspect.curvature_map": "Colours faces by how strongly they curve, red where the radius is small. Use it to find tight spots and to judge how smooth a surface is.",
|
||||
"help.inspect.draft": "Colours faces by their draft angle to a pull direction, marking those with too little. Use it to check a part before moulding or casting.",
|
||||
"help.inspect.environment_map": "Shows the model with a reflective, mirror-like finish. Use it to judge the flow of surfaces by the way reflections run across them.",
|
||||
"help.inspect.interference": "Finds bodies that overlap and shows each overlap with its volume. Use it to check an assembly for parts that collide.",
|
||||
"help.inspect.isocurve": "Draws the isoparametric curves of faces, the grid the surface is built on. Use it to see how a surface flows and where it bunches up.",
|
||||
"help.inspect.measure": "Measures lengths, distances, angles, areas and radii between what you pick, or the volume and mass of bodies. Use it to check sizes and clearances.",
|
||||
"help.inspect.minimum_radius": "Finds the smallest radius of curvature of curves, edges or faces, and where it is. Use it to check that a tool or nozzle can follow the shape.",
|
||||
"help.inspect.section": "Cuts the view open along a plane and hatches the cut faces, without changing the model. Use it to look inside parts and assemblies.",
|
||||
"help.inspect.zebra": "Shows black and white stripes reflected on the model's faces. Use it to judge smoothness: stripes that break or kink at an edge show a poor transition.",
|
||||
"help.joint.as_built": "Joins two parts where they already are, without moving either one, and sets how they may still move. Use it for parts you have already placed in their final position.",
|
||||
"help.joint.cam": "Links a turning cam to a follower, so the follower slides or swings as the cam's outline passes under it. Use it for cams, eccentrics and valve drives.",
|
||||
"help.joint.create": "Joins two parts at the joint origins you pick and moves the second part into place; the joint type sets how they may still move. Use it to build an assembly whose parts move like the real mechanism.",
|
||||
"help.joint.drive": "Sets a joint's angle or distance and moves the parts with it, within its limits; linked joints and closed loops follow. Use it to check that a mechanism moves as intended.",
|
||||
"help.joint.gear": "Links two turning joints with a gear ratio, so driving one turns the other. Use it for spur and ring gears, with the ratio from pitch radii or tooth counts.",
|
||||
"help.joint.limits": "Sets how far a joint may turn or slide, as a minimum and a maximum, or clears those limits. Use it to keep a hinge, slider or lever within its real range of travel.",
|
||||
"help.joint.motion_link": "Couples two joints with a ratio and an offset, so driving one moves the other. Use it for a fixed relation between joints that Gear, Rack and Pinion or Screw do not cover.",
|
||||
"help.joint.origin": "Places a named joint origin on a part: at the centre of a face or round end, the middle of an edge, a corner or a point. Use it to prepare where joints attach; one picked on a face follows it when the part changes size.",
|
||||
"help.joint.rack_pinion": "Links a turning pinion to a sliding rack, so the rack moves by the length of pitch circle the pinion rolls through. Use it for rack drives, steering and linear stages.",
|
||||
"help.joint.reach": "Moves a point on a part toward a target by changing the joints on its chain, within their limits. Use it to pose a mechanism by where its end should be, such as the tip of a robot arm.",
|
||||
"help.joint.rigid_group": "Locks the selected parts together as they are, so they move as one. Use it for parts that belong together and have no motion between them.",
|
||||
"help.joint.screw": "Links turning and sliding by a pitch, so each turn advances by that distance. Use it for lead screws, bolts and threaded spindles.",
|
||||
"help.layout.apply": "Apply a saved layout to the current workspace. Retained editors keep their drafts.",
|
||||
"help.layout.get": "Read the committed layout and discover registered workspaces.",
|
||||
"help.layout.reset": "Restore the current workspace's registered default layout. User presets remain available.",
|
||||
"help.layout.save": "Save the complete layout under a name. Replacing a user preset requires explicit overwrite permission.",
|
||||
"help.layout.workspace.select": "Select a registered layout workspace and remember the outgoing layout.",
|
||||
"help.library.apply": "Applies a material or appearance from a local library file to bodies, faces or components. Use it to reuse materials you saved from another design.",
|
||||
"help.library.export": "Saves the design's materials and appearances to a library file. Use it to share them or reuse them in other designs.",
|
||||
"help.library.inspect": "Checks a library file and lists its materials and appearances, without changing the design. Use it to see what a library holds before applying it.",
|
||||
"help.frame.member": "Coloca un perfil, como un tubo o un perfil de aluminio extruido, a lo largo de las líneas de un boceto de estructura, un miembro por línea. Úsalo para construir bastidores, estanterías y estructuras soldadas.",
|
||||
"help.inspect.accessibility": "Colorea las caras a las que una herramienta puede llegar desde una dirección y las que no. Úsalo para comprobar una pieza para mecanizado o moldeo desde ese lado.",
|
||||
"help.inspect.center_of_mass": "Muestra el centro de masa de los cuerpos, cada uno por separado y todos juntos, con densidad uniforme. Úsalo para comprobar el equilibrio y dónde volcará una pieza.",
|
||||
"help.inspect.colored_components": "Da a cada componente su propio color temporal, sin cambiar los aspectos. Úsalo para distinguir de un vistazo las piezas de un ensamblaje.",
|
||||
"help.inspect.compare": "Compara dos cuerpos y muestra dónde uno tiene material que el otro no, con volumen y desviación. Úsalo para comprobar una pieza modificada o importada con el original.",
|
||||
"help.inspect.continuity": "Comprueba con qué suavidad se encuentran las caras a lo largo de sus aristas: huecos, quiebros o saltos de curvatura, y sombrea las uniones. Úsalo para encontrar dónde las superficies no se unen limpiamente.",
|
||||
"help.inspect.curvature_comb": "Dibuja peines a lo largo de curvas, aristas o caras, cuyos dientes muestran cuánto se curvan. Úsalo para detectar zonas planas, quiebros y curvatura irregular.",
|
||||
"help.inspect.curvature_map": "Colorea las caras según cuánto se curvan, en rojo donde el radio es pequeño. Úsalo para encontrar zonas cerradas y para juzgar lo suave que es una superficie.",
|
||||
"help.inspect.draft": "Colorea las caras según su ángulo de desmoldeo respecto a una dirección de extracción, y marca las que tienen muy poco. Úsalo para comprobar una pieza antes del moldeo o la fundición.",
|
||||
"help.inspect.environment_map": "Muestra el modelo con un acabado reflectante, como un espejo. Úsalo para juzgar el fluir de las superficies por cómo corren los reflejos sobre ellas.",
|
||||
"help.inspect.interference": "Encuentra cuerpos que se solapan y muestra cada solapamiento con su volumen. Úsalo para comprobar si un ensamblaje tiene piezas que chocan.",
|
||||
"help.inspect.isocurve": "Dibuja las curvas isoparamétricas de las caras, la malla sobre la que se construye la superficie. Úsalo para ver cómo fluye una superficie y dónde se amontona.",
|
||||
"help.inspect.measure": "Mide longitudes, distancias, ángulos, áreas y radios entre lo que elijas, o el volumen y la masa de los cuerpos. Úsalo para comprobar tamaños y holguras.",
|
||||
"help.inspect.minimum_radius": "Encuentra el menor radio de curvatura de curvas, aristas o caras, y dónde está. Úsalo para comprobar que una herramienta o una boquilla puede seguir la forma.",
|
||||
"help.inspect.section": "Corta la vista a lo largo de un plano y raya las caras cortadas, sin cambiar el modelo. Úsalo para mirar dentro de piezas y ensamblajes.",
|
||||
"help.inspect.zebra": "Muestra rayas blancas y negras reflejadas en las caras del modelo. Úsalo para juzgar la suavidad: las rayas que se rompen o se doblan en una arista indican una mala transición.",
|
||||
"help.joint.as_built": "Une dos piezas donde ya están, sin mover ninguna, y define cómo pueden seguir moviéndose. Úsalo para piezas que ya colocaste en su posición final.",
|
||||
"help.joint.cam": "Enlaza una leva giratoria con un seguidor, de modo que el seguidor se desliza o oscila cuando el contorno de la leva pasa por debajo. Úsalo para levas, excéntricas y accionamientos de válvulas.",
|
||||
"help.joint.create": "Une dos piezas en los orígenes de unión que elijas y mueve la segunda pieza a su sitio; el tipo de unión define cómo pueden seguir moviéndose. Úsalo para construir un ensamblaje cuyas piezas se muevan como el mecanismo real.",
|
||||
"help.joint.drive": "Fija el ángulo o la distancia de una unión y mueve las piezas con ella, dentro de sus límites; las uniones enlazadas y los lazos cerrados la siguen. Úsalo para comprobar que un mecanismo se mueve como se pretende.",
|
||||
"help.joint.gear": "Enlaza dos uniones giratorias con una relación de engranaje, de modo que mover una hace girar la otra. Úsalo para engranajes rectos y de corona, con la relación a partir de los radios primitivos o del número de dientes.",
|
||||
"help.joint.limits": "Fija hasta dónde puede girar o deslizarse una unión, con un mínimo y un máximo, o quita esos límites. Úsalo para mantener una bisagra, una guía o una palanca dentro de su recorrido real.",
|
||||
"help.joint.motion_link": "Acopla dos uniones con una relación y un desfase, de modo que mover una mueve la otra. Úsalo para una relación fija entre uniones que Engranaje, Cremallera y piñón o Tornillo no cubren.",
|
||||
"help.joint.origin": "Coloca un origen de unión con nombre en una pieza: en el centro de una cara o de un extremo redondo, en el medio de una arista, en una esquina o en un punto. Úsalo para preparar dónde se acoplan las uniones; el elegido en una cara la sigue cuando la pieza cambia de tamaño.",
|
||||
"help.joint.rack_pinion": "Enlaza un piñón giratorio con una cremallera deslizante, de modo que la cremallera se mueve la longitud del círculo primitivo que recorre el piñón. Úsalo para accionamientos de cremallera, dirección y mesas lineales.",
|
||||
"help.joint.reach": "Mueve un punto de una pieza hacia un objetivo cambiando las uniones de su cadena, dentro de sus límites. Úsalo para posicionar un mecanismo según dónde deba estar su extremo, como la punta de un brazo robótico.",
|
||||
"help.joint.rigid_group": "Bloquea las piezas seleccionadas tal como están, de modo que se muevan como una sola. Úsalo para piezas que van juntas y no tienen movimiento entre ellas.",
|
||||
"help.joint.screw": "Enlaza giro y deslizamiento mediante un paso, de modo que cada vuelta avanza esa distancia. Úsalo para husillos, tornillos y ejes roscados.",
|
||||
"help.layout.apply": "Aplica una disposición guardada al espacio de trabajo actual. Los editores retenidos conservan sus borradores.",
|
||||
"help.layout.get": "Lee la disposición confirmada y descubre los espacios de trabajo registrados.",
|
||||
"help.layout.reset": "Restaura la disposición predeterminada registrada del espacio de trabajo actual. Los ajustes del usuario siguen disponibles.",
|
||||
"help.layout.save": "Guarda la disposición completa con un nombre. Reemplazar un ajuste del usuario exige permiso explícito de sobrescritura.",
|
||||
"help.layout.workspace.select": "Selecciona un espacio de trabajo de disposición registrado y recuerda la disposición que se abandona.",
|
||||
"help.library.apply": "Aplica un material o un aspecto de un archivo de biblioteca local a cuerpos, caras o componentes. Úsalo para reutilizar materiales que guardaste desde otro diseño.",
|
||||
"help.library.export": "Guarda los materiales y aspectos del diseño en un archivo de biblioteca. Úsalo para compartirlos o reutilizarlos en otros diseños.",
|
||||
"help.library.inspect": "Comprueba un archivo de biblioteca y lista sus materiales y aspectos, sin cambiar el diseño. Úsalo para ver qué contiene una biblioteca antes de aplicarla.",
|
||||
"help.licences": "Licencias",
|
||||
"help.material.assign": "Define de qué están hechos los cuerpos seleccionados, como acero, aluminio o ABS. Usa",
|
||||
"help.material.properties.validate": "Checks a material data card for consistent numbers and missing values. Use it before relying on the data for mass or stiffness.",
|
||||
"help.mesh.convert": "Rebuilds a mesh body, such as an STL, as an editable solid with flat and cylindrical faces. Use it to modify imported mechanical parts like a modelled body.",
|
||||
"help.material.properties.validate": "Comprueba que una ficha de datos de material tiene números coherentes y no le faltan valores. Úsalo antes de fiarte de los datos para la masa o la rigidez.",
|
||||
"help.mesh.convert": "Reconstruye un cuerpo de malla, como un STL, en un sólido editable con caras planas y cilíndricas. Úsalo para modificar piezas mecánicas importadas como un cuerpo modelado.",
|
||||
"help.mit": "Licencia MIT",
|
||||
"help.motion.study": "Sets joint values at steps along a timeline and plays them back as an animation. Use it to watch a mechanism move through a sequence and check clearances along the way.",
|
||||
"help.motion.trace": "Traces the path a point on a part follows while a motion study plays or a joint is driven, and keeps it as a 3D sketch curve when you confirm. Use it to see where a mechanism reaches, or to build on its path.",
|
||||
"help.motion.study": "Fija valores de unión en pasos a lo largo de una línea de tiempo y los reproduce como una animación. Úsalo para ver cómo se mueve un mecanismo en una secuencia y comprobar las holguras por el camino.",
|
||||
"help.motion.trace": "Traza el camino que sigue un punto de una pieza mientras se reproduce un estudio de movimiento o se acciona una unión, y lo conserva como una curva de boceto 3D al confirmar. Úsalo para ver hasta dónde llega un mecanismo o para construir sobre su trayectoria.",
|
||||
"help.notice": "AVISO",
|
||||
"help.occurrence.ground": "Fixes a part in place, or frees it again, so that joints move the other parts around it. Use it for the frame or base that the rest of the assembly is built on.",
|
||||
"help.occurrence.ground": "Fija una pieza en su sitio, o la libera de nuevo, para que las uniones muevan las demás piezas a su alrededor. Úsalo para el bastidor o la base sobre la que se construye el resto del ensamblaje.",
|
||||
"help.occurrence.move": "Mueve una pieza de ensamblaje solo por las libertades permitidas por sus uniones. Selecciona una pieza",
|
||||
"help.panel.activate": "Select an open panel tab without requesting keyboard focus.",
|
||||
"help.panel.close": "Close a panel through its content lifecycle guard. Its placement is remembered.",
|
||||
"help.panel.collapse": "Collapse or expand a panel section while retaining its requested dimensions.",
|
||||
"help.panel.dismiss": "Dismiss the temporary view of a collapsed panel.",
|
||||
"help.panel.float": "Move a panel into an explicitly positioned floating section.",
|
||||
"help.panel.focus": "Focus a panel, reopening its retained state and expanding its section when needed.",
|
||||
"help.panel.list": "Read registered panel kinds, committed instances, active tabs, availability and host capabilities.",
|
||||
"help.panel.move": "Move a panel into a new section or join an existing tab group.",
|
||||
"help.panel.native_close": "Return a native panel section to its remembered dock without cancelling its content.",
|
||||
"help.panel.open": "Open a panel kind with an explicit instance identity and placement for a new instance.",
|
||||
"help.panel.peek": "Temporarily show a collapsed panel without changing its saved size or collapse state.",
|
||||
"help.panel.popout": "Move a panel to a native host when supported. Browser hosts use a floating section.",
|
||||
"help.panel.reset_pair": "Restore an adjacent dock pair's default size ratio within its shared bounds.",
|
||||
"help.panel.resize": "Set a panel section's outer width and height within every tab's bounds.",
|
||||
"help.panel.resize_pair": "Resize adjacent dock sections together while conserving their shared extent.",
|
||||
"help.panel.activate": "Selecciona una pestaña de panel abierta sin pedir el foco del teclado.",
|
||||
"help.panel.close": "Cierra un panel mediante la protección del ciclo de vida de su contenido. Se recuerda su ubicación.",
|
||||
"help.panel.collapse": "Contrae o expande una sección de panel conservando las dimensiones solicitadas.",
|
||||
"help.panel.dismiss": "Descarta la vista temporal de un panel contraído.",
|
||||
"help.panel.float": "Mueve un panel a una sección flotante con posición explícita.",
|
||||
"help.panel.focus": "Da el foco a un panel, reabre su estado retenido y expande su sección cuando hace falta.",
|
||||
"help.panel.list": "Lee los tipos de panel registrados, las instancias confirmadas, las pestañas activas, la disponibilidad y las capacidades del anfitrión.",
|
||||
"help.panel.move": "Mueve un panel a una sección nueva o lo une a un grupo de pestañas existente.",
|
||||
"help.panel.native_close": "Devuelve una sección de panel nativa a su acoplamiento recordado sin cancelar su contenido.",
|
||||
"help.panel.open": "Abre un tipo de panel con una identidad de instancia explícita y una ubicación para una instancia nueva.",
|
||||
"help.panel.peek": "Muestra temporalmente un panel contraído sin cambiar su tamaño guardado ni su estado de contracción.",
|
||||
"help.panel.popout": "Mueve un panel a un anfitrión nativo cuando se admite. Los anfitriones de navegador usan una sección flotante.",
|
||||
"help.panel.reset_pair": "Restaura la proporción de tamaño predeterminada de un par de acoplamientos adyacentes dentro de sus límites compartidos.",
|
||||
"help.panel.resize": "Fija el ancho y el alto exteriores de una sección de panel dentro de los límites de cada pestaña.",
|
||||
"help.panel.resize_pair": "Redimensiona juntas secciones de acoplamiento adyacentes conservando su extensión compartida.",
|
||||
"help.parameters.change": "Abre la tabla de valores y expresiones con nombre que controlan las dimensiones del",
|
||||
"help.parameters.export": "Saves the design's parameters as CSV or JSON. Use it to edit them in a spreadsheet or move them to another design.",
|
||||
"help.parameters.graph": "Shows which parameters and features use which others, and any loops or errors among them. Use it to see what a change to a parameter will affect.",
|
||||
"help.parameters.import": "Reads parameters from CSV or JSON into the design, all or none of them. Use it to bring in values from a spreadsheet or another design.",
|
||||
"help.parameters.move": "Moves a user parameter before or after another in the list. Use it to keep related parameters together.",
|
||||
"help.parts.fastener": "Adds a standard screw, bolt, nut, washer, pin or bearing in the size you pick. Placed on a hole, it seats in the hole with a joint, so you need not model fasteners yourself.",
|
||||
"help.parts.insert": "Inserts a standard part in the family, size and length you pick. Placed on the rim or wall of a hole, it seats on the hole with a rigid joint.",
|
||||
"help.parts.library": "Opens the standard parts: screws, bolts, nuts, washers, set screws, dowel pins and bearings in standard sizes. Use it to add a standard part instead of modelling it yourself.",
|
||||
"help.parts.resize": "Changes the size or length of an inserted standard part and rebuilds it; its joints keep it seated. Use it when a screw turns out too long or a hole needs another size.",
|
||||
"help.plastic.assign_rule": "Assigns a plastic rule to bodies, so their plastic features take its draft and clearance as defaults. Use it to set up a moulded part once for all its features.",
|
||||
"help.plastic.boss": "Adds a screw boss on a face: a post with an optional hole, draft, root fillet and supporting ribs. Use it for screw points in moulded or printed housings.",
|
||||
"help.parameters.export": "Guarda los parámetros del diseño como CSV o JSON. Úsalo para editarlos en una hoja de cálculo o pasarlos a otro diseño.",
|
||||
"help.parameters.graph": "Muestra qué parámetros y operaciones usan a cuáles otros, y los lazos o errores que haya entre ellos. Úsalo para ver qué afectará un cambio en un parámetro.",
|
||||
"help.parameters.import": "Lee parámetros de un CSV o JSON al diseño, todos o ninguno. Úsalo para traer valores de una hoja de cálculo o de otro diseño.",
|
||||
"help.parameters.move": "Mueve un parámetro de usuario antes o después de otro en la lista. Úsalo para mantener juntos los parámetros relacionados.",
|
||||
"help.parts.fastener": "Añade un tornillo, perno, tuerca, arandela, pasador o rodamiento estándar del tamaño que elijas. Colocado sobre un agujero, se asienta en él con una unión, así que no necesitas modelar los elementos de fijación.",
|
||||
"help.parts.insert": "Inserta una pieza estándar de la familia, el tamaño y la longitud que elijas. Colocada en el borde o la pared de un agujero, se asienta en él con una unión rígida.",
|
||||
"help.parts.library": "Abre las piezas estándar: tornillos, pernos, tuercas, arandelas, tornillos sin cabeza, pasadores cilíndricos y rodamientos en tamaños estándar. Úsalo para añadir una pieza estándar en lugar de modelarla tú.",
|
||||
"help.parts.resize": "Cambia el tamaño o la longitud de una pieza estándar insertada y la reconstruye; sus uniones la mantienen asentada. Úsalo cuando un tornillo resulta demasiado largo o un agujero necesita otro tamaño.",
|
||||
"help.plastic.assign_rule": "Asigna una regla de plástico a cuerpos, de modo que sus operaciones de plástico toman su desmoldeo y holgura como valores por defecto. Úsalo para configurar una pieza moldeada una sola vez para todas sus operaciones.",
|
||||
"help.plastic.boss": "Añade una torreta para tornillo en una cara: un poste con agujero opcional, desmoldeo, redondeo en la base y nervios de apoyo. Úsalo para los puntos de tornillo en carcasas moldeadas o impresas.",
|
||||
"help.plastic.lip": "Adds a lip or a matching groove along the rim of a shelled body. Use it so that two housing halves locate on each other and close tightly.",
|
||||
"help.plastic.manage_rules": "Creates and edits plastic rules: material, wall thickness, radii, clearance and draft. Use them to keep the features of a moulded part consistent.",
|
||||
"help.plastic.rest": "Adds a rest on a face: a round or rectangular pad, solid or hollow, with draft. Use it as a support or standoff in a moulded housing.",
|
||||
"help.plastic.snap_fit": "Adds a snap-fit hook on a face, with its length, thickness and catch. Use it to clip parts together without screws.",
|
||||
"help.plastic.manage_rules": "Crea y edita reglas de plástico: material, espesor de pared, radios, holgura y desmoldeo. Úsalas para mantener coherentes las operaciones de una pieza moldeada.",
|
||||
"help.plastic.rest": "Añade un apoyo en una cara: un taco redondo o rectangular, macizo o hueco, con desmoldeo. Úsalo como soporte o separador en una carcasa moldeada.",
|
||||
"help.plastic.snap_fit": "Añade un gancho de encaje a presión en una cara, con su longitud, espesor y resalte. Úsalo para unir piezas sin tornillos.",
|
||||
"help.pointcloud.insert": "Inserta un escaneo PLY, XYZ o PTS como nube de puntos junto al modelo. Úsala como",
|
||||
"help.sheet.convert": "Turns a plate or shelled body of even thickness into a sheet metal body, with bends at the edges you pick. Use it to make an existing part unfoldable.",
|
||||
"help.sheet.export_bend_table": "Saves the bend table of a sheet metal body as CSV or JSON: angles, radii and bend positions in the flat. Use it for the press brake or the workshop.",
|
||||
"help.sheet.export_dxf": "Saves the flat pattern as a DXF, with outlines, bend lines and optional bend notes. Use it for laser, plasma or waterjet cutting.",
|
||||
"help.sheet.flange": "Adds a flange: a base plate from a sketch, a wall along an open sketch contour, or a bent wall on sheet edges. Use it to build up sheet metal parts.",
|
||||
"help.sheet.flat_pattern": "Creates the flat pattern of a sheet metal body, with its size, cut-outs and bend lines. Use it to check the blank before you cut it.",
|
||||
"help.sheet.fold": "Bends a sheet along a sketch line by an angle and radius. Use it to fold a flat sheet after cutting features into it.",
|
||||
"help.sheet.hem": "Folds a sheet edge back on itself. Use it for safe, stiff edges without sharp burrs.",
|
||||
"help.sheet.manage_rules": "Creates and edits sheet metal rules: thickness, bend radius, K-factor, reliefs and gaps. Use them to match the material and tools of your workshop.",
|
||||
"help.sheet.path_flange": "Adds a chain of flanges along a sheet edge, following an open chain of sketch lines. Use it for profiles such as a U or Z shape in one step.",
|
||||
"help.sheet.perforate": "Adds a field of holes over the whole flat sheet, in a staggered or square pattern. Use it for vents, grilles and lighter panels.",
|
||||
"help.sheet.refold": "Folds an unfolded sheet metal body back up. Use it after adding features to the flat sheet.",
|
||||
"help.sheet.unfold": "Unfolds all bends of a sheet metal body. Use it to add holes or cuts that have to cross a bend, then refold.",
|
||||
"help.sketch.arc.center_point": "Draws a circular arc around a centre point, from a start point to an end point. Use it when the arc's centre is known, such as a radius around a hole or a pivot.",
|
||||
"help.sketch.arc.tangent": "Draws an arc that starts at the end of a line or arc and continues tangent to it. Use it to carry on a chain with a smooth bend instead of a corner.",
|
||||
"help.sketch.arc.three_point": "Draws an arc from a start point to an end point through a third point. Use it when the arc has to pass through given points rather than around a known centre.",
|
||||
"help.sketch.arc3d": "Draws an exact circular arc in space through three points, with 3D Sketch on. Use it for bends in paths and guide rails that leave the sketch plane.",
|
||||
"help.sketch.auto_constrain": "Adds the constraints the sketch nearly has already, such as horizontal, parallel or coincident, then dimensions it until it is fully defined. Use it to lock a roughly drawn sketch in one step.",
|
||||
"help.sketch.auto_constrain_from_datum": "Works like AutoConstrain, but measures the positions from a datum point you pick instead of the origin. Use it when the part is laid out from one reference point, such as a corner or a hole.",
|
||||
"help.sketch.blend_curve": "Joins the ends of two curves with a smooth spline that is tangent to both, or also curvature continuous if you choose. Use it to bridge a gap between curves without a kink.",
|
||||
"help.sketch.break": "Splits a curve into pieces where other curves cross it, or at points you place on it. Use it when part of a curve needs its own constraint or should be deleted on its own.",
|
||||
"help.sketch.cancel": "Leaves the sketch and discards everything changed since it was created or opened for editing. Undo brings the changes back.",
|
||||
"help.sketch.centerline": "Switches lines between normal lines and centerlines, axes that profiles leave out. Use a centerline as the axis for a revolve, a mirror or a symmetry constraint.",
|
||||
"help.sketch.chamfer.distance_angle": "Bevels the corner between two lines, set by a distance along the first line and an angle. Use it when a drawing gives the chamfer as a length and an angle, such as 2 mm × 30°.",
|
||||
"help.sketch.chamfer.equal_distance": "Bevels the corner between two lines the same distance back along both. Use it for the usual 45° chamfer on an outline.",
|
||||
"help.sketch.chamfer.two_distance": "Bevels the corner between two lines, set by a separate distance along each line. Use it for chamfers that are not 45°, given as two lengths.",
|
||||
"help.sketch.circle.center": "Draws a circle from its centre and its diameter. Use it for holes, bosses and other round features whose centre is known.",
|
||||
"help.sketch.circle.three_point": "Draws a circle through three points. Use it when the circle has to pass through given points, for example of existing geometry.",
|
||||
"help.sketch.circle.three_tangent": "Draws a circle that touches three lines, circles or arcs. Use it to fit a circle into the space between three curves, such as the inscribed circle of a triangle.",
|
||||
"help.sketch.circle.two_point": "Draws a circle from the two ends of its diameter. Use it when the circle's edge points are known rather than its centre.",
|
||||
"help.sketch.circle.two_tangent": "Draws a circle of a given size that touches two lines, circles or arcs. Use it for a rounding of fixed radius between two curves.",
|
||||
"help.sketch.conic": "Draws a conic curve between two end points, shaped by an apex point and a rho value. Use it for smooth transitions whose fullness you want to tune, from flat to nearly a sharp corner.",
|
||||
"help.sketch.constrainer": "Applies the constraint that one or two picked curves nearly have already, such as horizontal, parallel, tangent or equal. Use it to tidy a hand-drawn sketch one relation at a time.",
|
||||
"help.sketch.constraint.coincident": "Makes a point lie on another point, a curve or a sketch axis. Use it to close gaps in a profile or to put a point on a line.",
|
||||
"help.sketch.constraint.collinear": "Makes two lines lie on one straight line. Use it to line up interrupted edges, such as both sides of a notch.",
|
||||
"help.sketch.constraint.concentric": "Gives two circles or arcs the same centre, or centres a circle or arc on a sketch point, including the origin. Pick either pair in either order.",
|
||||
"help.sketch.constraint.curvature": "Makes two curves that meet at an end point continue with the same curvature (G2). Use it where a tangent join is not smooth enough, for example on visible surfaces.",
|
||||
"help.sketch.constraint.equal": "Makes lines the same length, or circles and arcs the same radius. Use it so that one dimension drives several matching features.",
|
||||
"help.sketch.constraint.fix": "Fixes points or curves where they are, or frees them again. Use it for geometry that must not move when you drag or solve the sketch.",
|
||||
"help.sketch.constraint.horizontal_vertical": "Makes a line, or the line between two points, horizontal or vertical, whichever is closer. Use it to square an outline up to the sketch axes.",
|
||||
"help.sketch.constraint.midpoint": "Puts a point on the middle of a line, or makes the midpoints of two lines meet. Use it to centre geometry on an edge.",
|
||||
"help.sketch.constraint.parallel": "Makes two lines parallel. Use it for sides that must stay parallel when other dimensions change.",
|
||||
"help.sketch.constraint.perpendicular": "Makes two lines meet at a right angle. Use it for square corners between lines that are not on the sketch axes.",
|
||||
"help.sketch.constraint.polygon": "Makes a closed chain of lines a regular polygon: equal sides, with every corner on one circle. Use it to make a hand-drawn polygon regular and keep it so.",
|
||||
"help.sketch.constraint.symmetry": "Makes two points or curves mirror each other across a line or about a point. Use it to keep a profile symmetric when you change one side.",
|
||||
"help.sketch.constraint.tangent": "Makes two curves touch tangentially, such as a line and an arc. Use it for smooth joins without a kink.",
|
||||
"help.sketch.construction": "Switches curves between normal geometry and construction geometry, which profiles leave out. Use construction curves as helpers for layout, references and dimensions.",
|
||||
"help.sheet.convert": "Convierte una placa o un cuerpo vaciado de espesor uniforme en un cuerpo de chapa metálica, con pliegues en las aristas que elijas. Úsalo para hacer desplegable una pieza existente.",
|
||||
"help.sheet.export_bend_table": "Guarda la tabla de plegado de un cuerpo de chapa metálica como CSV o JSON: ángulos, radios y posiciones de los pliegues en el desarrollo. Úsalo para la plegadora o el taller.",
|
||||
"help.sheet.export_dxf": "Guarda el desarrollo plano como DXF, con contornos, líneas de plegado y notas de plegado opcionales. Úsalo para corte por láser, plasma o chorro de agua.",
|
||||
"help.sheet.flange": "Añade una pestaña: una placa base a partir de un boceto, una pared a lo largo de un contorno abierto de boceto, o una pared plegada en aristas de chapa. Úsalo para construir piezas de chapa metálica.",
|
||||
"help.sheet.flat_pattern": "Crea el desarrollo plano de un cuerpo de chapa metálica, con su tamaño, recortes y líneas de plegado. Úsalo para comprobar la pieza en bruto antes de cortarla.",
|
||||
"help.sheet.fold": "Pliega una chapa a lo largo de una línea de boceto con un ángulo y un radio. Úsalo para plegar una chapa plana tras practicarle operaciones de corte.",
|
||||
"help.sheet.hem": "Dobla el borde de una chapa sobre sí mismo. Úsalo para bordes seguros y rígidos, sin rebabas cortantes.",
|
||||
"help.sheet.manage_rules": "Crea y edita reglas de chapa metálica: espesor, radio de plegado, factor K, alivios y holguras. Úsalas para ajustarte al material y a las herramientas de tu taller.",
|
||||
"help.sheet.path_flange": "Añade una cadena de pestañas a lo largo del borde de una chapa, siguiendo una cadena abierta de líneas de boceto. Úsalo para perfiles como una U o una Z en un solo paso.",
|
||||
"help.sheet.perforate": "Añade un campo de agujeros sobre toda la chapa plana, en patrón al tresbolillo o cuadrado. Úsalo para rejillas, ventilaciones y paneles más ligeros.",
|
||||
"help.sheet.refold": "Vuelve a plegar un cuerpo de chapa metálica desplegado. Úsalo tras añadir operaciones a la chapa plana.",
|
||||
"help.sheet.unfold": "Despliega todos los pliegues de un cuerpo de chapa metálica. Úsalo para añadir agujeros o cortes que deban cruzar un pliegue, y luego vuelve a plegar.",
|
||||
"help.sketch.arc.center_point": "Dibuja un arco circular alrededor de un punto central, de un punto inicial a un punto final. Úsalo cuando se conoce el centro del arco, como un radio alrededor de un agujero o de un pivote.",
|
||||
"help.sketch.arc.tangent": "Dibuja un arco que empieza en el extremo de una línea o arco y continúa tangente a él. Úsalo para seguir una cadena con una curva suave en lugar de una esquina.",
|
||||
"help.sketch.arc.three_point": "Dibuja un arco de un punto inicial a un punto final pasando por un tercer punto. Úsalo cuando el arco deba pasar por puntos dados y no alrededor de un centro conocido.",
|
||||
"help.sketch.arc3d": "Dibuja un arco circular exacto en el espacio por tres puntos, con el Boceto 3D activado. Úsalo para curvas en trayectorias y guías que salen del plano del boceto.",
|
||||
"help.sketch.auto_constrain": "Añade las restricciones que el boceto ya casi cumple, como horizontal, paralela o coincidente, y luego lo acota hasta definirlo por completo. Úsalo para fijar de un paso un boceto dibujado a mano alzada.",
|
||||
"help.sketch.auto_constrain_from_datum": "Funciona como Restricción automática, pero mide las posiciones desde un punto de referencia que eliges en lugar del origen. Úsalo cuando la pieza se organiza a partir de un punto de referencia, como una esquina o un agujero.",
|
||||
"help.sketch.blend_curve": "Une los extremos de dos curvas con una spline suave tangente a ambas, o también de curvatura continua si lo eliges. Úsalo para salvar un hueco entre curvas sin quiebros.",
|
||||
"help.sketch.break": "Divide una curva en trozos donde otras curvas la cruzan, o en puntos que colocas sobre ella. Úsalo cuando una parte de una curva necesite su propia restricción o deba borrarse por separado.",
|
||||
"help.sketch.cancel": "Sale del boceto y descarta todo lo cambiado desde que se creó o se abrió para editarlo. Deshacer recupera los cambios.",
|
||||
"help.sketch.centerline": "Cambia las líneas entre líneas normales y líneas de eje, ejes que los perfiles dejan fuera. Usa una línea de eje como eje de una revolución, un espejo o una restricción de simetría.",
|
||||
"help.sketch.chamfer.distance_angle": "Bisela la esquina entre dos líneas, definido por una distancia a lo largo de la primera línea y un ángulo. Úsalo cuando un plano da el chaflán como una longitud y un ángulo, como 2 mm × 30°.",
|
||||
"help.sketch.chamfer.equal_distance": "Bisela la esquina entre dos líneas la misma distancia hacia atrás en ambas. Úsalo para el chaflán habitual de 45° en un contorno.",
|
||||
"help.sketch.chamfer.two_distance": "Bisela la esquina entre dos líneas, definido por una distancia distinta a lo largo de cada línea. Úsalo para chaflanes que no son de 45°, dados como dos longitudes.",
|
||||
"help.sketch.circle.center": "Dibuja un círculo a partir de su centro y su diámetro. Úsalo para agujeros, salientes y otras formas redondas cuyo centro se conoce.",
|
||||
"help.sketch.circle.three_point": "Dibuja un círculo por tres puntos. Úsalo cuando el círculo deba pasar por puntos dados, por ejemplo de geometría existente.",
|
||||
"help.sketch.circle.three_tangent": "Dibuja un círculo que toca tres líneas, círculos o arcos. Úsalo para ajustar un círculo en el espacio entre tres curvas, como el círculo inscrito de un triángulo.",
|
||||
"help.sketch.circle.two_point": "Dibuja un círculo a partir de los dos extremos de su diámetro. Úsalo cuando se conocen los puntos del borde del círculo y no su centro.",
|
||||
"help.sketch.circle.two_tangent": "Dibuja un círculo de un tamaño dado que toca dos líneas, círculos o arcos. Úsalo para un redondeo de radio fijo entre dos curvas.",
|
||||
"help.sketch.conic": "Dibuja una curva cónica entre dos puntos finales, definida por un punto de vértice y un valor rho. Úsalo para transiciones suaves cuya plenitud quieras ajustar, de plana a casi una esquina viva.",
|
||||
"help.sketch.constrainer": "Aplica la restricción que una o dos curvas elegidas ya casi cumplen, como horizontal, paralela, tangente o igual. Úsalo para ordenar un boceto dibujado a mano, una relación cada vez.",
|
||||
"help.sketch.constraint.coincident": "Hace que un punto quede sobre otro punto, una curva o un eje del boceto. Úsalo para cerrar huecos en un perfil o para poner un punto sobre una línea.",
|
||||
"help.sketch.constraint.collinear": "Hace que dos líneas queden sobre una misma recta. Úsalo para alinear aristas interrumpidas, como los dos lados de una muesca.",
|
||||
"help.sketch.constraint.concentric": "Da a dos círculos o arcos el mismo centro, o centra un círculo o arco en un punto de boceto, incluido el origen. Elige cualquiera de los dos pares en cualquier orden.",
|
||||
"help.sketch.constraint.curvature": "Hace que dos curvas que se encuentran en un punto final continúen con la misma curvatura (G2). Úsalo donde una unión tangente no es lo bastante suave, por ejemplo en superficies visibles.",
|
||||
"help.sketch.constraint.equal": "Hace que las líneas tengan la misma longitud, o los círculos y arcos el mismo radio. Úsalo para que una sola cota controle varias formas iguales.",
|
||||
"help.sketch.constraint.fix": "Fija puntos o curvas donde están, o los libera de nuevo. Úsalo para geometría que no debe moverse al arrastrar o resolver el boceto.",
|
||||
"help.sketch.constraint.horizontal_vertical": "Hace que una línea, o la línea entre dos puntos, sea horizontal o vertical, la más cercana. Úsalo para ajustar un contorno a los ejes del boceto.",
|
||||
"help.sketch.constraint.midpoint": "Pone un punto en el medio de una línea, o hace que se encuentren los puntos medios de dos líneas. Úsalo para centrar geometría sobre una arista.",
|
||||
"help.sketch.constraint.parallel": "Hace paralelas dos líneas. Úsalo para lados que deben seguir paralelos cuando cambian otras cotas.",
|
||||
"help.sketch.constraint.perpendicular": "Hace que dos líneas se encuentren en ángulo recto. Úsalo para esquinas en escuadra entre líneas que no están sobre los ejes del boceto.",
|
||||
"help.sketch.constraint.polygon": "Convierte una cadena cerrada de líneas en un polígono regular: lados iguales, con todas las esquinas en un mismo círculo. Úsalo para hacer regular un polígono dibujado a mano y mantenerlo así.",
|
||||
"help.sketch.constraint.symmetry": "Hace que dos puntos o curvas sean reflejo uno de otro respecto a una línea o a un punto. Úsalo para mantener simétrico un perfil cuando cambias un lado.",
|
||||
"help.sketch.constraint.tangent": "Hace que dos curvas se toquen tangencialmente, como una línea y un arco. Úsalo para uniones suaves sin quiebros.",
|
||||
"help.sketch.construction": "Cambia las curvas entre geometría normal y geometría de construcción, que los perfiles dejan fuera. Usa las curvas de construcción como ayuda para la disposición, las referencias y las cotas.",
|
||||
"help.sketch.construction_line": "Crea una línea de construcción infinita a través de dos puntos. Úsala para organizar un boceto.",
|
||||
"help.sketch.construction_line.angle": "Crea una línea de construcción infinita en un ángulo desde el eje X del boceto. Elige el punto a",
|
||||
"help.sketch.construction_line.bisector": "Elige dos líneas rectas de boceto que se intersecten, luego elige una de las dos bisectrices del ángulo.",
|
||||
@@ -1897,72 +1897,72 @@
|
||||
"help.sketch.construction_line.tangent_external": "Elige un círculo o arco circular, luego un punto externo y una solución de tangente. Th",
|
||||
"help.sketch.construction_line.tangent_two": "Elige dos círculos o arcos circulares, luego elige una tangente común en la previsualización.",
|
||||
"help.sketch.construction_line.vertical": "Crea una línea de construcción vertical infinita a través de un punto. Su dirección vertical",
|
||||
"help.sketch.copy": "Copies the selected sketch curves and points, together with the constraints and dimensions among them. Paste them into this sketch or another one.",
|
||||
"help.sketch.create": "Starts a new 2D sketch on a plane or on a flat face of the model. Every extrude, revolve and sweep begins with a sketch.",
|
||||
"help.sketch.cut": "Copies the selected sketch geometry and deletes it from the sketch, in one undo step. Paste it elsewhere in this sketch or into another one.",
|
||||
"help.sketch.dimension": "Adds a driving dimension: a length, distance, angle, radius or diameter, depending on what you pick. Type a value or a parameter name, and the sketch follows it.",
|
||||
"help.sketch.edit": "Opens an existing sketch for editing. The features built on it update when you finish the sketch.",
|
||||
"help.sketch.ellipse": "Draws an ellipse from its centre, the end of its major axis and a point on its minor side. Use it for oval openings, cams and other elongated round shapes.",
|
||||
"help.sketch.copy": "Copia las curvas y puntos de boceto seleccionados, junto con las restricciones y cotas entre ellos. Pégalos en este boceto o en otro.",
|
||||
"help.sketch.create": "Empieza un nuevo boceto 2D en un plano o en una cara plana del modelo. Toda extrusión, revolución y barrido empieza con un boceto.",
|
||||
"help.sketch.cut": "Copia la geometría de boceto seleccionada y la borra del boceto, en un solo paso de deshacer. Pégala en otro lugar de este boceto o en otro.",
|
||||
"help.sketch.dimension": "Añade una cota conductora: una longitud, distancia, ángulo, radio o diámetro, según lo que elijas. Escribe un valor o el nombre de un parámetro y el boceto lo sigue.",
|
||||
"help.sketch.edit": "Abre un boceto existente para editarlo. Las operaciones construidas sobre él se actualizan al terminar el boceto.",
|
||||
"help.sketch.ellipse": "Dibuja una elipse a partir de su centro, el extremo de su eje mayor y un punto de su lado menor. Úsalo para aberturas ovaladas, levas y otras formas redondas alargadas.",
|
||||
"help.sketch.equation_curve": "Dibuja una curva a partir de fórmulas: x(t) e y(t), o y = f(x), sobre un rango. La fórmula",
|
||||
"help.sketch.extend": "Lengthens a line or arc up to the nearest curve in its way, or grows two curves until they meet. Use it to close gaps in a profile after trimming or editing.",
|
||||
"help.sketch.fillet": "Rounds the corner where two lines or arcs meet with an arc of a given radius. Several corners rounded together share one radius.",
|
||||
"help.sketch.finish": "Leaves the sketch and returns to the model. Its closed profiles are then ready for Extrude, Revolve and other features.",
|
||||
"help.sketch.finish_auto_constrain": "Runs AutoConstrain on the sketch, then finishes it. Use it to leave a sketch fully defined in one step.",
|
||||
"help.sketch.fit_curves_to_section": "Cuts a mesh or solid body with the sketch plane and fits lines and arcs to the section. Use it to rebuild a scanned or imported part as an editable sketch.",
|
||||
"help.sketch.include_3d": "Brings model edges, vertices and curves of other sketches into this sketch as linked references, flattening those off its plane onto it. Use it to build on geometry that does not lie in the sketch plane.",
|
||||
"help.sketch.infinite": "Switches lines between normal lines and infinite construction lines that run across the whole view. Use them as layout references that never end too short.",
|
||||
"help.sketch.insert_dxf": "Reads the curves of a DXF drawing into a sketch, scaled, turned and placed where you set. Use it to build on a 2D drawing from another program, such as a laser-cut outline.",
|
||||
"help.sketch.insert_svg": "Reads the paths of an SVG drawing into a sketch, scaled, turned and placed where you set. Use it to turn a logo or vector outline into curves you can extrude.",
|
||||
"help.sketch.extend": "Alarga una línea o un arco hasta la curva más cercana que encuentre, o hace crecer dos curvas hasta que se encuentran. Úsalo para cerrar huecos de un perfil tras recortar o editar.",
|
||||
"help.sketch.fillet": "Redondea la esquina donde se encuentran dos líneas o arcos con un arco de un radio dado. Varias esquinas redondeadas a la vez comparten un radio.",
|
||||
"help.sketch.finish": "Sale del boceto y vuelve al modelo. Sus perfiles cerrados quedan listos para Extrusión, Revolución y otras operaciones.",
|
||||
"help.sketch.finish_auto_constrain": "Ejecuta Restricción automática en el boceto y luego lo finaliza. Úsalo para dejar un boceto totalmente definido de un paso.",
|
||||
"help.sketch.fit_curves_to_section": "Corta un cuerpo de malla o sólido con el plano del boceto y ajusta líneas y arcos a la sección. Úsalo para reconstruir como boceto editable una pieza escaneada o importada.",
|
||||
"help.sketch.include_3d": "Trae aristas del modelo, vértices y curvas de otros bocetos a este boceto como referencias vinculadas, aplanando sobre él las que no están en su plano. Úsalo para construir sobre geometría que no está en el plano del boceto.",
|
||||
"help.sketch.infinite": "Cambia las líneas entre líneas normales y líneas de construcción infinitas que cruzan toda la vista. Úsalas como referencias de disposición que nunca se quedan cortas.",
|
||||
"help.sketch.insert_dxf": "Lee las curvas de un dibujo DXF en un boceto, escaladas, giradas y colocadas donde indiques. Úsalo para construir sobre un dibujo 2D de otro programa, como un contorno para corte láser.",
|
||||
"help.sketch.insert_svg": "Lee los trazados de un dibujo SVG en un boceto, escalados, girados y colocados donde indiques. Úsalo para convertir un logotipo o un contorno vectorial en curvas que puedas extruir.",
|
||||
"help.sketch.inspect": "Abre un informe sobre el boceto abierto: cuántos grados de libertad quedan y qué",
|
||||
"help.sketch.intersect": "Adds the curves or points where bodies, faces, edges or other sketches cross the sketch plane. They stay linked and follow the model when it changes.",
|
||||
"help.sketch.intersect": "Añade las curvas o puntos donde cuerpos, caras, aristas u otros bocetos cruzan el plano del boceto. Quedan vinculados y siguen al modelo cuando cambia.",
|
||||
"help.sketch.intersection_curve": "Crea curvas 3D donde se encuentran dos cuerpos, caras o curvas de otros bocetos, vinculadas a ellos. Úsalas como trayectorias o líneas guía que siguen el modelo.",
|
||||
"help.sketch.isoparametric_curve": "Creates a 3D curve along a face's U or V direction through a point you pick, linked to the face. Use it as a path or split line that follows the surface.",
|
||||
"help.sketch.line": "Draws connected lines point by point, as an open chain or a closed outline. It is the basic tool for most profiles.",
|
||||
"help.sketch.line.midpoint": "Draws a line from its midpoint out to one end, with the other end mirrored. Use it for lines centred on a point, such as a symmetric edge.",
|
||||
"help.sketch.line3d": "Draws connected straight lines between points in space, with 3D Sketch on. Use it for paths and frames that leave the sketch plane.",
|
||||
"help.sketch.mirror": "Mirrors sketch curves and points across a line or axis and adds symmetry constraints. Use it to draw half of a symmetric profile and complete it.",
|
||||
"help.sketch.move": "Moves or rotates sketch curves and points, or a copy of them. Use it to reposition geometry while keeping its shape and constraints.",
|
||||
"help.sketch.offset": "Creates a copy of a chain of curves at a set distance, on one side or both. Use it for walls, outlines and clearances; the distance stays an editable dimension.",
|
||||
"help.sketch.paste": "Pastes sketch geometry you copied or cut into the active sketch. Place it at a point or shift it by an offset.",
|
||||
"help.sketch.pattern.circular": "Copies sketch geometry around a centre point, over a full circle or a set angle. Use it for bolt circles, spokes and teeth.",
|
||||
"help.sketch.pattern.rectangular": "Copies sketch geometry in rows and columns at set spacings. Use it for grids of holes, slots or vents.",
|
||||
"help.sketch.point": "Places a sketch point. Use it as a reference for dimensions, constraints, hole centres or later features.",
|
||||
"help.sketch.isoparametric_curve": "Crea una curva 3D en la dirección U o V de una cara, por un punto que eliges, vinculada a la cara. Úsala como trayectoria o línea de división que sigue la superficie.",
|
||||
"help.sketch.line": "Dibuja líneas conectadas punto por punto, como cadena abierta o contorno cerrado. Es la herramienta básica de la mayoría de los perfiles.",
|
||||
"help.sketch.line.midpoint": "Dibuja una línea desde su punto medio hasta un extremo, con el otro extremo reflejado. Úsalo para líneas centradas en un punto, como una arista simétrica.",
|
||||
"help.sketch.line3d": "Dibuja líneas rectas conectadas entre puntos del espacio, con el Boceto 3D activado. Úsalo para trayectorias y estructuras que salen del plano del boceto.",
|
||||
"help.sketch.mirror": "Refleja curvas y puntos de boceto respecto a una línea o un eje y añade restricciones de simetría. Úsalo para dibujar la mitad de un perfil simétrico y completarlo.",
|
||||
"help.sketch.move": "Mueve o gira curvas y puntos de boceto, o una copia de ellos. Úsalo para recolocar geometría conservando su forma y sus restricciones.",
|
||||
"help.sketch.offset": "Crea una copia de una cadena de curvas a una distancia fijada, por un lado o por ambos. Úsalo para paredes, contornos y holguras; la distancia sigue siendo una cota editable.",
|
||||
"help.sketch.paste": "Pega en el boceto activo la geometría de boceto que copiaste o cortaste. Colócala en un punto o desplázala un desfase.",
|
||||
"help.sketch.pattern.circular": "Copia la geometría de boceto alrededor de un punto central, en un círculo completo o un ángulo fijado. Úsalo para círculos de pernos, radios y dientes.",
|
||||
"help.sketch.pattern.rectangular": "Copia la geometría de boceto en filas y columnas con separaciones fijadas. Úsalo para cuadrículas de agujeros, ranuras o ventilaciones.",
|
||||
"help.sketch.point": "Coloca un punto de boceto. Úsalo como referencia para cotas, restricciones, centros de agujeros u operaciones posteriores.",
|
||||
"help.sketch.point.divide": "Coloca puntos que dividen las curvas elegidas en longitudes iguales. Los puntos permanecen en cada curva y mantienen su separación cuando esta cambia.",
|
||||
"help.sketch.point3d": "Places a point in space, with 3D Sketch on. Use it as a reference for 3D curves and paths.",
|
||||
"help.sketch.polygon.circumscribed": "Draws a regular polygon around a circle, sized from its centre to the middle of a side. Use it when the width across flats is known, as for a hex nut.",
|
||||
"help.sketch.polygon.edge": "Draws a regular polygon from the two ends of one side. Use it when the length and position of a side are known.",
|
||||
"help.sketch.polygon.inscribed": "Draws a regular polygon inside a circle, sized from its centre to a corner. Use it when the size across corners is known.",
|
||||
"help.sketch.project": "Brings model edges, faces, vertices and curves of other sketches into this sketch, projected onto its plane. They stay linked and follow the model when it changes.",
|
||||
"help.sketch.project_to_surface": "Projects curves of other sketches along this sketch's normal onto a face, as linked 3D curves. Use it to put a logo, split line or path onto a curved surface.",
|
||||
"help.sketch.rectangle.center": "Draws a rectangle from its centre and one corner. Use it for outlines centred on a point, such as the origin.",
|
||||
"help.sketch.rectangle.rounded": "Draws a rectangle with all four corners rounded to one radius. Use it for plates, lids and openings with rounded corners.",
|
||||
"help.sketch.rectangle.three_point": "Draws a rectangle from one edge and a point on the opposite side. Use it for rectangles at an angle to the sketch axes.",
|
||||
"help.sketch.rectangle.two_point": "Draws a rectangle from two opposite corners. Use it for the outlines of plates, blocks and pockets.",
|
||||
"help.sketch.scale": "Scales sketch curves and points by a factor about a base point. Use it to resize part of a sketch without drawing it again.",
|
||||
"help.sketch.slot.arc_center": "Draws a curved slot of a given width along an arc set by its centre, start and end. Use it for adjustment slots around a pivot.",
|
||||
"help.sketch.slot.arc_three_point": "Draws a curved slot of a given width along an arc through three points. Use it when the slot's path has to pass through given points.",
|
||||
"help.sketch.slot.center_point": "Draws a straight slot of a given width from its centre to the centre of one end arc. Use it for slots centred on a point.",
|
||||
"help.sketch.slot.center_to_center": "Draws a straight slot of a given width between the centres of its two end arcs. Use it for slots dimensioned centre to centre, such as adjustment slots for screws.",
|
||||
"help.sketch.slot.overall": "Draws a straight slot of a given width from one outer end to the other. Use it when the slot's overall length is what matters.",
|
||||
"help.sketch.spline.control_point": "Draws a cubic spline shaped by control points that it does not pass through. Use it for smooth, flowing curves that you shape by moving the points.",
|
||||
"help.sketch.spline.control_point_5": "Draws a degree 5 spline shaped by control points. Use it where curves have to join with smoother curvature, for example on visible styled surfaces.",
|
||||
"help.sketch.spline.fit_point": "Draws a smooth spline that passes through every point you place, open or closed. Use it to trace a shape through known points.",
|
||||
"help.sketch.spline3d": "Draws a smooth curve in space through points, with 3D Sketch on. Use it for sweep paths and cable runs that leave the sketch plane.",
|
||||
"help.sketch.spun_profile": "Creates in the sketch plane the outline a body sweeps when it turns about an axis. Use it to get the silhouette of a turned part for a revolve or a drawing.",
|
||||
"help.sketch.text": "Writes text in the sketch in a chosen font, height and angle; its words can follow parameters. Extrude or emboss it for labels and lettering.",
|
||||
"help.sketch.transform": "Scales, turns and moves sketch geometry about a centre point in one step. Use it to reposition and resize a selection at once.",
|
||||
"help.sketch.trim": "Removes the piece of a curve between the nearest crossings around where you click. Use it to clean up overlapping lines into a closed profile.",
|
||||
"help.sketch.point3d": "Coloca un punto en el espacio, con el Boceto 3D activado. Úsalo como referencia para curvas y trayectorias 3D.",
|
||||
"help.sketch.polygon.circumscribed": "Dibuja un polígono regular alrededor de un círculo, dimensionado desde su centro hasta el medio de un lado. Úsalo cuando se conoce la anchura entre caras, como en una tuerca hexagonal.",
|
||||
"help.sketch.polygon.edge": "Dibuja un polígono regular a partir de los dos extremos de un lado. Úsalo cuando se conocen la longitud y la posición de un lado.",
|
||||
"help.sketch.polygon.inscribed": "Dibuja un polígono regular dentro de un círculo, dimensionado desde su centro hasta una esquina. Úsalo cuando se conoce la medida entre esquinas.",
|
||||
"help.sketch.project": "Trae aristas del modelo, caras, vértices y curvas de otros bocetos a este boceto, proyectados sobre su plano. Quedan vinculados y siguen al modelo cuando cambia.",
|
||||
"help.sketch.project_to_surface": "Proyecta curvas de otros bocetos a lo largo de la normal de este boceto sobre una cara, como curvas 3D vinculadas. Úsalo para poner un logotipo, una línea de división o una trayectoria sobre una superficie curva.",
|
||||
"help.sketch.rectangle.center": "Dibuja un rectángulo a partir de su centro y una esquina. Úsalo para contornos centrados en un punto, como el origen.",
|
||||
"help.sketch.rectangle.rounded": "Dibuja un rectángulo con las cuatro esquinas redondeadas con un mismo radio. Úsalo para placas, tapas y aberturas con esquinas redondeadas.",
|
||||
"help.sketch.rectangle.three_point": "Dibuja un rectángulo a partir de un borde y un punto del lado opuesto. Úsalo para rectángulos inclinados respecto a los ejes del boceto.",
|
||||
"help.sketch.rectangle.two_point": "Dibuja un rectángulo a partir de dos esquinas opuestas. Úsalo para los contornos de placas, bloques y vaciados.",
|
||||
"help.sketch.scale": "Escala curvas y puntos de boceto por un factor respecto a un punto base. Úsalo para cambiar el tamaño de parte de un boceto sin volver a dibujarla.",
|
||||
"help.sketch.slot.arc_center": "Dibuja una ranura curva de una anchura dada a lo largo de un arco definido por su centro, inicio y fin. Úsalo para ranuras de ajuste alrededor de un pivote.",
|
||||
"help.sketch.slot.arc_three_point": "Dibuja una ranura curva de una anchura dada a lo largo de un arco por tres puntos. Úsalo cuando la trayectoria de la ranura deba pasar por puntos dados.",
|
||||
"help.sketch.slot.center_point": "Dibuja una ranura recta de una anchura dada desde su centro hasta el centro de un arco de extremo. Úsalo para ranuras centradas en un punto.",
|
||||
"help.sketch.slot.center_to_center": "Dibuja una ranura recta de una anchura dada entre los centros de sus dos arcos de extremo. Úsalo para ranuras acotadas de centro a centro, como las ranuras de ajuste de tornillos.",
|
||||
"help.sketch.slot.overall": "Dibuja una ranura recta de una anchura dada de un extremo exterior al otro. Úsalo cuando lo que importa es la longitud total de la ranura.",
|
||||
"help.sketch.spline.control_point": "Dibuja una spline cúbica definida por puntos de control por los que no pasa. Úsalo para curvas suaves y fluidas que moldeas moviendo los puntos.",
|
||||
"help.sketch.spline.control_point_5": "Dibuja una spline de grado 5 definida por puntos de control. Úsalo donde las curvas deban unirse con una curvatura más suave, por ejemplo en superficies de diseño visibles.",
|
||||
"help.sketch.spline.fit_point": "Dibuja una spline suave que pasa por cada punto que colocas, abierta o cerrada. Úsalo para trazar una forma por puntos conocidos.",
|
||||
"help.sketch.spline3d": "Dibuja una curva suave en el espacio por puntos, con el Boceto 3D activado. Úsalo para trayectorias de barrido y recorridos de cable que salen del plano del boceto.",
|
||||
"help.sketch.spun_profile": "Crea en el plano del boceto el contorno que barre un cuerpo al girar sobre un eje. Úsalo para obtener la silueta de una pieza torneada para una revolución o un plano.",
|
||||
"help.sketch.text": "Escribe texto en el boceto con una fuente, altura y ángulo elegidos; sus palabras pueden seguir parámetros. Extrúyelo o grábalo para etiquetas y rótulos.",
|
||||
"help.sketch.transform": "Escala, gira y mueve la geometría del boceto respecto a un punto central en un solo paso. Úsalo para recolocar y cambiar de tamaño una selección a la vez.",
|
||||
"help.sketch.trim": "Elimina el trozo de una curva entre los cruces más cercanos alrededor de donde haces clic. Úsalo para limpiar líneas solapadas y obtener un perfil cerrado.",
|
||||
"help.solid.align": "Mueve los cuerpos seleccionados para que un punto, cara o plano de ellos coincida con un punto,",
|
||||
"help.solid.boundary_fill": "Makes solids from the regions enclosed by overlapping tool bodies, filling only the regions you pick. Use it to build a shape from the space that several bodies bound together.",
|
||||
"help.solid.bounding_solid": "Creates a box that encloses the selected bodies, with an optional margin. Use it to see a part's overall size, or as the stock it is machined from.",
|
||||
"help.solid.box": "Creates a box from a length, width and height, from a corner point or centred on a point. Use it for a quick block, a placeholder or a body to cut features into.",
|
||||
"help.solid.boundary_fill": "Crea sólidos a partir de las regiones encerradas por cuerpos herramienta que se solapan, rellenando solo las regiones que elijas. Úsalo para construir una forma a partir del espacio que delimitan varios cuerpos juntos.",
|
||||
"help.solid.bounding_solid": "Crea una caja que envuelve los cuerpos seleccionados, con un margen opcional. Úsalo para ver el tamaño total de una pieza, o como material en bruto del que se mecaniza.",
|
||||
"help.solid.box": "Crea una caja a partir de largo, ancho y alto, desde un punto de esquina o centrada en un punto. Úsalo para un bloque rápido, un marcador de posición o un cuerpo en el que practicar operaciones de corte.",
|
||||
"help.solid.chamfer": "Corta las aristas seleccionadas con un chaflán plano de la distancia que indiques. Úsalo para romper aristas vivas o para facilitar la entrada de un pasador o un tornillo.",
|
||||
"help.solid.coil": "Creates a helical body, such as a spring, from a diameter, turns, height or pitch and a round or square section. Use it for springs, coils and helical ridges.",
|
||||
"help.solid.coil": "Crea un cuerpo helicoidal, como un muelle, a partir de un diámetro, vueltas, altura o paso y una sección redonda o cuadrada. Úsalo para muelles, bobinas y resaltes helicoidales.",
|
||||
"help.solid.combine": "Combina cuerpos: los une, los recorta de un cuerpo de destino o conserva solo el volumen que comparten, y puede mantener los cuerpos de herramienta. Úsalo para fusionar piezas, recortar una forma con otra o encontrar dónde se solapan dos cuerpos.",
|
||||
"help.solid.cone": "Creates a cone from a base circle and a height, or a truncated cone when the top has a radius too. Use it for tapers, funnels, countersinks and points.",
|
||||
"help.solid.cylinder": "Creates a cylinder from a radius or diameter and a height, standing on a point along an axis. Use it for shafts, pins, bosses and round blanks.",
|
||||
"help.solid.cone": "Crea un cono a partir de un círculo base y una altura, o un cono truncado cuando la parte superior también tiene radio. Úsalo para conicidades, embudos, avellanados y puntas.",
|
||||
"help.solid.cylinder": "Crea un cilindro a partir de un radio o diámetro y una altura, apoyado en un punto a lo largo de un eje. Úsalo para ejes, pasadores, salientes y piezas en bruto redondas.",
|
||||
"help.solid.draft": "Inclina las caras seleccionadas según el ángulo que indiques, medido desde un plano neutro. Usa",
|
||||
"help.solid.emboss": "Raises sketch profiles, such as text or a logo, out of a face, or sinks them into it. Use it for lettering, labels and markings on flat or round faces.",
|
||||
"help.solid.emboss": "Eleva perfiles de boceto, como texto o un logotipo, sobre una cara, o los hunde en ella. Úsalo para rótulos, etiquetas y marcas en caras planas o redondas.",
|
||||
"help.solid.extrude": "Empuja un perfil de boceto hacia el 3D a lo largo de una distancia, añadiendo o quitando material. Úsalo para convertir un contorno plano en un bloque, un saliente o una cavidad.",
|
||||
"help.solid.fillet": "Redondea las aristas seleccionadas con una transición circular suave del radio que indiques. Úsalo para suavizar aristas vivas por resistencia, comodidad o aspecto.",
|
||||
"help.solid.hole": "Perfora un agujero redondo del diámetro que indiques en un punto elegido de una cara. Úsalo para holguras de tornillos, pasadores y otras aberturas redondas sencillas.",
|
||||
@@ -1971,62 +1971,62 @@
|
||||
"help.solid.move": "Mueve o rota los cuerpos seleccionados, o una copia de ellos, por la distancia y el ángulo",
|
||||
"help.solid.offset_face": "Empuja las caras seleccionadas hacia dentro o fuera por la distancia que indiques, y las caras de alrededor",
|
||||
"help.solid.pattern.circular": "Repite los objetos seleccionados alrededor de un eje, con el recuento y el ángulo total que indiques. Úsalo para círculos de tornillos, radios, aletas y dientes.",
|
||||
"help.solid.pattern.path": "Copies features or bodies along a sketch path, by count and spacing. Use it for holes along a curved edge or parts along a rail.",
|
||||
"help.solid.pattern.path": "Copia operaciones o cuerpos a lo largo de una trayectoria de boceto, por número y separación. Úsalo para agujeros a lo largo de una arista curva o piezas a lo largo de un carril.",
|
||||
"help.solid.pattern.rectangular": "Repite los objetos seleccionados en una o dos direcciones con el recuento y el espaciado que indiques. Úsalo para filas y cuadrículas de agujeros, nervios, pasadores o patas.",
|
||||
"help.solid.pipe": "Creates a round tube along a path of sketch curves, solid or hollow with a wall thickness. Use it for tubes, wires, cables and rails.",
|
||||
"help.solid.pipe": "Crea un tubo redondo a lo largo de una trayectoria de curvas de boceto, macizo o hueco con un espesor de pared. Úsalo para tubos, cables y carriles.",
|
||||
"help.solid.press_pull": "Añade o quita material al arrastrar una cara, o redondea aristas al arrastrarlas. Usa",
|
||||
"help.solid.remove": "Saca los cuerpos seleccionados del diseño desde este punto de la línea de tiempo en adelante;",
|
||||
"help.solid.replace_face": "Mueve las caras planas seleccionadas sobre un plano o sobre una cara paralela, y el cuerpo",
|
||||
"help.solid.revolve": "Gira un perfil de boceto alrededor de un eje para crear un sólido de revolución. Úsalo para ejes, pomos, cuencos y cualquier otra pieza de revolución.",
|
||||
"help.solid.rib": "Adds a thin wall along an open sketch curve, filled out to the next faces of the body. Use it to stiffen walls and corners, for example in moulded or printed parts.",
|
||||
"help.solid.rib": "Añade una pared fina a lo largo de una curva de boceto abierta, extendida hasta las siguientes caras del cuerpo. Úsalo para reforzar paredes y esquinas, por ejemplo en piezas moldeadas o impresas.",
|
||||
"help.solid.scale": "Hace los cuerpos seleccionados más grandes o más pequeños por un factor, el mismo en todas las direcciones",
|
||||
"help.solid.shell": "Vacía un sólido y deja paredes del grosor que indiques; además, puede abrir las caras que elijas. Úsalo para cajas, tapas y otras piezas de paredes finas.",
|
||||
"help.solid.sphere": "Creates a sphere from a radius or diameter around a centre point. Use it for balls, knobs and rounded ends.",
|
||||
"help.solid.sphere": "Crea una esfera a partir de un radio o diámetro alrededor de un punto central. Úsalo para bolas, pomos y extremos redondeados.",
|
||||
"help.solid.split_body": "Corta un cuerpo en cuerpos separados con un plano, la cara de otro cuerpo o un boceto",
|
||||
"help.solid.split_face": "Divide las caras seleccionadas a lo largo de un plano, la cara de otro cuerpo o una curva de boceto",
|
||||
"help.solid.sweep": "Arrastra un perfil de boceto a lo largo de una trayectoria para crear un sólido. Úsalo para tubos, raíles, asas y cualquier pieza de sección constante que siga una curva.",
|
||||
"help.solid.thread": "Adds an ISO metric thread to a cylindrical face, either as a cosmetic thread or cut into the body. Use it for bolts, threaded holes and printed screw parts.",
|
||||
"help.solid.torus": "Creates a ring from a major radius around its axis and a minor radius for its round section. Use it for O-rings, handles and round beads.",
|
||||
"help.solid.web": "Adds a thin wall along each open sketch curve, each filled out to the next faces of the body. Use it for a grid of supporting walls inside housings and trays.",
|
||||
"help.surface.blend": "Creates a surface that bridges the edges of two bodies, tangent or curvature continuous to both. Use it to join two surfaces smoothly across a gap.",
|
||||
"help.surface.boundary": "Creates a surface filling a loop of two to four sketch curves, or a network of curves. Use it for free-form panels defined by their edges.",
|
||||
"help.surface.extend": "Lengthens a surface past its edges, by a distance or up to a plane or face. Use it so that surfaces overlap before you trim or stitch them.",
|
||||
"help.surface.extrude": "Pushes sketch curves or profiles along a distance into a surface, walls only, without caps. Use it for thin walls and for cutting or splitting tools.",
|
||||
"help.surface.fair": "Smooths the inside of free-form faces while their edges stay put. Use it to even out bumps and wavy reflections in a surface.",
|
||||
"help.surface.loft": "Creates a surface that passes through two or more sections in order, without caps. Use it for shells and transitions between different shapes.",
|
||||
"help.surface.match": "Rebuilds the edge of a surface so it meets another body's edge, with matching tangent or curvature. Use it to close a seam smoothly between two surfaces.",
|
||||
"help.surface.offset": "Creates a copy of faces at a distance along their normals, as a new surface body. Use it for skins, clearances or the other side of a wall.",
|
||||
"help.surface.patch": "Fills a sketch region or a closed loop of edges with a face, flat or smoothly curved. Use it to close holes in a surface body.",
|
||||
"help.surface.reverse_normal": "Turns faces of a surface body over, so their outside faces the other way. Use it before thickening or stitching when the faces point inward.",
|
||||
"help.surface.revolve": "Turns sketch curves or profiles about an axis into a surface, without caps. Use it for round shells such as lampshades, bowls and nozzles.",
|
||||
"help.surface.ruled": "Creates a strip of straight lines out from a chain of edges, along the face's normal, tangent or at an angle. Use it for draft walls, run-offs and parting surfaces.",
|
||||
"help.surface.stitch": "Sews surface bodies together along their shared edges, into a solid when they close. Use it to turn a set of surfaces into one body.",
|
||||
"help.surface.sweep": "Moves sketch curves or profiles along a path into a surface, without caps. Use it for gutters, trims and other thin shapes that follow a path.",
|
||||
"help.surface.thicken": "Gives a surface body a thickness, turning it into a solid. Use it to make printable or machinable parts from surfaces.",
|
||||
"help.surface.trim": "Cuts a surface with a plane, another surface or sketch curves, and keeps the side you pick. Use it to cut surfaces to shape before stitching.",
|
||||
"help.surface.unstitch": "Separates faces of a body into surface bodies of their own; a solid comes apart into surfaces. Use it to rework single faces of a body.",
|
||||
"help.surface.untrim": "Removes holes from a face, or restores its outer boundary to the surface's natural bounds. Use it to get back the full surface after a trim.",
|
||||
"help.solid.thread": "Añade una rosca métrica ISO a una cara cilíndrica, como rosca cosmética o tallada en el cuerpo. Úsalo para pernos, agujeros roscados y piezas impresas con rosca.",
|
||||
"help.solid.torus": "Crea un anillo a partir de un radio mayor alrededor de su eje y un radio menor para su sección redonda. Úsalo para juntas tóricas, asas y cuentas redondas.",
|
||||
"help.solid.web": "Añade una pared fina a lo largo de cada curva de boceto abierta, cada una extendida hasta las siguientes caras del cuerpo. Úsalo para una rejilla de paredes de apoyo dentro de carcasas y bandejas.",
|
||||
"help.surface.blend": "Crea una superficie que une las aristas de dos cuerpos, tangente o de curvatura continua con ambos. Úsalo para unir suavemente dos superficies a través de un hueco.",
|
||||
"help.surface.boundary": "Crea una superficie que rellena un lazo de dos a cuatro curvas de boceto, o una red de curvas. Úsalo para paneles de forma libre definidos por sus bordes.",
|
||||
"help.surface.extend": "Alarga una superficie más allá de sus bordes, una distancia o hasta un plano o una cara. Úsalo para que las superficies se solapen antes de recortarlas o coserlas.",
|
||||
"help.surface.extrude": "Empuja curvas o perfiles de boceto una distancia para crear una superficie, solo paredes, sin tapas. Úsalo para paredes finas y para herramientas de corte o división.",
|
||||
"help.surface.fair": "Suaviza el interior de caras de forma libre mientras sus bordes se quedan donde están. Úsalo para igualar bultos y reflejos ondulados en una superficie.",
|
||||
"help.surface.loft": "Crea una superficie que pasa por dos o más secciones en orden, sin tapas. Úsalo para cascarones y transiciones entre formas distintas.",
|
||||
"help.surface.match": "Reconstruye el borde de una superficie para que encuentre el borde de otro cuerpo, con tangencia o curvatura coincidentes. Úsalo para cerrar suavemente una unión entre dos superficies.",
|
||||
"help.surface.offset": "Crea una copia de caras a una distancia a lo largo de sus normales, como un nuevo cuerpo de superficie. Úsalo para pieles, holguras o el otro lado de una pared.",
|
||||
"help.surface.patch": "Rellena una región de boceto o un lazo cerrado de aristas con una cara, plana o suavemente curva. Úsalo para cerrar agujeros en un cuerpo de superficie.",
|
||||
"help.surface.reverse_normal": "Da la vuelta a caras de un cuerpo de superficie, de modo que su exterior mire al otro lado. Úsalo antes de engrosar o coser cuando las caras apuntan hacia dentro.",
|
||||
"help.surface.revolve": "Gira curvas o perfiles de boceto alrededor de un eje para crear una superficie, sin tapas. Úsalo para cascarones redondos como pantallas de lámpara, cuencos y toberas.",
|
||||
"help.surface.ruled": "Crea una tira de líneas rectas a partir de una cadena de aristas, a lo largo de la normal de la cara, tangente o en ángulo. Úsalo para paredes con desmoldeo, salidas y superficies de partición.",
|
||||
"help.surface.stitch": "Cose cuerpos de superficie a lo largo de sus aristas compartidas, en un sólido cuando se cierran. Úsalo para convertir un conjunto de superficies en un solo cuerpo.",
|
||||
"help.surface.sweep": "Mueve curvas o perfiles de boceto a lo largo de una trayectoria para crear una superficie, sin tapas. Úsalo para canalones, molduras y otras formas finas que siguen una trayectoria.",
|
||||
"help.surface.thicken": "Da espesor a un cuerpo de superficie y lo convierte en sólido. Úsalo para obtener piezas imprimibles o mecanizables a partir de superficies.",
|
||||
"help.surface.trim": "Corta una superficie con un plano, otra superficie o curvas de boceto, y conserva el lado que elijas. Úsalo para dar forma a las superficies antes de coserlas.",
|
||||
"help.surface.unstitch": "Separa caras de un cuerpo en cuerpos de superficie propios; un sólido se descompone en superficies. Úsalo para retocar caras sueltas de un cuerpo.",
|
||||
"help.surface.untrim": "Quita agujeros de una cara, o restaura su contorno exterior a los límites naturales de la superficie. Úsalo para recuperar la superficie completa tras un recorte.",
|
||||
"help.third_party": "Licencias de terceros",
|
||||
"help.timeline.compute_all": "Reconstruye cada operación de la línea de tiempo desde el inicio. Úsalo para refrescar el modelo",
|
||||
"help.timeline.delete": "Elimina las operaciones seleccionadas de la línea de tiempo; borrar un boceto también elimina",
|
||||
"help.timeline.dependents": "Lists the features that would be deleted with a feature, and those that would fail without it. Use it before deleting or changing a feature.",
|
||||
"help.timeline.dependents": "Lista las operaciones que se borrarían junto con una operación, y las que fallarían sin ella. Úsalo antes de borrar o cambiar una operación.",
|
||||
"help.timeline.play": "Reproduce las operaciones restantes una a una, con una pausa de medio segundo tras cada una",
|
||||
"help.version": "Version {version}",
|
||||
"help.view.apply": "Turns the view to a standard direction such as front, top or iso, or to a saved named view. Use it to look at the model from a fixed angle.",
|
||||
"help.view.delete": "Deletes a saved named view. The model is not changed.",
|
||||
"help.view.fit": "Zooms and pans so the whole model, or the selection, fills the view. Use it when the model has gone out of sight.",
|
||||
"help.view.grid": "Shows or hides the grid in the viewport. Use it as a size and orientation guide while modelling.",
|
||||
"help.view.ground_shadow": "Shows or hides the model's shadow on the ground. Use it to judge height and position more easily.",
|
||||
"help.view.home": "Turns the view back to the home direction and fits the model. Use it to get back to a known view quickly.",
|
||||
"help.view.list": "Lists the named views saved in the design. Use it to find a view you saved earlier.",
|
||||
"help.view.navigate": "Turns, pans or zooms the view by steps, such as a quarter turn left. Use it to move the camera precisely instead of dragging.",
|
||||
"help.view.navigation_bar": "Shows or hides the navigation bar at the bottom of the viewport. Hide it for more room, show it to reach the view tools by mouse.",
|
||||
"help.view.rename": "Gives a saved named view a new name. The view itself stays the same.",
|
||||
"help.version": "Versión {version}",
|
||||
"help.view.apply": "Gira la vista a una dirección estándar como frontal, superior o isométrica, o a una vista con nombre guardada. Úsalo para mirar el modelo desde un ángulo fijo.",
|
||||
"help.view.delete": "Borra una vista con nombre guardada. El modelo no cambia.",
|
||||
"help.view.fit": "Acerca y desplaza para que todo el modelo, o la selección, llene la vista. Úsalo cuando el modelo se ha salido de la vista.",
|
||||
"help.view.grid": "Muestra u oculta la cuadrícula en la vista. Úsala como guía de tamaño y orientación al modelar.",
|
||||
"help.view.ground_shadow": "Muestra u oculta la sombra del modelo en el suelo. Úsalo para juzgar con más facilidad la altura y la posición.",
|
||||
"help.view.home": "Devuelve la vista a la dirección de inicio y encuadra el modelo. Úsalo para volver rápido a una vista conocida.",
|
||||
"help.view.list": "Lista las vistas con nombre guardadas en el diseño. Úsalo para encontrar una vista que guardaste antes.",
|
||||
"help.view.navigate": "Gira, desplaza o acerca la vista por pasos, como un cuarto de vuelta a la izquierda. Úsalo para mover la cámara con precisión en lugar de arrastrar.",
|
||||
"help.view.navigation_bar": "Muestra u oculta la barra de navegación en la parte inferior de la vista. Ocúltala para tener más espacio, muéstrala para llegar a las herramientas de vista con el ratón.",
|
||||
"help.view.rename": "Da un nombre nuevo a una vista con nombre guardada. La vista en sí no cambia.",
|
||||
"help.view.ribbon_tabs_only": "Pliega la cinta hasta su fila de pestañas para que la vista recupere el espacio de los paneles. Haz clic en una pestaña para mostrar sus paneles sobre la vista; vuelve a elegir esta opción para mantener toda la cinta visible.",
|
||||
"help.view.save": "Saves the current camera position as a named view in the design. Use it to come back to the same angle later, for example for screenshots.",
|
||||
"help.view.spin": "Orbits the view around the model continuously until the next click or key. Use it to present a model from all sides.",
|
||||
"help.view.tool": "Latches a camera tool, orbit, pan or zoom, so that dragging with the left mouse button moves the view until you switch it off. Use it on a trackpad or without a middle mouse button.",
|
||||
"help.view.visual_style": "Switches how the model is drawn: shaded with or without edges, wireframe, or with hidden edges. Use wireframe to see inside, shaded for a clean look.",
|
||||
"help.view.save": "Guarda la posición actual de la cámara como una vista con nombre en el diseño. Úsalo para volver al mismo ángulo más tarde, por ejemplo para capturas de pantalla.",
|
||||
"help.view.spin": "Hace orbitar la vista alrededor del modelo de forma continua hasta el siguiente clic o tecla. Úsalo para presentar un modelo por todos sus lados.",
|
||||
"help.view.tool": "Fija una herramienta de cámara, órbita, desplazamiento o zoom, de modo que arrastrar con el botón izquierdo del ratón mueva la vista hasta que la desactives. Úsalo en un trackpad o sin botón central del ratón.",
|
||||
"help.view.visual_style": "Cambia cómo se dibuja el modelo: sombreado con o sin aristas, estructura alámbrica o con aristas ocultas. Usa la estructura alámbrica para ver el interior y el sombreado para un aspecto limpio.",
|
||||
"history.sketch_under_constrained": "Bajo restricción ({count} grados de libertad)",
|
||||
"history.sketch_under_constrained_one": "Bajo restricción ({count} grado de libertad)",
|
||||
"hole_folder.applies_to": "Los cambios se aplican a los {count} agujeros de {folder}; cada uno conserva su posición.",
|
||||
|
||||
+373
-65
@@ -477,6 +477,7 @@
|
||||
"Rectangular": "Rectangulaire",
|
||||
"Rectangular Tube": "Tube rectangulaire",
|
||||
"Reference face": "Face de référence",
|
||||
"Reference plane": "Plan de référence",
|
||||
"Relief Depth": "Profondeur de dégagement",
|
||||
"Relief Width": "Largeur de dégagement",
|
||||
"Remove Tools": "Retirer les outils",
|
||||
@@ -495,6 +496,7 @@
|
||||
"Render Stage": "Plateau de rendu",
|
||||
"Reopen designs": "Rouvrir les conceptions",
|
||||
"Reopen the designs that were open when SolidCraft was last closed": "Rouvrir les conceptions ouvertes lors de la dernière fermeture de SolidCraft",
|
||||
"Repair Part": "Réparer la pièce",
|
||||
"Replace existing library file": "Remplacer le fichier de bibliothèque existant",
|
||||
"Report a bug — review a screenshot and open a GitHub draft": "Signaler un bug — relire une capture d'écran et ouvrir un brouillon GitHub",
|
||||
"Report copied. Keep this text to submit on GitHub when you are online.": "Rapport copié. Conservez ce texte pour le soumettre sur GitHub une fois en ligne.",
|
||||
@@ -790,18 +792,19 @@
|
||||
"browser.edit_canvas_title": "Modifier la toile : {name}",
|
||||
"browser.edit_point_cloud_title": "Modifier le nuage de points : {name}",
|
||||
"browser.move_title": "Déplacer : {name}",
|
||||
"browser.needs_repair": "{name} : nécessite une réparation",
|
||||
"browser.parameters": "Paramètres ({count})",
|
||||
"browser.precision": "Précision : {precision}",
|
||||
"browser.sketch_attachment_lost": "{name} (attache perdue)",
|
||||
"browser.sketch_editing": "{name} (en cours de modification)",
|
||||
"browser.sketch_name": "Esquisse{number}",
|
||||
"browser.sketches_to_parts_already_in_part": "déjà dans leur pièce",
|
||||
"browser.sketches_to_parts_design_body": "sur un corps de la conception elle-même",
|
||||
"browser.sketches_to_parts_moved": "{moved} esquisses déplacées vers la pièce sur laquelle elles se trouvent",
|
||||
"browser.sketches_to_parts_no_exact_attachment": "sur une face sans rattachement exact",
|
||||
"browser.sketches_to_parts_not_on_face": "pas sur la face d'une pièce",
|
||||
"browser.sketches_to_parts_design_body": "sur un corps appartenant directement à la conception",
|
||||
"browser.sketches_to_parts_moved": "{moved} esquisses déplacées dans la pièce à laquelle elles appartiennent",
|
||||
"browser.sketches_to_parts_no_exact_attachment": "sur une face sans liaison exacte",
|
||||
"browser.sketches_to_parts_not_on_face": "pas sur une face de pièce",
|
||||
"browser.sketches_to_parts_part_missing": "leur pièce n'existe plus",
|
||||
"browser.sketches_to_parts_result": "{moved} esquisses déplacées vers la pièce sur laquelle elles se trouvent ; {stayed} sont restées en place : {why}",
|
||||
"browser.sketches_to_parts_result": "{moved} esquisses déplacées dans leur pièce ; {stayed} conservées à leur emplacement : {why}",
|
||||
"browser.units": "Unités : {units}",
|
||||
"cam.flat": "Plateau",
|
||||
"cam.follower": "Suiveur",
|
||||
@@ -834,6 +837,7 @@
|
||||
"cmd.assembly_mass_properties": "Propriétés de masse",
|
||||
"cmd.body.print_face": "Face d’impression",
|
||||
"cmd.body_rename": "Renommer le corps",
|
||||
"cmd.body_repair": "Réparer la pièce",
|
||||
"cmd.browser_collapse_all": "Tout réduire",
|
||||
"cmd.browser_expand_all": "Tout développer",
|
||||
"cmd.browser_group": "Nouveau groupe",
|
||||
@@ -870,7 +874,7 @@
|
||||
"cmd.component_move_bodies": "Déplacer les corps vers le composant",
|
||||
"cmd.component_move_features": "Déplacer les fonctions vers le composant",
|
||||
"cmd.component_move_sketches": "Déplacer les esquisses vers le composant",
|
||||
"cmd.component_move_sketches_to_parts": "Déplacer les esquisses vers leurs pièces",
|
||||
"cmd.component_move_sketches_to_parts": "Déplacer les esquisses dans leurs pièces",
|
||||
"cmd.component_paste_from_design": "Coller depuis une autre conception",
|
||||
"cmd.component_paste_new": "Coller comme nouveau",
|
||||
"cmd.component_properties": "Propriétés physiques du composant",
|
||||
@@ -918,6 +922,8 @@
|
||||
"cmd.diagnostics_crash_reports": "Rapports de plantage",
|
||||
"cmd.diagnostics_crash_reports_clear": "Supprimer les rapports de plantage",
|
||||
"cmd.diagnostics_crash_test": "Test de plantage",
|
||||
"cmd.diagnostics_profile": "Profil",
|
||||
"cmd.diagnostics_validation": "Validation",
|
||||
"cmd.doc_recover": "Récupérer la conception",
|
||||
"cmd.doc_recovery_discard": "Abandonner la conception récupérée",
|
||||
"cmd.doc_recovery_list": "Conceptions récupérables",
|
||||
@@ -938,11 +944,11 @@
|
||||
"cmd.explode_show": "Afficher la vue éclatée",
|
||||
"cmd.expr_evaluate": "Évaluer une expression",
|
||||
"cmd.face_delete": "Supprimer la face",
|
||||
"cmd.file.export_3mf": "Exporter en 3MF",
|
||||
"cmd.file.export_obj": "Exporter en OBJ",
|
||||
"cmd.file.export_step": "Exporter en STEP",
|
||||
"cmd.file.export_stl": "Exporter en STL",
|
||||
"cmd.file.export_urdf": "Exporter en URDF",
|
||||
"cmd.file.export_3mf": "Exporter au format 3MF",
|
||||
"cmd.file.export_obj": "Exporter au format OBJ",
|
||||
"cmd.file.export_step": "Exporter au format STEP",
|
||||
"cmd.file.export_stl": "Exporter au format STL",
|
||||
"cmd.file.export_urdf": "Exporter au format URDF",
|
||||
"cmd.file_export": "Exporter",
|
||||
"cmd.file_insert_mesh": "Insérer un maillage",
|
||||
"cmd.file_insert_step": "Insérer un STEP",
|
||||
@@ -955,6 +961,7 @@
|
||||
"cmd.frame_profile_list": "Bibliothèque de profilés",
|
||||
"cmd.frame_profile_properties": "Propriétés du profilé",
|
||||
"cmd.inspect_accessibility": "Analyse d'accessibilité",
|
||||
"cmd.inspect_analysis": "Afficher l'analyse",
|
||||
"cmd.inspect_center_of_mass": "Centre de gravité",
|
||||
"cmd.inspect_clearance": "Jeu",
|
||||
"cmd.inspect_compare": "Comparer les corps",
|
||||
@@ -976,6 +983,7 @@
|
||||
"cmd.joint_delete": "Supprimer la liaison",
|
||||
"cmd.joint_drive": "Piloter les liaisons",
|
||||
"cmd.joint_edit": "Modifier la liaison",
|
||||
"cmd.joint_find_limits": "Rechercher les limites de la liaison",
|
||||
"cmd.joint_gear": "Engrenage",
|
||||
"cmd.joint_inspect": "Inspecter la liaison",
|
||||
"cmd.joint_limits": "Limites de liaison",
|
||||
@@ -988,6 +996,11 @@
|
||||
"cmd.joint_screw": "Vis",
|
||||
"cmd.joint_solve": "Résoudre les liaisons",
|
||||
"cmd.joint_sweep": "Balayer une liaison",
|
||||
"cmd.layout.apply": "Appliquer la disposition",
|
||||
"cmd.layout.get": "Inspecter la disposition",
|
||||
"cmd.layout.reset": "Réinitialiser la disposition",
|
||||
"cmd.layout.save": "Enregistrer la disposition",
|
||||
"cmd.layout.workspace.select": "Sélectionner l'espace de travail de la disposition",
|
||||
"cmd.library_apply": "Appliquer une entrée de la bibliothèque locale",
|
||||
"cmd.library_export": "Exporter la bibliothèque de la conception",
|
||||
"cmd.library_inspect": "Inspecter la bibliothèque locale",
|
||||
@@ -1022,6 +1035,21 @@
|
||||
"cmd.occurrence_move": "Déplacer l'occurrence",
|
||||
"cmd.occurrence_properties": "Propriétés physiques de l'occurrence",
|
||||
"cmd.occurrence_reparent": "Déplacer vers le composant",
|
||||
"cmd.panel.activate": "Activer l'onglet de panneau",
|
||||
"cmd.panel.close": "Fermer le panneau",
|
||||
"cmd.panel.collapse": "Réduire la section de panneau",
|
||||
"cmd.panel.dismiss": "Fermer l'aperçu du panneau",
|
||||
"cmd.panel.float": "Rendre le panneau flottant",
|
||||
"cmd.panel.focus": "Mettre le panneau au premier plan",
|
||||
"cmd.panel.list": "Lister les panneaux",
|
||||
"cmd.panel.move": "Déplacer le panneau",
|
||||
"cmd.panel.native_close": "Réancrer la section de panneau natif",
|
||||
"cmd.panel.open": "Ouvrir le panneau",
|
||||
"cmd.panel.peek": "Aperçu d'un panneau réduit",
|
||||
"cmd.panel.popout": "Détacher le panneau",
|
||||
"cmd.panel.reset_pair": "Réinitialiser le séparateur de panneaux",
|
||||
"cmd.panel.resize": "Redimensionner la section de panneau",
|
||||
"cmd.panel.resize_pair": "Redimensionner le séparateur de panneaux",
|
||||
"cmd.parameters_add": "Ajouter un paramètre utilisateur",
|
||||
"cmd.parameters_change": "Modifier les paramètres",
|
||||
"cmd.parameters_comment": "Commenter le paramètre",
|
||||
@@ -1052,8 +1080,8 @@
|
||||
"cmd.pointcloud_list": "Nuages de points",
|
||||
"cmd.pointcloud_reload": "Recharger le nuage de points",
|
||||
"cmd.render.compare.divider": "Déplacer le séparateur de comparaison des rendus",
|
||||
"cmd.render.result.discard": "Écarter le résultat de rendu",
|
||||
"cmd.render.result.select": "Sélectionner le résultat de rendu",
|
||||
"cmd.render.result.discard": "Ignorer le résultat du rendu",
|
||||
"cmd.render.result.select": "Sélectionner le résultat du rendu",
|
||||
"cmd.render_aging_describe": "Vieillissement de surface en couches",
|
||||
"cmd.render_backends": "Moteurs de rendu",
|
||||
"cmd.render_batch": "Rendre toutes les prises de vue",
|
||||
@@ -1270,7 +1298,7 @@
|
||||
"cmd.timeline_rollback": "Déplacer le marqueur de chronologie",
|
||||
"cmd.timeline_stop": "Arrêter l'historique",
|
||||
"cmd.timeline_suppress": "Désactiver la fonction",
|
||||
"cmd.ui.assistant": "Afficher/masquer l'assistant",
|
||||
"cmd.ui.assistant": "Afficher ou masquer l'assistant",
|
||||
"cmd.view.render_browser": "Navigateur de rendu",
|
||||
"cmd.view.render_dock": "Déplacer le panneau de rendu",
|
||||
"cmd.view.render_focus": "Vue de rendu ciblée",
|
||||
@@ -1325,8 +1353,8 @@
|
||||
"color.step_up": "Augmenter d'un pas",
|
||||
"color.value": "Valeur, la luminosité (pour cent)",
|
||||
"config.column_filter_empty": "Aucune colonne correspondante",
|
||||
"config.rule_parameter_columns": "Seuls les paramètres ayant une colonne dans la table sont listés. Ajouter une colonne avec Ajouter une colonne (+) pour l'utiliser ici.",
|
||||
"config.rule_suppression_columns": "Seules les fonctions ayant une colonne Désactiver dans la table sont listées. Ajouter une colonne avec Ajouter une colonne (+) pour la piloter ici.",
|
||||
"config.rule_parameter_columns": "Seuls les paramètres disposant d'une colonne dans le tableau sont répertoriés. Ajoutez une colonne avec Ajouter une colonne (+) pour utiliser un paramètre ici.",
|
||||
"config.rule_suppression_columns": "Seules les fonctions disposant d'une colonne Supprimer dans le tableau sont répertoriées. Ajoutez une colonne avec Ajouter une colonne (+) pour les piloter ici.",
|
||||
"contact.components_count": "{count} composants",
|
||||
"contact.enabled_label": "activé",
|
||||
"coupling.gear_1": "Engrenage 1",
|
||||
@@ -1361,6 +1389,7 @@
|
||||
"crash.unclean_explanation": "Détecté lors d’un lancement ultérieur ; l’heure exacte de la sortie n’a pas été enregistrée. Un arrêt du système ou une interruption forcée peut aussi provoquer une sortie anormale.",
|
||||
"delete.and_more": "… et {count} de plus",
|
||||
"diagnostic.empty_boolean_component": "il n'y a aucun corps à couper ou à intersecter dans le composant « {component} » ; l'outil chevauche peut-être « {body} » dans le composant « {other} » : activez ce composant ou choisissez ce corps comme cible",
|
||||
"diagnostic.reselect_reference": "{feature} : la référence `{reference}` n'existe plus à l'emplacement où elle avait été sélectionnée ; sélectionnez-la à nouveau",
|
||||
"dialog.bodies_count": "{count} corps",
|
||||
"dialog.clearance_invalid": "le jeu doit être une longueur positive ou nulle",
|
||||
"dialog.compute": "Calculer",
|
||||
@@ -1381,7 +1410,7 @@
|
||||
"dialog.selection_constraint": "Contrainte {id}",
|
||||
"dialog.selection_external_curve": "{sketch} · courbe {id}",
|
||||
"dialog.selection_guidance": "Sélectionner une entrée pour la modifier. Cliquer sur un objet sélectionné pour le retirer ; Ctrl/Cmd-clic le bascule aussi. Vérifier l'aperçu, puis appuyer sur OK.",
|
||||
"dialog.selection_midpoint": "Point milieu · {id}",
|
||||
"dialog.selection_midpoint": "Milieu · {id}",
|
||||
"dialog.selection_profile": "{sketch} · profil {number}",
|
||||
"dialog.selection_step": "{step} sur {total} : sélectionner {input}",
|
||||
"dialog.step": "Étape",
|
||||
@@ -1431,6 +1460,14 @@
|
||||
"file_load.rebuilding": "Reconstruction de l’entité {done} sur {total}",
|
||||
"file_load.recovering": "Récupération de la conception",
|
||||
"file_load.reloading_cloud": "Rechargement du nuage de points",
|
||||
"file_load.step_build": "Construction du modèle",
|
||||
"file_load.step_feature": "Fonction {done} sur {total}",
|
||||
"file_load.step_part": "Pièce {done} sur {total}",
|
||||
"file_load.step_percent": "{percent} %",
|
||||
"file_load.step_read": "Lecture du fichier",
|
||||
"file_load.step_rebuild": "Reconstruction des fonctions",
|
||||
"file_load.step_repair": "Vérification et réparation des pièces",
|
||||
"file_load.step_show": "Préparation de la vue",
|
||||
"file_load.stopping": "Attente de l’arrêt de l’opération précédente...",
|
||||
"file_load.updating_links": "Mise à jour des liens",
|
||||
"file_load.waiting": "En attente d’une opération sur fichier",
|
||||
@@ -1467,7 +1504,7 @@
|
||||
"help.construct.axis.two_points": "Crée un axe de construction passant par deux points, sommets ou points d'esquisse. À utiliser pour un axe qui relie deux positions connues.",
|
||||
"help.construct.plane.along_path": "Crée un plan de construction perpendiculaire à une arête ou une courbe, à une position choisie le long de celle-ci. À utiliser pour esquisser le profil d'un balayage ou une coupe d'une trajectoire.",
|
||||
"help.construct.plane.at_angle": "Crée un plan de construction tourné d'un angle par rapport à un plan ou une face, autour d'un axe ou d'une arête. À utiliser pour des esquisses inclinées, par exemple une équerre à angle.",
|
||||
"help.construct.plane.axis_point": "Crée un plan de construction contenant un axe et un point situé hors de cet axe. Sélectionner une origine ou un axe de construction, une arête rectiligne ou une ligne d'esquisse, puis un sommet, un point d'esquisse ou un point de construction. Un point situé sur l'axe ne définit pas un plan unique.",
|
||||
"help.construct.plane.axis_point": "Crée un plan de construction contenant un axe et un point situé hors de cet axe. Sélectionnez une origine ou un axe de construction, une arête droite ou une ligne d'esquisse, puis un sommet, un point d'esquisse ou un point de construction. Un point situé sur l'axe ne permet pas de définir un plan unique.",
|
||||
"help.construct.plane.midplane": "Crée un plan de construction à mi-distance entre deux plans ou faces planes, ou bissecteur lorsqu'ils se rencontrent en formant un angle. À utiliser comme plan de symétrie.",
|
||||
"help.construct.plane.offset": "Crée un plan de construction parallèle à un plan ou une face plane, à une distance donnée ou passant par un point. À utiliser pour esquisser à une hauteur précise au-dessus d'une face.",
|
||||
"help.construct.plane.perpendicular": "Crée un plan de construction qui contient une droite ou une arête et qui est perpendiculaire à un plan ou une face. À utiliser pour esquisser à la verticale sur un modèle, le long d'une arête.",
|
||||
@@ -1527,6 +1564,11 @@
|
||||
"help.joint.reach": "Déplace un point d'une pièce vers une cible en modifiant les liaisons de sa chaîne, dans leurs limites. À utiliser pour positionner un mécanisme selon l'endroit où doit se trouver son extrémité, comme le bout d'un bras de robot.",
|
||||
"help.joint.rigid_group": "Verrouille ensemble les pièces sélectionnées telles qu'elles sont, pour qu'elles se déplacent d'un seul bloc. À utiliser pour des pièces qui vont ensemble et qui n'ont aucun mouvement entre elles.",
|
||||
"help.joint.screw": "Couple rotation et translation par un pas, de sorte que chaque tour avance de cette distance. À utiliser pour des vis mères, des boulons et des broches filetées.",
|
||||
"help.layout.apply": "Applique une disposition enregistrée à l'espace de travail actuel. Les éditeurs conservés gardent leurs brouillons.",
|
||||
"help.layout.get": "Lit la disposition validée et recense les espaces de travail enregistrés.",
|
||||
"help.layout.reset": "Rétablit la disposition par défaut enregistrée pour l'espace de travail actuel. Les préréglages de l'utilisateur restent disponibles.",
|
||||
"help.layout.save": "Enregistre la disposition complète sous un nom. Remplacer un préréglage de l'utilisateur nécessite une autorisation explicite d'écrasement.",
|
||||
"help.layout.workspace.select": "Sélectionne un espace de travail de disposition enregistré et mémorise la disposition quittée.",
|
||||
"help.library.apply": "Applique un matériau ou une apparence d'un fichier de bibliothèque local à des corps, des faces ou des composants. À utiliser pour réutiliser des matériaux enregistrés depuis une autre conception.",
|
||||
"help.library.export": "Enregistre les matériaux et apparences de la conception dans un fichier de bibliothèque. À utiliser pour les partager ou les réutiliser dans d'autres conceptions.",
|
||||
"help.library.inspect": "Vérifie un fichier de bibliothèque et liste ses matériaux et apparences, sans modifier la conception. À utiliser pour voir ce que contient une bibliothèque avant de l'appliquer.",
|
||||
@@ -1540,6 +1582,21 @@
|
||||
"help.notice": "NOTICE",
|
||||
"help.occurrence.ground": "Fixe une pièce en place, ou la libère, de sorte que les liaisons déplacent les autres pièces autour d'elle. À utiliser pour le châssis ou la base sur laquelle le reste de l'assemblage est construit.",
|
||||
"help.occurrence.move": "Déplace une pièce d’assemblage selon les seules libertés permises par ses liaisons. Sélectionnez une face de la pièce, puis faites glisser une flèche ou un arc disponible.",
|
||||
"help.panel.activate": "Sélectionne un onglet de panneau ouvert sans demander le focus clavier.",
|
||||
"help.panel.close": "Ferme un panneau via la protection du cycle de vie de son contenu. Son emplacement est mémorisé.",
|
||||
"help.panel.collapse": "Réduit ou développe une section de panneau en conservant les dimensions demandées.",
|
||||
"help.panel.dismiss": "Ferme l'affichage temporaire d'un panneau réduit.",
|
||||
"help.panel.float": "Déplace un panneau dans une section flottante positionnée explicitement.",
|
||||
"help.panel.focus": "Donne le focus à un panneau, en rouvrant son état conservé et en développant sa section si nécessaire.",
|
||||
"help.panel.list": "Lit les types de panneaux enregistrés, les instances validées, les onglets actifs, la disponibilité et les capacités de l'hôte.",
|
||||
"help.panel.move": "Déplace un panneau dans une nouvelle section ou le rattache à un groupe d'onglets existant.",
|
||||
"help.panel.native_close": "Replace une section de panneau natif dans son ancrage mémorisé sans annuler son contenu.",
|
||||
"help.panel.open": "Ouvre un type de panneau avec une identité d'instance explicite et un emplacement pour une nouvelle instance.",
|
||||
"help.panel.peek": "Affiche temporairement un panneau réduit sans modifier sa taille enregistrée ni son état réduit.",
|
||||
"help.panel.popout": "Déplace un panneau vers un hôte natif lorsque c'est pris en charge. Les hôtes de navigateur utilisent une section flottante.",
|
||||
"help.panel.reset_pair": "Rétablit le rapport de taille par défaut d'une paire de panneaux ancrés adjacents dans leurs limites communes.",
|
||||
"help.panel.resize": "Définit la largeur et la hauteur extérieures d'une section de panneau dans les limites de chaque onglet.",
|
||||
"help.panel.resize_pair": "Redimensionne ensemble des sections ancrées adjacentes en conservant leur étendue commune.",
|
||||
"help.parameters.change": "Ouvre le tableau des valeurs nommées et des expressions qui pilotent les cotes de la conception. À utiliser pour changer une dimension à un seul endroit et faire suivre toutes les fonctions qui l'utilisent.",
|
||||
"help.parameters.export": "Enregistre les paramètres de la conception en CSV ou JSON. À utiliser pour les modifier dans un tableur ou les transférer vers une autre conception.",
|
||||
"help.parameters.graph": "Montre quels paramètres et fonctions en utilisent quels autres, ainsi que les boucles ou erreurs entre eux. À utiliser pour voir ce que la modification d'un paramètre va affecter.",
|
||||
@@ -1726,6 +1783,7 @@
|
||||
"help.timeline.delete": "Supprime les fonctions sélectionnées de la chronologie ; supprimer une esquisse supprime aussi les fonctions construites à partir d'elle. À utiliser pour retirer une étape devenue inutile.",
|
||||
"help.timeline.dependents": "Liste les fonctions qui seraient supprimées avec une fonction, et celles qui échoueraient sans elle. À utiliser avant de supprimer ou de modifier une fonction.",
|
||||
"help.timeline.play": "Rejoue les fonctions restantes une par une, avec une pause d'une demi-seconde après chaque reconstruction. Relancez cette commande ou appuyez sur Échap pour arrêter ; Aller à la fin saute immédiatement.",
|
||||
"help.version": "Version {version}",
|
||||
"help.view.apply": "Oriente la vue selon une direction standard comme face, dessus ou iso, ou selon une vue nommée enregistrée. À utiliser pour regarder le modèle sous un angle fixe.",
|
||||
"help.view.delete": "Supprime une vue nommée enregistrée. Le modèle n'est pas modifié.",
|
||||
"help.view.fit": "Zoome et déplace la vue pour que tout le modèle, ou la sélection, remplisse la vue. À utiliser lorsque le modèle est sorti du champ.",
|
||||
@@ -1813,6 +1871,27 @@
|
||||
"home.start_hint": "Créez une conception, ouvrez un fichier récent ou explorez un exemple.",
|
||||
"home.whats_new": "Nouveautés",
|
||||
"home.yesterday": "Hier",
|
||||
"import_report.details": "Détails :",
|
||||
"import_report.file_one": "Un autre problème a été détecté dans le fichier.",
|
||||
"import_report.file_other": "{count} autres problèmes ont été détectés dans le fichier.",
|
||||
"import_report.hint": "Réexporter ces pièces depuis le logiciel d'origine peut résoudre le problème. La commande Copier le message d'avertissement fournit les détails.",
|
||||
"import_report.left_out_one": "Une face n'a pas pu être réparée et est manquante.",
|
||||
"import_report.left_out_other": "{count} faces n'ont pas pu être réparées et sont manquantes.",
|
||||
"import_report.needs_repair_one": "Une pièce doit être réparée avant de pouvoir servir à la création de nouvelles fonctions.",
|
||||
"import_report.needs_repair_other": "{count} pièces doivent être réparées avant de pouvoir servir à la création de nouvelles fonctions.",
|
||||
"import_report.not_imported_one": "Une pièce n'a pas pu être importée.",
|
||||
"import_report.not_imported_other": "{count} pièces n'ont pas pu être importées.",
|
||||
"import_report.not_shown_one": "Une face n'a pas pu être affichée et est masquée.",
|
||||
"import_report.not_shown_other": "{count} faces n'ont pas pu être affichées et sont masquées.",
|
||||
"import_report.open_one": "Une pièce présente des espaces entre ses faces et a été importée sous forme de corps ouvert.",
|
||||
"import_report.open_other": "{count} pièces présentent des espaces entre leurs faces et ont été importées sous forme de corps ouverts.",
|
||||
"import_report.refused_one": "Une pièce n'a pas pu être convertie en solide et n'a pas été importée.",
|
||||
"import_report.refused_other": "{count} pièces n'ont pas pu être converties en solides et n'ont pas été importées.",
|
||||
"import_report.repaired_one": "De petits défauts ont été réparés sur une pièce.",
|
||||
"import_report.repaired_other": "De petits défauts ont été réparés sur {count} pièces.",
|
||||
"import_report.solids": "{solids} pièces sur {parts} ont été importées sous forme de solides.",
|
||||
"import_report.surfaces_one": "Une pièce n'a pas pu être convertie en solide et a été importée sous forme de surfaces.",
|
||||
"import_report.surfaces_other": "{count} pièces n'ont pas pu être converties en solides et ont été importées sous forme de surfaces.",
|
||||
"install.button_tip": "Installer SolidCraft comme une app : il s'ouvre dans sa propre fenêtre et fonctionne hors ligne",
|
||||
"install.dock_1": "Choisissez Fichier › Ajouter au Dock.",
|
||||
"install.dock_2": "Cliquez sur Ajouter.",
|
||||
@@ -1837,7 +1916,18 @@
|
||||
"issue.note_save_failed": "Impossible d’enregistrer la capture d’écran : {error}",
|
||||
"issue.note_saved": "Capture d’écran enregistrée. Joignez le PNG dans le brouillon GitHub.",
|
||||
"issue.save_screenshot": "Enregistrer la capture d’écran…",
|
||||
"joint.find_limits": "Rechercher les limites",
|
||||
"joint.find_limits_failed": "La recherche des limites s'est interrompue à la suite d'une erreur.",
|
||||
"joint.find_limits_hint": "Définissez les limites à partir des positions où les pièces déplacées par cette liaison entrent en contact avec une autre pièce pour la première fois, en tournant ou en faisant coulisser chaque pièce dans les deux sens depuis sa position actuelle. L'opération s'effectue sur une copie : rien ne change avant de cliquer sur OK.",
|
||||
"joint.find_limits_stale": "La liaison ou la conception a changé depuis le calcul de ces limites. Recherchez-les à nouveau.",
|
||||
"joint.finding_limits": "Recherche des limites…",
|
||||
"joint.from_bodies_hint": "Chaque corps sélectionné passe dans un nouveau composant à lui et reste où il est.",
|
||||
"joint.limit_contact": "{side} {value} : {a} entre en contact avec {b}",
|
||||
"joint.limit_limit": "{side} {value} : limite imposée par une autre valeur ou une autre liaison",
|
||||
"joint.limit_loop": "{side} {value} : une boucle fermée ne peut pas se refermer au-delà de cette limite",
|
||||
"joint.limit_range": "{side} : aucun contact dans la plage {range} ; valeur inchangée",
|
||||
"joint.limit_turn": "{side} {value} : aucun contact après un tour complet",
|
||||
"joint.limits_overlapping": "Déjà en contact l'une avec l'autre ici : {pairs}. Elles n'interrompent la recherche que si elles s'enfoncent davantage l'une dans l'autre.",
|
||||
"joint.one_body": "Les deux sélections sont sur {body}. Choisissez la seconde sur une autre pièce.",
|
||||
"joint.one_component": "Ces pièces sont des corps d'un même composant : {bodies}. Une liaison déplace un composant par rapport à un autre, chaque pièce a donc besoin de son propre composant.",
|
||||
"joint.rigid_group_one_component": "Ces {count} corps sont tous dans un même composant (ou dans la conception elle-même) : utilisez d'abord {command}.",
|
||||
@@ -1845,8 +1935,8 @@
|
||||
"joint_move.blocked_hint": "Vérifiez le type de liaison (par exemple rigide), la fixation de la pièce, les limites de la liaison et les valeurs pilotées par des paramètres.",
|
||||
"joint_move.blocked_title": "Impossible de déplacer cette pièce",
|
||||
"joint_move.coarse": "Pas de rotation près de l’axe (°)",
|
||||
"joint_move.conflict": "Une liaison de cette pièce est en conflit avec les autres : {joint}.",
|
||||
"joint_move.conflict_hint": "Modifier, désactiver ou supprimer la liaison en conflit pour que les autres liaisons puissent placer la pièce.",
|
||||
"joint_move.conflict": "Une liaison de cette pièce est incompatible avec les autres : {joint}.",
|
||||
"joint_move.conflict_hint": "Modifiez, supprimez ou désactivez la liaison incompatible afin que les autres liaisons puissent positionner la pièce.",
|
||||
"joint_move.distance": "Distance depuis le départ",
|
||||
"joint_move.done": "Terminé",
|
||||
"joint_move.fine": "Pas de rotation loin de l’axe (°)",
|
||||
@@ -1947,7 +2037,7 @@
|
||||
"motion.track_name": "Piste {number}",
|
||||
"nav.alias.help": "Maj+Alt+glisser gauche fait orbiter, Maj+Alt+milieu fait un panoramique, Maj+Alt+droit zoome ; glisser avec le milieu fait aussi un panoramique et glisser avec le droit fait orbiter",
|
||||
"nav.blender.help": "Glisser avec le milieu fait orbiter, Maj+milieu fait un panoramique, Ctrl+milieu zoome ; glisser avec le droit ne touche pas la caméra",
|
||||
"nav.creo.help": "Glisser avec le milieu fait orbiter, Maj+milieu fait un panoramique, Ctrl+glisser avec le milieu zoome verticalement (vers le bas pour zoomer) ; la molette zoome",
|
||||
"nav.creo.help": "Faites glisser avec le bouton du milieu pour orbiter, Maj + bouton du milieu pour déplacer la vue, Ctrl + bouton du milieu pour zoomer verticalement (vers le bas pour zoomer avant) ; faites tourner la molette pour zoomer",
|
||||
"nav.creo.label": "Creo",
|
||||
"nav.free_orbit.help": "La souris et la souris 3D tournent en passant par les deux pôles et conservent le roulis. L'alignement des axes avec Maj est désactivé.",
|
||||
"nav.free_orbit.label": "Orbite libre",
|
||||
@@ -1958,7 +2048,7 @@
|
||||
"nav.hfss.help": "Alt+glisser gauche fait un panoramique, Maj+Alt+gauche zoome, Ctrl+glisser gauche sur un espace vide fait orbiter",
|
||||
"nav.inventor.help": "Glisser avec le milieu fait un panoramique, Maj+milieu fait orbiter, Ctrl+milieu zoome, glisser avec le droit fait orbiter",
|
||||
"nav.maya.help": "Alt+glisser gauche fait orbiter, Alt+milieu fait un panoramique, Alt+droit zoome ; glisser avec le milieu fait aussi un panoramique",
|
||||
"nav.nx.help": "Glisser avec le milieu fait orbiter, Maj+milieu fait un panoramique (milieu + droit dans NX), Ctrl+milieu zoome (milieu + gauche dans NX) ; glisser avec le droit ne touche pas la caméra",
|
||||
"nav.nx.help": "Faites glisser avec le bouton du milieu pour orbiter, Maj + bouton du milieu pour déplacer la vue (boutons du milieu + droit dans NX), Ctrl + bouton du milieu pour zoomer (boutons du milieu + gauche dans NX) ; faites glisser avec le bouton droit pour laisser la caméra en place",
|
||||
"nav.openscad.help": "Glisser avec le gauche dans le vide fait orbiter, Maj+glisser gauche sélectionne par rectangle, glisser la géométrie d'esquisse la modifie ; glisser avec le droit ou le milieu fait un panoramique, Maj+droit ou Maj+milieu zoome",
|
||||
"nav.perspective.sketch": "La modification d'une esquisse utilise la vue orthographique. Terminer l'esquisse pour passer en perspective.",
|
||||
"nav.right_drag_orbits.help": "Désactivé : glisser avec le droit ne touche pas la caméra et le bouton droit ouvre seulement le menu contextuel. Choisir l'affectation des boutons de la souris SolidWorks le désactive.",
|
||||
@@ -1977,6 +2067,12 @@
|
||||
"navbar.assistant": "Assistant",
|
||||
"navbar.custom.add_slot": "Ajouter {slot}",
|
||||
"navbar.custom.always": "Toujours visible",
|
||||
"navbar.custom.anchor.bottom_centre": "En bas au centre",
|
||||
"navbar.custom.anchor.bottom_left": "En bas à gauche",
|
||||
"navbar.custom.anchor.bottom_right": "En bas à droite",
|
||||
"navbar.custom.anchor.top_centre": "En haut au centre",
|
||||
"navbar.custom.anchor.top_left": "En haut à gauche",
|
||||
"navbar.custom.anchor.top_right": "En haut à droite",
|
||||
"navbar.custom.available": "{available} · faire glisser sur la barre, ou appuyer sur Ajouter",
|
||||
"navbar.custom.buttons": "Boutons",
|
||||
"navbar.custom.compact": "Compacte",
|
||||
@@ -2013,6 +2109,7 @@
|
||||
"navbar.custom.reset_default": "Réinitialiser par défaut",
|
||||
"navbar.custom.right": "Déplacer à droite",
|
||||
"navbar.custom.select": "Aucun emplacement sélectionné. Sélectionner un emplacement sur la barre pour le déplacer, le retirer ou modifier son apparence.",
|
||||
"navbar.custom.separator_hint": "Un séparateur entre des groupes de boutons. Le faire glisser sur la barre, ou appuyer sur Ajouter ; en utiliser autant que souhaité.",
|
||||
"navbar.custom.separators_full": "La barre compte déjà quatre séparateurs.",
|
||||
"navbar.custom.show": "Afficher la barre de navigation",
|
||||
"navbar.custom.shows": "Affiche",
|
||||
@@ -2152,8 +2249,28 @@
|
||||
"prefs.alt_frees_manipulators": "Alt / Option libère aussi les flèches du manipulateur",
|
||||
"prefs.anti_aliasing_amd_dx12": "L'anticrénelage est à 1× car la vérification au démarrage n'a rien dessiné avec le multiéchantillonnage et a réussi à 1×. Vous pouvez choisir un autre réglage ci-dessus ; redémarrez pour l'appliquer si la vérification réussit.",
|
||||
"prefs.anti_aliasing_note": "Adoucit les bords crénelés.",
|
||||
"prefs.appearance.colour_vision_help": "Modifie les couleurs porteuses de sens : états des esquisses, axes, pliages, analyses et icônes.",
|
||||
"prefs.appearance.desktop_only": "Version de bureau uniquement",
|
||||
"prefs.appearance.follow_help": "Recharge le fichier lorsqu'un autre outil le réécrit.",
|
||||
"prefs.appearance.interface_scale": "Échelle de l'interface",
|
||||
"prefs.appearance.next_themes": "Thèmes suivants",
|
||||
"prefs.appearance.option_count": "{count} options",
|
||||
"prefs.appearance.option_count_one": "{count} option",
|
||||
"prefs.appearance.previous_themes": "Thèmes précédents",
|
||||
"prefs.appearance.theme_count": "{count} thèmes",
|
||||
"prefs.appearance.theme_own": "Propre au thème",
|
||||
"prefs.appearance.viewport_colours": "Couleurs de la vue 3D",
|
||||
"prefs.appearance.viewport_logo": "Vue 3D et logo",
|
||||
"prefs.applies_on_restart": "Appliqué au redémarrage",
|
||||
"prefs.assistant": "Assistant",
|
||||
"prefs.assistant_connecting": "Connexion en cours",
|
||||
"prefs.assistant_follow_help": "Les vues normales aux esquisses déplacent la vue avec le pointeur.",
|
||||
"prefs.assistant_limit": "Limite",
|
||||
"prefs.assistant_limited": "Limité",
|
||||
"prefs.assistant_pointer_speed": "Vitesse du pointeur",
|
||||
"prefs.assistant_seconds": "secondes",
|
||||
"prefs.assistant_seconds_aria": "Secondes",
|
||||
"prefs.assistant_use_care": "À utiliser avec précaution",
|
||||
"prefs.auto_operation": "Choisir l'opération automatiquement",
|
||||
"prefs.auto_operation_note": "Les boîtes de dialogue des fonctions choisissent Joindre, Nouveau corps ou Couper d'après ce que touche la nouvelle matière, tant que vous n'en choisissez pas une vous-même. Désactivé : elles gardent l'opération avec laquelle elles s'ouvrent.",
|
||||
"prefs.axes": "Axes",
|
||||
@@ -2194,13 +2311,24 @@
|
||||
"prefs.curved_surfaces": "Surfaces courbes",
|
||||
"prefs.curves": "Surfaces courbes",
|
||||
"prefs.cut_preview_tint": "Afficher en rouge la matière retirée",
|
||||
"prefs.cut_preview_tint_help": "Un aperçu remplit la matière qu'une fonction retire, et la forme qu'elle remplace, d'un fantôme rouge translucide. Désactivée, ces remplissages sont entièrement transparents et seuls leurs contours sont tracés.",
|
||||
"prefs.dark_parts_shading": "Conserver la forme des pièces sombres",
|
||||
"prefs.dark_parts_shading_help": "Ombrer la vue en lumière linéaire avec un léger éclairage de ciel, pour que les faces sombres gardent un dégradé au lieu de devenir noires",
|
||||
"prefs.cut_preview_tint_help": "L'aperçu remplit d'une silhouette rouge translucide la matière retirée par une fonction ainsi que la forme qu'elle remplace. Lorsque cette option est désactivée, ces remplissages sont entièrement transparents et seuls leurs contours sont tracés.",
|
||||
"prefs.dark_parts_shading": "Préserver la forme des pièces sombres",
|
||||
"prefs.dark_parts_shading_help": "Éclaire la vue en lumière linéaire avec un remplissage doux simulant le ciel, afin que les faces sombres conservent un dégradé au lieu de devenir noires.",
|
||||
"prefs.dead_zone_note": "La bande hachurée est la zone morte : les mouvements à l'intérieur sont ignorés.",
|
||||
"prefs.default": "par défaut",
|
||||
"prefs.design": "Valeurs par défaut des conceptions",
|
||||
"prefs.design_note": "Ce avec quoi démarrent les nouvelles conceptions. Les conceptions ouvertes gardent les leurs.",
|
||||
"prefs.design_tools.ask": "Demander",
|
||||
"prefs.design_tools.degrees": "Degrés",
|
||||
"prefs.design_tools.double_click_help": "Ou pour modifier sur place un élément lié.",
|
||||
"prefs.design_tools.ghost": "Afficher l'ancienne position des pièces déplacées sous forme de fantôme",
|
||||
"prefs.design_tools.hole_moves_help": "Sélectionner à nouveau la face déplace le perçage au lieu de le supprimer.",
|
||||
"prefs.design_tools.hole_snaps_help": "Le milieu d'une face et les centres de ses arêtes circulaires.",
|
||||
"prefs.design_tools.imported_files": "Fichiers importés",
|
||||
"prefs.design_tools.note": "Remarque",
|
||||
"prefs.design_tools.off": "Désactivé",
|
||||
"prefs.design_tools.placement_group": "Appui, Bossage, Clip",
|
||||
"prefs.design_tools.rows": "Lignes",
|
||||
"prefs.devices": "Souris 3D",
|
||||
"prefs.dialog_buttons": "Boutons OK",
|
||||
"prefs.dialogs": "Dialogues",
|
||||
@@ -2221,6 +2349,18 @@
|
||||
"prefs.font_sample": "Portez ce vieux whisky au juge blond qui fume · Ø12,50 mm · 45,0° · 0123456789",
|
||||
"prefs.font_unreadable": "La police sélectionnée n'a pas pu être lue.",
|
||||
"prefs.general": "Général",
|
||||
"prefs.general.active": "Actif",
|
||||
"prefs.general.crash_reports": "Rapports de plantage",
|
||||
"prefs.general.edited": "Modifié",
|
||||
"prefs.general.held": "Maintenu",
|
||||
"prefs.general.import": "Importer…",
|
||||
"prefs.general.last_check": "Dernière vérification : {time}",
|
||||
"prefs.general.minutes": "Minutes",
|
||||
"prefs.general.name_setup": "Nommer cette configuration",
|
||||
"prefs.general.profile_name": "Nom du profil",
|
||||
"prefs.general.save_new": "Enregistrer comme nouveau",
|
||||
"prefs.general.step_import": "STEP et importation",
|
||||
"prefs.general.this_computer": "Cet ordinateur",
|
||||
"prefs.general_note": "Langue, enregistrement et mises à jour.",
|
||||
"prefs.gesture_orbit": "Orbite",
|
||||
"prefs.gesture_pan": "Panoramique",
|
||||
@@ -2230,8 +2370,25 @@
|
||||
"prefs.graphics_card_auto": "Automatique",
|
||||
"prefs.graphics_card_missing": "La carte graphique enregistrée n'est pas disponible ; Automatique est utilisé.",
|
||||
"prefs.graphics_card_restart": "Prend effet après le redémarrage de SolidCraft. WGPU_ADAPTER_NAME prévaut sur ce choix.",
|
||||
"prefs.graphics_card_unused": "La carte graphique enregistrée n'a pas été utilisée pour cette fenêtre ; la carte utilisée est indiquée dans Aide › À propos et dans la barre d'état. Essayer Automatique, ou définir WGPU_ADAPTER_NAME avec une partie unique du nom de la carte.",
|
||||
"prefs.graphics_card_unused": "La carte graphique enregistrée n'a pas été utilisée pour cette fenêtre ; la carte utilisée est indiquée dans Aide › À propos et dans la barre d'état. Essayez le mode Automatique ou définissez WGPU_ADAPTER_NAME avec une partie unique du nom de la carte.",
|
||||
"prefs.graphics_note": "Compromis entre vitesse et fluidité. Chaque choix montre son effet sur un exemple.",
|
||||
"prefs.graphics_page.current_view": "Vue actuelle",
|
||||
"prefs.graphics_page.fastest": "Le plus rapide",
|
||||
"prefs.graphics_page.fold_items": "Replier les éléments",
|
||||
"prefs.graphics_page.in_view": "Dans la vue",
|
||||
"prefs.graphics_page.live_details": "Détails en direct",
|
||||
"prefs.graphics_page.own_mix": "Votre propre combinaison",
|
||||
"prefs.graphics_page.quick_measure": "Mesure rapide",
|
||||
"prefs.graphics_page.reference_geometry_through_bodies": "Géométrie de référence à travers les corps",
|
||||
"prefs.graphics_page.restart": "Redémarrage nécessaire",
|
||||
"prefs.graphics_page.sharpest": "Le plus net",
|
||||
"prefs.graphics_page.single_surface_analysis": "Analyse d'une seule surface",
|
||||
"prefs.graphics_page.status_chips": "Pastilles d'état",
|
||||
"prefs.graphics_page.subtitle": "Compromis entre vitesse et fluidité.",
|
||||
"prefs.graphics_page.supersampling": "Suréchantillonnage",
|
||||
"prefs.graphics_page.supersampling_adaptive": "Seulement lorsque la vue est immobile",
|
||||
"prefs.graphics_page.surfaces_edges": "Surfaces et arêtes",
|
||||
"prefs.graphics_page.view_bar": "Aussi dans la barre de vue",
|
||||
"prefs.graphics_presets_note": "Les préréglages définissent ensemble les choix ci-dessous.",
|
||||
"prefs.hide_constraint_glyphs_zoomed_out": "Masquer les symboles de contraintes en cas de zoom arrière",
|
||||
"prefs.hide_constraint_glyphs_zoomed_out_note": "Les symboles de contraintes quittent la vue lorsque le zoom arrière sur l'esquisse est assez important pour qu'ils l'encombrent. Désactivé : ils gardent une taille fixe à l'écran quel que soit le zoom.",
|
||||
@@ -2245,8 +2402,8 @@
|
||||
"prefs.history_sketches_note": "Avec Esquisses réglé sur Sous leur fonction, l'historique de gauche liste chaque esquisse un niveau en retrait, sous la première fonction construite à partir d'elle, dès qu'il est assez large pour les noms. La chronologie en bas garde toujours l'ordre de création.",
|
||||
"prefs.history_sketches_under_feature": "Sous leur fonction",
|
||||
"prefs.hold_stop_snapping": "Maintenir pour désactiver l'accrochage",
|
||||
"prefs.home_fit_size": "Taille de Accueil et Cadrer",
|
||||
"prefs.home_fit_size_note": "Part de la vue que remplit le modèle quand Accueil, Cadrer, l'ouverture d'une conception ou une vue du repère de navigation recadre la vue, que le réglage ci-dessous soit activé ou non. 100 % : remplit la vue entre les panneaux, la boussole et la barre de navigation.",
|
||||
"prefs.home_fit_size": "Taille de la vue initiale et ajustement",
|
||||
"prefs.home_fit_size_note": "Détermine la place occupée par le modèle dans la vue lorsque la vue initiale, l'ajustement, une conception ouverte ou une vue du navigateur recadre l'affichage, que le réglage ci-dessous soit activé ou non. 100 % : le modèle remplit la zone entre les panneaux, la boussole et la barre de navigation.",
|
||||
"prefs.icons_only": "Icônes seules",
|
||||
"prefs.imported_file": "Fichier importé",
|
||||
"prefs.in_browser": "Dans le navigateur",
|
||||
@@ -2255,22 +2412,38 @@
|
||||
"prefs.interface_language": "Langue de l'interface",
|
||||
"prefs.interface_note": "L'apparence de SolidCraft et la place de ses éléments.",
|
||||
"prefs.interval_minutes": "{n} min",
|
||||
"prefs.invert_curved_roll_arrows": "Inverser les flèches courbes de roulis",
|
||||
"prefs.invert_curved_roll_arrows_note": "Les deux flèches courbes au coin du cube font rouler la vue dans le plan de l'écran. Activé : la flèche horaire fait rouler dans le sens antihoraire et la flèche antihoraire dans le sens horaire. Désactivé : chaque flèche fait rouler la vue dans le sens de sa courbure.",
|
||||
"prefs.invert_curved_roll_arrows": "Inverser les flèches de rotation courbe",
|
||||
"prefs.invert_curved_roll_arrows_note": "Les deux flèches courbes au coin du cube font pivoter la vue dans le plan de l'écran. Activé : la flèche horaire fait tourner la vue dans le sens antihoraire, et inversement. Désactivé : chaque flèche fait tourner la vue dans le sens indiqué par sa courbure.",
|
||||
"prefs.invert_navigator_arrows": "Inverser les flèches de rotation du cube de vue",
|
||||
"prefs.invert_navigator_arrows_note": "Les flèches autour du cube font orbiter la caméra dans le sens où elles pointent, comme dans Fusion et Inventor : la flèche de gauche pointe vers la droite et fait pivoter la caméra vers la droite. Désactivé : une flèche fait tourner le cube vers le côté où elle se trouve, donc la flèche de gauche fait pivoter la caméra vers la gauche. Les flèches courbes de roulis ne sont pas concernées.",
|
||||
"prefs.invert_navigator_arrows_note": "Les flèches autour du cube font orbiter la caméra dans la direction qu'elles indiquent, comme dans Fusion et Inventor : la flèche de gauche pointe vers la droite et fait pivoter la caméra vers la droite. Désactivé : une flèche fait tourner le cube vers le côté où elle se trouve ; la flèche de gauche fait donc pivoter la caméra vers la gauche. Les flèches courbes de rotation ne sont pas affectées.",
|
||||
"prefs.keep_work_on_tab_switch": "Garder dialogues et outils ouverts en changeant de conception",
|
||||
"prefs.keep_work_on_tab_switch_note": "Chaque onglet de conception garde son dialogue ou son outil ouvert, avec ce que vous y avez sélectionné et saisi, ainsi que son onglet de barre d'outils. Vous les retrouvez en revenant à la conception. Désactivé : changer de conception les annule et affiche l'onglet Modèle.",
|
||||
"prefs.labels": "Libellés",
|
||||
"prefs.language_system": "Système",
|
||||
"prefs.layout": "Disposition",
|
||||
"prefs.layout_note": "Compacte : ancre les panneaux aux bords de la fenêtre. La transparence du navigateur est disponible en mode Flottante. Changez le côté de l'assistant dans la page Assistant.",
|
||||
"prefs.layout_page.active_commands": "Mettre en évidence les commandes actives",
|
||||
"prefs.layout_page.always": "Toujours",
|
||||
"prefs.layout_page.card": "Carte",
|
||||
"prefs.layout_page.column": "Colonne",
|
||||
"prefs.layout_page.hover": "Survol",
|
||||
"prefs.layout_page.icons_labels": "Icônes + libellés",
|
||||
"prefs.layout_page.ok_cancel": "OK et Annuler",
|
||||
"prefs.layout_page.on_hover": "Au survol",
|
||||
"prefs.layout_page.open": "Ouvert",
|
||||
"prefs.layout_page.origin_bodies": "Origine et corps au premier plan",
|
||||
"prefs.layout_page.panels": "Panneaux",
|
||||
"prefs.layout_page.pinned_menus": "Commandes épinglées hors des menus",
|
||||
"prefs.layout_page.play_history": "Bouton Lire l'historique",
|
||||
"prefs.layout_page.slot_count": "{count} sur {max} emplacements",
|
||||
"prefs.layout_page.view_corner": "Aussi dans le coin de la vue",
|
||||
"prefs.layout_page.window": "Fenêtre",
|
||||
"prefs.left": "Gauche",
|
||||
"prefs.left_click": "Clic gauche",
|
||||
"prefs.line_drag_draws_one": "Appuyer et glisser trace une seule ligne",
|
||||
"prefs.line_drag_draws_one_note": "Dans l'outil Ligne, appuyer, faire glisser puis relâcher trace une seule ligne, du point d'appui au point de relâchement, et le tracé s'arrête là. Les clics tracent toujours une chaîne. Désactivé : un glissement place un point là où il est relâché, comme un clic.",
|
||||
"prefs.line_hover_tangent_arc": "S'arrêter sur le dernier point d'une ligne pour passer à un arc tangent",
|
||||
"prefs.line_hover_tangent_arc_note": "Dans l'outil Ligne, une fois un segment tracé, éloigner le pointeur du dernier point de la chaîne, revenir et le maintenir immobile dessus : le clic suivant termine un arc tangent, et le même geste revient aux lignes. Désactivé : s'arrêter là ne fait rien.",
|
||||
"prefs.line_hover_tangent_arc": "Survoler le dernier point d'une ligne pour passer à un arc tangent",
|
||||
"prefs.line_hover_tangent_arc_note": "Dans l'outil Ligne, après avoir tracé un segment, éloignez le pointeur du dernier point de la chaîne, revenez dessus et immobilisez le pointeur : le clic suivant termine un arc tangent. Le même geste permet de revenir aux lignes. Si l'option est désactivée, le survol immobile n'a aucun effet.",
|
||||
"prefs.linked_designs": "Conceptions liées",
|
||||
"prefs.live_input": "Saisie en direct",
|
||||
"prefs.live_preview": "Aperçu en direct",
|
||||
@@ -2295,9 +2468,16 @@
|
||||
"prefs.move_drag_highlights": "Mettre en évidence ce qui est sous le pointeur pendant que les flèches de Déplacer font glisser un composant",
|
||||
"prefs.move_drag_highlights_tip": "Désactivé : pendant que les flèches de Déplacer font glisser un composant, rien n’est mis en évidence sous le pointeur, ce qui garde les grands assemblages fluides. Avec une coupe ou une analyse affichée, la mise en évidence reste, et une pièce glissée le long de ses liaisons n’en montre jamais.",
|
||||
"prefs.navigation": "Navigation",
|
||||
"prefs.navigation.axes_signed": "Axes",
|
||||
"prefs.navigation.cube_compact": "Cube",
|
||||
"prefs.navigation.device": "Appareil",
|
||||
"prefs.navigation.free": "Libre",
|
||||
"prefs.navigation.orbit_style": "Style d'orbite",
|
||||
"prefs.navigation.radial_help": "Maintenez ou balayez le bouton droit pour afficher un anneau d'outils.",
|
||||
"prefs.navigation.turntable": "Plateau tournant",
|
||||
"prefs.navigation_note": "Comment la souris, le pavé tactile et la souris 3D déplacent la vue.",
|
||||
"prefs.navigator_fit": "Cadrer le modèle après un changement de vue du repère de navigation",
|
||||
"prefs.navigator_fit_note": "Une face, un coin ou une flèche du cube de vue, ou un axe du gizmo, regarde aussi le milieu du modèle depuis la distance unique qui le cadre sous tous les côtés (sa sphère englobante). Accueil utilise le même zoom et le même centre tant que cette option est activée, de sorte que les vues choisies ensuite ne font que tourner. Désactivé : la vue tourne sur place, en gardant sa cible et son zoom.",
|
||||
"prefs.navigator_fit": "Ajuster le modèle après un changement de vue du navigateur",
|
||||
"prefs.navigator_fit_note": "Une face, un coin ou une flèche du cube de vue, ainsi qu'un axe du gizmo, centre aussi la vue sur le modèle à la distance permettant de le voir en entier depuis toutes les directions (sa sphère englobante). Tant que cette option est activée, la touche Accueil utilise le même zoom et le même centrage : les vues choisies ensuite ne font que tourner. Désactivée, la vue pivote sur place en conservant sa cible et son zoom.",
|
||||
"prefs.network_host_remove": "Retirer",
|
||||
"prefs.network_locations": "Autoriser les emplacements réseau dans les conceptions",
|
||||
"prefs.network_locations_note": "Désactivé : les fichiers liés d'une conception situés sur un autre ordinateur (\\\\server\\share) ne sont ouverts que depuis les serveurs listés ici, ou après en avoir autorisé un sur demande.",
|
||||
@@ -2316,10 +2496,14 @@
|
||||
"prefs.persistent_ribbon_pressed_help": "Met en surbrillance les commandes du ruban tant que leurs effets sont actifs. Désactivez cette option pour conserver l'apparence neutre précédente et l'aide des commandes.",
|
||||
"prefs.perspective_fov": "Champ de vision",
|
||||
"prefs.placement": "Placement",
|
||||
"prefs.plugins_enabled": "Activé",
|
||||
"prefs.plugins_installed": "Installé",
|
||||
"prefs.plugins_intro": "Modules externes en bac à sable.",
|
||||
"prefs.plugins_show_folder": "Afficher le dossier des modules externes",
|
||||
"prefs.prefer_free_sketch_points": "Privilégier les points d'esquisse déplaçables quand des points se superposent",
|
||||
"prefs.preview_choices": "Aperçu de vos choix",
|
||||
"prefs.preview_tint_new_faces": "Teinter la nouvelle surface dans un aperçu",
|
||||
"prefs.preview_tint_new_faces_help": "L'aperçu d'une fonction qui modifie un corps peut tracer la surface qu'elle ajoute dans la couleur d'aperçu. Désactivée, le corps est tracé tel quel.",
|
||||
"prefs.preview_tint_new_faces": "Colorer les nouvelles surfaces dans l'aperçu",
|
||||
"prefs.preview_tint_new_faces_help": "L'aperçu d'une fonction qui modifie un corps peut colorer, avec la couleur d'aperçu, les surfaces qu'elle ajoute. Lorsque cette option est désactivée, le corps conserve son apparence normale.",
|
||||
"prefs.print_face_highlight": "Mise en évidence de la face d’impression",
|
||||
"prefs.print_face_highlight_tip": "Intensité de la teinte et du contour de la face d’impression d’un corps dans la vue. 0 % n’affiche aucune mise en évidence.",
|
||||
"prefs.profile_active": "Profil actif",
|
||||
@@ -2330,6 +2514,8 @@
|
||||
"prefs.profile_exported": "Profil exporté.",
|
||||
"prefs.profile_imported": "Profil importé. Choisissez-le sous Profil actif pour basculer dessus.",
|
||||
"prefs.profile_name_hint": "Nom du profil, par ex. Portable",
|
||||
"prefs.profile_operations": "Opérations du profil",
|
||||
"prefs.profile_operations_note": "Enregistre la durée des appels à SMLib, des opérations du noyau, des fonctions, des commandes et des importations. Les outils automatisés peuvent consulter ces données avec diagnostics.profile.",
|
||||
"prefs.profile_rename": "Renommer",
|
||||
"prefs.profile_renamed": "Profil renommé.",
|
||||
"prefs.profile_save": "Enregistrer",
|
||||
@@ -2348,8 +2534,9 @@
|
||||
"prefs.render_previous_geometry_budget": "Utiliser l'ancien budget de géométrie de l'aperçu Rendu",
|
||||
"prefs.render_previous_geometry_budget_help": "Rétablir l'ancienne limite fixe de géométrie (512 Mio sur un ordinateur 64 bits, 128 Mio ailleurs) au lieu du budget basé sur l'appareil.",
|
||||
"prefs.reports_saved": "Enregistrés : {n}",
|
||||
"prefs.ribbon_click_ends_tool": "Cliquer sur le bouton de l'outil en cours le termine",
|
||||
"prefs.ribbon_click_ends_tool_note": "Un clic sur le bouton allumé du ruban de l'outil d'esquisse en cours termine l'outil, et les clics dans la vue sélectionnent de nouveau. Désactivé : le clic relance l'outil.",
|
||||
"prefs.restore_page_defaults": "Rétablir les valeurs par défaut de la page",
|
||||
"prefs.ribbon_click_ends_tool": "Cliquer sur le bouton de l'outil actif termine l'outil",
|
||||
"prefs.ribbon_click_ends_tool_note": "Cliquer sur le bouton en surbrillance de l'outil d'esquisse actif termine cet outil, afin que les clics dans la vue servent à nouveau à sélectionner. Si l'option est désactivée, le clic relance l'outil.",
|
||||
"prefs.ribbon_reveal": "Montrer les résultats de recherche dans le ruban",
|
||||
"prefs.ribbon_reveal_note": "Survoler un résultat dans Rechercher des commandes montre où se trouve la commande dans le ruban : son onglet, son bouton ou sa ligne dans le menu déroulant d'un panneau. Une commande lancée depuis la recherche y clignote, et une commande en cours issue d'un menu déroulant signale son panneau.",
|
||||
"prefs.right_click": "Clic droit",
|
||||
@@ -2358,6 +2545,9 @@
|
||||
"prefs.scale_text": "Échelle et texte",
|
||||
"prefs.search": "Rechercher dans les paramètres",
|
||||
"prefs.search_empty": "Aucun paramètre correspondant",
|
||||
"prefs.section_hatch": "Hachures de coupe",
|
||||
"prefs.section_hatch_by_part": "Par pièce",
|
||||
"prefs.section_hatch_one": "Un seul style",
|
||||
"prefs.select": "Sélectionner",
|
||||
"prefs.select_one_item": "Sélectionner un élément",
|
||||
"prefs.select_other_hidden": "Sélectionner la géométrie masquée avec Sélectionner un autre",
|
||||
@@ -2367,10 +2557,45 @@
|
||||
"prefs.shift_add_ctrl_toggle": "Maj ajoute seulement ; Ctrl / Cmd bascule",
|
||||
"prefs.shift_add_note": "Activé : Maj ajoute, Ctrl / Cmd bascule. Désactivé (par défaut) : les deux basculent.",
|
||||
"prefs.shortcuts": "Raccourcis",
|
||||
"prefs.shortcuts_import": "Importer",
|
||||
"prefs.shortcuts_intro": "Les touches associées à chaque commande.",
|
||||
"prefs.shortcuts_not_assigned": "Non attribué",
|
||||
"prefs.shortcuts_press": "Appuyez sur une touche...",
|
||||
"prefs.single_surface_analysis": "Utiliser une seule analyse de surface",
|
||||
"prefs.single_surface_analysis_help": "Désactivé, l'ombrage de surface et Continuité peuvent rester actifs ensemble. Activé, seule la dernière analyse lancée ou modifiée est conservée.",
|
||||
"prefs.sketch.align_points": "S'aligner sur les autres points d'esquisse",
|
||||
"prefs.sketch.align_points_note": "Les lignes en cours de tracé s'alignent sur des points sur les deux axes à la fois.",
|
||||
"prefs.sketch.auto_dimensions": "Coter entièrement les nouvelles formes",
|
||||
"prefs.sketch.auto_dimensions_note": "Les valeurs saisies, plus toutes les cotes qui définissent la forme.",
|
||||
"prefs.sketch.auto_locate": "Placer depuis l'origine de l'esquisse",
|
||||
"prefs.sketch.auto_locate_note": "Avec cotation complète.",
|
||||
"prefs.sketch.center_arc": "L'arc par centre suit le curseur",
|
||||
"prefs.sketch.click_selects": "Le clic sélectionne",
|
||||
"prefs.sketch.conflict_colour": "Couleur de conflit",
|
||||
"prefs.sketch.drawing": "Dessin",
|
||||
"prefs.sketch.escape_twice_finishes": "Un double Échap termine l'esquisse",
|
||||
"prefs.sketch.escape_twice_finishes_note": "Deux pressions rapides sur Échap terminent l'esquisse. Désactivé : Échap annule seulement l'outil ou la sélection, et Terminer l'esquisse ferme l'esquisse.",
|
||||
"prefs.sketch.exit_keep": "Conserver",
|
||||
"prefs.sketch.exit_previous": "Revenir à la vue précédente",
|
||||
"prefs.sketch.exit_unless_rotated": "Sauf si la vue a tourné",
|
||||
"prefs.sketch.faces_edges": "Faces et arêtes",
|
||||
"prefs.sketch.hide_glyphs": "Masquer les symboles en cas de zoom arrière",
|
||||
"prefs.sketch.marks": "Repères dans l'esquisse",
|
||||
"prefs.sketch.note": "Dessin, accrochage et sélection.",
|
||||
"prefs.sketch.opening_closing": "Ouverture et fermeture",
|
||||
"prefs.sketch.prefer_free_points": "Privilégier les points mobiles en cas de chevauchement",
|
||||
"prefs.sketch.project_options": "Demander d'abord les options de projection",
|
||||
"prefs.sketch.recent_snap": "S'accrocher à l'intersection de deux guides",
|
||||
"prefs.sketch.select_other_hidden": "Sélectionner un autre atteint la géométrie masquée",
|
||||
"prefs.sketch.shortcut_cycles_modes": "Un nouvel appui sur le raccourci change de mode",
|
||||
"prefs.sketch.shortcut_cycles_modes_tip": "Désactivé : il relance l'outil.",
|
||||
"prefs.sketch.snapping_guides": "Accrochage et guides",
|
||||
"prefs.sketch.state_icons": "Icônes d'état",
|
||||
"prefs.sketch.tracking_guides": "Guides de centre et de point milieu",
|
||||
"prefs.sketch.tracking_guides_note": "Guides horizontaux et verticaux temporaires à partir des centres et des points milieux d'arêtes survolés.",
|
||||
"prefs.sketch.tracking_points": "Guides aussi depuis les points d'esquisse",
|
||||
"prefs.sketch.unless_turned_note": "retour si la vue n'a pas tourné",
|
||||
"prefs.sketch.whole_bodies": "Corps entiers",
|
||||
"prefs.sketch_align_points": "S'aligner sur d'autres points d'esquisse pendant le dessin",
|
||||
"prefs.sketch_align_points_note": "Pendant le dessin, un point s'aligne à la fois horizontalement sur un point d'esquisse et verticalement sur un autre, avec un guide en pointillés, et le clic conserve les deux alignements. Désactivé : uniquement sur le point précédent, un axe à la fois.",
|
||||
"prefs.sketch_conflict_colour": "Géométrie en conflit dans la couleur de conflit",
|
||||
@@ -2381,8 +2606,8 @@
|
||||
"prefs.sketch_exit_view.previous": "Revenir à la vue précédente",
|
||||
"prefs.sketch_exit_view.unless_rotated": "Revenir, sauf si la vue a été tournée",
|
||||
"prefs.sketch_exit_view_note": "Où va la vue après Terminer l'esquisse, Annuler ou un double Échap.",
|
||||
"prefs.sketch_face_activates_part": "Esquisser sur la face d'une pièce active cette pièce",
|
||||
"prefs.sketch_face_activates_part_note": "Une esquisse commencée sur une face du corps d'un autre composant active d'abord ce composant, de sorte que l'esquisse lui appartient et reste avec cette pièce dans le navigateur. La pièce reste ensuite active. Désactivé : l'esquisse appartient au composant actif.",
|
||||
"prefs.sketch_face_activates_part": "Esquisser sur une face active la pièce correspondante",
|
||||
"prefs.sketch_face_activates_part_note": "Lorsqu'une esquisse commence sur une face du corps d'un autre composant, ce composant est d'abord activé : l'esquisse lui appartient et reste avec cette pièce dans le navigateur. La pièce reste ensuite active. Si l'option est désactivée, l'esquisse appartient au composant actif.",
|
||||
"prefs.sketch_open_look_at": "Se placer face à l'esquisse à son ouverture",
|
||||
"prefs.sketch_open_look_at_note": "Désactivé : créer ou modifier une esquisse laisse la vue telle quelle. Vue normale place la vue face à l'esquisse quand vous le souhaitez.",
|
||||
"prefs.sketch_recent_snap": "Accrocher automatiquement aux centres et points milieux récents",
|
||||
@@ -2418,15 +2643,15 @@
|
||||
"prefs.structure.appearance_note": "Couleurs, texte et accessibilité.",
|
||||
"prefs.structure.in_profile": "Dans le profil",
|
||||
"prefs.structure.layout": "Disposition",
|
||||
"prefs.structure.layout_note": "Où se placent les parties de la fenêtre.",
|
||||
"prefs.structure.layout_note": "Position des éléments de la fenêtre.",
|
||||
"prefs.structure.look": "Aspect",
|
||||
"prefs.structure.measure_pointer": "Mesure et pointeur",
|
||||
"prefs.structure.mouse3d": "Souris 3D",
|
||||
"prefs.structure.mouse3d_note": "SpaceMouse et SpaceNavigator.",
|
||||
"prefs.structure.navigation_note": "Souris et pavé tactile. La souris 3D a sa propre page.",
|
||||
"prefs.structure.navigation_note": "Souris et pavé tactile. La souris 3D possède sa propre page.",
|
||||
"prefs.structure.profile": "Profil",
|
||||
"prefs.structure.profile_edited": "Modifié depuis l'enregistrement",
|
||||
"prefs.structure.profile_hover": "Enregistré dans les profils de réglages",
|
||||
"prefs.structure.profile_hover": "Enregistré dans les profils de paramètres",
|
||||
"prefs.structure.scale_percent": "{percent} %",
|
||||
"prefs.structure.sketch": "Esquisse",
|
||||
"prefs.structure.tools": "Outils",
|
||||
@@ -2474,6 +2699,12 @@
|
||||
"prefs.under_cursor": "Sous le curseur",
|
||||
"prefs.units_precision": "Unités et précision",
|
||||
"prefs.updates": "Mises à jour",
|
||||
"prefs.validation": "Vérification du corps",
|
||||
"prefs.validation.each_feature": "Une fois par fonction",
|
||||
"prefs.validation.each_step": "Après chaque étape",
|
||||
"prefs.validation.label": "Vérification complète du noyau géométrique",
|
||||
"prefs.validation.off": "Désactivée (expérimental)",
|
||||
"prefs.validation_note": "Après chaque étape : vérifie chaque balayage, opération booléenne et raccordement.\nUne fois par fonction : vérifie une seule fois le résultat de chaque fonction.\nDésactivée (expérimental) : aucune vérification.",
|
||||
"prefs.value_boxes_in_view": "Afficher les valeurs à côté de leurs poignées dans la vue",
|
||||
"prefs.value_boxes_in_view_tip": "La valeur d'une commande (distance, rayon…) dans une case à côté de sa poignée, par-dessus le modèle. Désactivé : vous la saisissez dans la fenêtre de la commande, qui prend le clavier après une sélection, et rien ne masque le modèle.",
|
||||
"prefs.view": "Comportement de la vue",
|
||||
@@ -2508,6 +2739,17 @@
|
||||
"recovery.just_now": "à l’instant",
|
||||
"recovery.min_ago": "il y a {count} min",
|
||||
"recovery.never_saved": "jamais enregistré",
|
||||
"refused.change": "Impossible de modifier {body}.",
|
||||
"refused.cut": "Impossible de soustraire de la matière à {body}.",
|
||||
"refused.face_curved": "L'une de ses faces courbes ne peut pas être utilisée pour la modélisation.",
|
||||
"refused.face_flat": "L'une de ses faces planes ne peut pas être utilisée pour la modélisation.",
|
||||
"refused.face_freeform": "L'une de ses faces de forme libre ne peut pas être utilisée pour la modélisation.",
|
||||
"refused.face_rounded": "L'une de ses faces arrondies ne peut pas être utilisée pour la modélisation.",
|
||||
"refused.faces_apart": "Ses faces ne sont pas suffisamment proches pour être utilisées en modélisation.",
|
||||
"refused.intersect": "Impossible de réaliser l'intersection avec {body}.",
|
||||
"refused.join": "Impossible de fusionner avec {body}.",
|
||||
"refused.repair": "Réparer la pièce",
|
||||
"refused.show_face": "Afficher la face",
|
||||
"render.adaptive_absolute": "Plancher d'erreur RVB absolu",
|
||||
"render.adaptive_coverage": "Erreur de couverture visée",
|
||||
"render.adaptive_enable": "Répartir les échantillons avec des pilotes indépendants",
|
||||
@@ -2619,9 +2861,9 @@
|
||||
"render.base_color": "Couleur de base · sRVB",
|
||||
"render.base_metallic": "Fraction métallique",
|
||||
"render.base_opaque_only": "Cet éditeur conserve la sémantique des corps opaques. Utilisez les commandes de verre dédiées pour la transmission optique.",
|
||||
"render.batch_all_shots": "Toutes les prises de vue ({count})",
|
||||
"render.batch_empty": "Enregistrer une prise de vue avant de rendre toutes les prises de vue.",
|
||||
"render.batch_limit": "Le rendu de toutes les prises de vue est limité à 32 prises de vue.",
|
||||
"render.batch_all_shots": "Tous les rendus ({count})",
|
||||
"render.batch_empty": "Enregistrez un rendu avant de lancer le rendu de tous les rendus.",
|
||||
"render.batch_limit": "Le rendu de tous les rendus est limité à 32 vues.",
|
||||
"render.batch_status": "{running} en cours · {waiting} en attente",
|
||||
"render.bloom_enable": "Halo lumineux (bloom) à l'affichage",
|
||||
"render.bloom_help": "Lueur créative appliquée à la sortie seulement, à partir des hautes lumières linéaires positives, étalée par trois passes de flou normalisées. Le rayon est en pixels de sortie. Ajoutée en lumière d'affichage linéaire avant sRVB ; ce n'est ni un effet d'objectif, ni un effet volumétrique, ni une amélioration de la convergence. L'EXR brut est inchangé.",
|
||||
@@ -3951,7 +4193,7 @@
|
||||
"sketch_text.formula": "Commencez par = pour composer le texte avec des paramètres : ='L' + number(Largeur)",
|
||||
"sketch_text.italic": "Italique",
|
||||
"sketch_text.loading_fonts": "Recherche des polices installées…",
|
||||
"sketch_text.no_bold": "La police intégrée n'a pas de graisse grasse : choisir une police installée",
|
||||
"sketch_text.no_bold": "La police intégrée ne possède pas de graisse ; choisissez une police installée.",
|
||||
"sketch_text.on_path": "Le texte suit sa trajectoire : la courbe le positionne",
|
||||
"sketch_text.path_clear": "Détacher le texte de sa courbe",
|
||||
"sketch_text.path_hint": "Une courbe de l'esquisse que le texte suit : cliquer ici, puis sur la courbe",
|
||||
@@ -3982,7 +4224,19 @@
|
||||
"the section's profiles must be in one sketch": "les profils de la section doivent être dans une seule esquisse",
|
||||
"the two origins are on the same component": "les deux origines se trouvent sur le même composant",
|
||||
"thread.automatic_size": "Taille automatique",
|
||||
"thread.chamfer_depth_needed": "nécessaire pour cette forme",
|
||||
"thread.designation": "Désignation",
|
||||
"thread.drill_range": "Le foret recommandé par le fabricant du taraud mesure {drill} mm. Le diamètre mineur normalisé du filetage intérieur est de {minor} mm. Un foret de {low} à {high} mm est accepté.",
|
||||
"thread.drill_range_custom": "Le diamètre du foret correspond au diamètre nominal moins le pas, soit {drill} mm. Le diamètre mineur normalisé du filetage intérieur est de {minor} mm. Un foret de {low} à {high} mm est accepté.",
|
||||
"thread.drill_range_taper": "Le foret recommandé par le fabricant du taraud mesure {drill} mm. Le diamètre mineur normalisé à l'extrémité du filetage est de {minor} mm. Un foret de {low} à {high} mm est accepté.",
|
||||
"thread.end_square": "Carré",
|
||||
"thread.fade_short": "1,25 P (ISO 3508)",
|
||||
"thread.fade_standard": "2,5 P (ISO 3508)",
|
||||
"thread.fits_the_face": "s'adapte à la face, par exemple {example}",
|
||||
"thread.form_bspp": "Filetage de tuyauterie G (ISO 228-1)",
|
||||
"thread.form_bspt": "Filetage conique de tuyauterie R, Rc (ISO 7-1)",
|
||||
"thread.form_npt": "Filetage conique de tuyauterie NPT (ASME B1.20.1)",
|
||||
"thread.form_rp": "Filetage de tuyauterie Rp (ISO 7-1)",
|
||||
"thread.iso_metric": "Métrique ISO",
|
||||
"thread.select_size": "Sélectionner la taille",
|
||||
"timeline.delete_after_marker_one": "Supprimer 1 fonction après le marqueur d'historique",
|
||||
@@ -4157,6 +4411,7 @@
|
||||
"ui.agent_chat_auth_terminal": "Exécuter ceci dans un terminal, puis appuyer de nouveau sur Connecter :",
|
||||
"ui.agent_chat_auth_title": "Authentification auprès de l'agent",
|
||||
"ui.agent_chat_cancel": "Annuler",
|
||||
"ui.agent_chat_cancel_timeout": "L'agent n'a pas répondu à la demande d'arrêt et a été déconnecté. Reconnectez-vous pour continuer.",
|
||||
"ui.agent_chat_cannot_start": "Installé, mais ne démarre pas : {error}",
|
||||
"ui.agent_chat_changes": "Modifications : {n}, en une seule étape d'annulation",
|
||||
"ui.agent_chat_changes_n": "Modifications : {n}",
|
||||
@@ -4216,16 +4471,16 @@
|
||||
"ui.agent_chat_mode_all": "Tout",
|
||||
"ui.agent_chat_mode_ask": "Demander",
|
||||
"ui.agent_chat_mode_edits": "Édition",
|
||||
"ui.agent_chat_model_custom": "Utiliser le modèle personnalisé : {model}",
|
||||
"ui.agent_chat_model_custom": "Utiliser le modèle personnalisé : {model}",
|
||||
"ui.agent_chat_model_no_tools": "{model} ne peut pas utiliser les outils de SolidCraft : il peut seulement discuter. Choisissez un modèle qui prend en charge les outils.",
|
||||
"ui.agent_chat_model_rejected": "L'agent n'a pas accepté {model} : {error}",
|
||||
"ui.agent_chat_model_rejected": "L'agent a refusé {model} : {error}",
|
||||
"ui.agent_chat_model_search": "Rechercher des modèles…",
|
||||
"ui.agent_chat_model_tip": "Le modèle utilisé par l'agent. Votre choix est mémorisé pour cet agent.",
|
||||
"ui.agent_chat_models_failed": "Impossible de lister les modèles : {error}",
|
||||
"ui.agent_chat_models_failed": "Impossible de répertorier les modèles : {error}",
|
||||
"ui.agent_chat_models_heading": "Modèles disponibles",
|
||||
"ui.agent_chat_models_listing": "Liste des modèles en cours…",
|
||||
"ui.agent_chat_models_none": "Le point d'accès ne liste aucun modèle",
|
||||
"ui.agent_chat_models_not_a_list": "La réponse n'était pas une liste de modèles",
|
||||
"ui.agent_chat_models_listing": "Répertoriage des modèles…",
|
||||
"ui.agent_chat_models_none": "Le point de terminaison ne répertorie aucun modèle",
|
||||
"ui.agent_chat_models_not_a_list": "La réponse ne contenait aucune liste de modèles",
|
||||
"ui.agent_chat_new": "Nouveau chat",
|
||||
"ui.agent_chat_new_confirm": "Démarrer un nouveau chat ? Le chat actuel sera effacé.",
|
||||
"ui.agent_chat_next_picture": "Image suivante",
|
||||
@@ -4234,6 +4489,7 @@
|
||||
"ui.agent_chat_no_images": "Cet agent n'accepte pas les images",
|
||||
"ui.agent_chat_no_picture": "Il n'y a pas d'image dans le presse-papiers",
|
||||
"ui.agent_chat_no_tool_call": "Le modèle n'a pas utilisé les outils de SolidCraft : la conception n'a donc pas été modifiée. Choisissez un modèle qui prend en charge l'appel d'outils ; voir Modèles locaux dans le guide du chat avec l'agent.",
|
||||
"ui.agent_chat_node_too_old": "La version de Node.js {version} est trop ancienne pour cet agent. Installez Node.js 20.10 ou une version ultérieure, puis cliquez sur Actualiser.",
|
||||
"ui.agent_chat_none_found": "Aucun agent de programmation trouvé. En installer un parmi ceux-ci, puis appuyer sur Actualiser :",
|
||||
"ui.agent_chat_none_found_short": "Aucun agent trouvé",
|
||||
"ui.agent_chat_not_installed": "Non installé",
|
||||
@@ -4361,9 +4617,9 @@
|
||||
"ui.ai_permissions": "Autorisations",
|
||||
"ui.ai_preset": "Préréglage",
|
||||
"ui.ai_protocol": "Protocole",
|
||||
"ui.ai_reasoning_effort": "Effort de raisonnement",
|
||||
"ui.ai_reasoning_effort": "Niveau de raisonnement",
|
||||
"ui.ai_reasoning_effort_field_hint": "vide = valeur par défaut du fournisseur",
|
||||
"ui.ai_reasoning_effort_hint": "Facultatif. Envoyé au point d'accès sous le nom `reasoning_effort` ; les valeurs acceptées varient selon le fournisseur (par exemple `low`, `high` ou `max`). Une valeur saisie ici n'est jamais remplacée par SolidCraft. Laisser vide pour ne rien envoyer et garder la valeur par défaut du fournisseur.",
|
||||
"ui.ai_reasoning_effort_hint": "Facultatif. Envoyé au point de terminaison sous le nom `reasoning_effort` ; les valeurs acceptées varient selon le fournisseur (par exemple `low`, `high` ou `max`). Une valeur définie ici n'est jamais remplacée par SolidCraft. Laissez ce champ vide pour ne rien envoyer et conserver la valeur par défaut du fournisseur.",
|
||||
"ui.ai_remove": "Retirer",
|
||||
"ui.ai_request_timed_out": "Le modèle a mis plus de {seconds} s. Vous pouvez augmenter le délai d'expiration des requêtes de ce point d'accès dans Préférences › Assistant.",
|
||||
"ui.ai_request_timeout": "Délai d'expiration des requêtes",
|
||||
@@ -4453,6 +4709,8 @@
|
||||
"ui.centerline": "Ligne de construction",
|
||||
"ui.chain": "Chaîne",
|
||||
"ui.chamfer": "Chanfrein",
|
||||
"ui.chamfer_angle": "Angle du chanfrein",
|
||||
"ui.chamfer_depth": "Profondeur du chanfrein",
|
||||
"ui.chamfer_type": "Type de chanfrein",
|
||||
"ui.change_workspace": "Changer d'espace de travail",
|
||||
"ui.circle": "Cercle",
|
||||
@@ -4484,10 +4742,16 @@
|
||||
"ui.colour_vision_sample": "Exemple",
|
||||
"ui.colour_vision_tritan": "Tritan",
|
||||
"ui.colour_vision_tritan_tip": "Pour une perception du bleu faible ou absente",
|
||||
"ui.comb_length": "Longueur des peignes",
|
||||
"ui.comb_length_tip": "Longueur des dents : un multiple de la longueur automatique, qui donne à la dent la plus longue une longueur égale au cinquième de la taille des courbes affichées.",
|
||||
"ui.comb_teeth": "Dents",
|
||||
"ui.comb_teeth_tip": "Nombre de dents de chaque peigne, régulièrement espacées le long de la courbe. Plus il y a de dents, plus les variations de courbure sont détaillées.",
|
||||
"ui.combine": "Combiner",
|
||||
"ui.coming_later": "bientôt disponible",
|
||||
"ui.command_done": "{command} terminé",
|
||||
"ui.command_palette_hint": "Tapez une commande, ex. {example} — ou S pour chercher",
|
||||
"ui.components_from_bodies_hint": "Crée un composant par corps sélectionné, portant le nom de ce corps, sous le composant actif.",
|
||||
"ui.components_from_bodies_required": "Sélectionnez au moins un corps.",
|
||||
"ui.concentric": "Concentricité",
|
||||
"ui.cone": "Cône",
|
||||
"ui.conic_curve": "Courbe conique",
|
||||
@@ -4500,22 +4764,30 @@
|
||||
"ui.construction.contact_hint": "Tangente : sélectionnez un cercle/arc ou une spline/conique ouverte, puis le point de contact (courbes libres : extrémités)",
|
||||
"ui.construction.external_hint": "Tangente : sélectionnez un cercle ou un arc, un point extérieur, puis la solution souhaitée",
|
||||
"ui.construction.free_hint": "Droite de construction : cliquez sur deux points ; clic droit pour recommencer",
|
||||
"ui.construction.normal_needs_length": "Une ligne infinie est toujours de construction : saisir une longueur pour tracer une ligne normale",
|
||||
"ui.construction.normal_needs_length": "Une droite infinie est toujours une ligne de construction : saisissez une longueur pour tracer une droite normale.",
|
||||
"ui.construction.point_hint": "Droite de construction : cliquez sur le point de passage",
|
||||
"ui.construction.reference_hint": "Droite de construction : sélectionnez une ligne droite, puis un point ; clic droit pour changer la référence",
|
||||
"ui.construction.ribbon_label": "Lignes aux.",
|
||||
"ui.construction.side_hint": "Ligne de construction : cliquer du côté vers lequel la ligne s'étend ; clic droit pour recommencer",
|
||||
"ui.construction.side_hint": "Ligne de construction : cliquez du côté vers lequel la ligne doit se prolonger ; clic droit pour recommencer.",
|
||||
"ui.context_menu": "Menu contextuel",
|
||||
"ui.continuity_crease": "Angle vif",
|
||||
"ui.continuity_curvature": "Courbure",
|
||||
"ui.continuity_curvature_change": "Variation de courbure",
|
||||
"ui.continuity_curvature_change_tip": "Variation de courbure (G3) : la courbure varie également de façon régulière de part et d'autre de la jonction.",
|
||||
"ui.continuity_curvature_tip": "Continuité de courbure (G2) : les reflets se prolongent sans cassure.",
|
||||
"ui.continuity_g0": "G0 angle vif",
|
||||
"ui.continuity_g1": "G1 tangence",
|
||||
"ui.continuity_g2": "G2 courbure",
|
||||
"ui.continuity_gap": "Écart",
|
||||
"ui.continuity_position": "Position",
|
||||
"ui.continuity_position_tip": "Position (G0) : les surfaces se rejoignent, avec une arête visible à la jonction.",
|
||||
"ui.continuity_smooth_curvature_change": "Variation régulière de la courbure",
|
||||
"ui.continuity_smooth_curvature_change_tip": "Variation régulière de la courbure (G4) : même l'évolution de la courbure se prolonge sans rupture à la jonction.",
|
||||
"ui.continuity_tangent": "Tangence",
|
||||
"ui.continuity_tangent_tip": "Tangence (G1) : aucune arête visible, mais la courbure présente une discontinuité à la jonction.",
|
||||
"ui.copy": "Copier",
|
||||
"ui.copy_details": "Copier les détails",
|
||||
"ui.copy_details_tip": "Copie le message complet pour permettre de le rechercher ou de le signaler.",
|
||||
"ui.corner": "Angle",
|
||||
"ui.corners": "Angles",
|
||||
"ui.cosmetic_thread_markings": "Marquages de filetage cosmétiques",
|
||||
@@ -4537,7 +4809,7 @@
|
||||
"ui.dark": "Sombre",
|
||||
"ui.default_modelling_orientation": "Orientation de modélisation par défaut",
|
||||
"ui.delete": "Supprimer",
|
||||
"ui.delete_select_first": "Sélectionner d'abord ce qu'il faut supprimer : fonctions, corps, composants ou géométrie d'esquisse",
|
||||
"ui.delete_select_first": "Sélectionnez d'abord les éléments à supprimer : fonctions, corps, composants ou géométrie d'esquisse.",
|
||||
"ui.depth": "Profondeur",
|
||||
"ui.design": "Conception",
|
||||
"ui.design_properties.author": "Auteur",
|
||||
@@ -4633,17 +4905,19 @@
|
||||
"ui.edit_sketch_empty": "Aucune esquisse à modifier",
|
||||
"ui.ellipse": "Ellipse",
|
||||
"ui.emboss_wrap_note": "Les profils de lignes orthogonales tangents à un cylindre pris en charge s'enroulent automatiquement. Choisir une paroi pour définir une cible.",
|
||||
"ui.end": "Fin",
|
||||
"ui.end_radius": "Rayon final",
|
||||
"ui.end_scale": "Échelle finale",
|
||||
"ui.ends": "Extrémités",
|
||||
"ui.entities": "Entités",
|
||||
"ui.equal": "Égalité",
|
||||
"ui.equation_end": "Fin",
|
||||
"ui.equation_explicit": "Explicite",
|
||||
"ui.equation_form": "Forme",
|
||||
"ui.equation_note": "La variable est un simple nombre : sin(t) la prend en radians. Un résultat sans unité est dans l'unité de la conception.",
|
||||
"ui.equation_note_range": "La variable est une longueur, comme sa plage : la combiner avec des paramètres de longueur, et la diviser par une longueur pour sin(). Un résultat sans unité est dans l'unité de la conception.",
|
||||
"ui.equation_note_range": "La variable est une longueur, comme l'indique son intervalle : combinez-la avec des paramètres de longueur et divisez-la par une longueur pour utiliser sin(). Un résultat sans unité est exprimé dans l'unité de la conception.",
|
||||
"ui.equation_parametric": "Paramétrique",
|
||||
"ui.equation_variable_unit": "La variable a l'unité de la plage",
|
||||
"ui.equation_variable_unit": "La variable utilise l'unité de l'intervalle",
|
||||
"ui.equation_x_of_t": "x(t)",
|
||||
"ui.equation_y_of_t": "y(t)",
|
||||
"ui.equation_y_of_x": "y(x)",
|
||||
@@ -4654,6 +4928,7 @@
|
||||
"ui.export_ellipsis_keymap": "Exporter…",
|
||||
"ui.export_keymap_tip": "Raccourcis, favoris de la boîte S et barre d'outils, dans un fichier",
|
||||
"ui.extend": "Prolonger",
|
||||
"ui.extent": "Étendue",
|
||||
"ui.extent_type": "Type de limite",
|
||||
"ui.extract_component": "Extraire dans un fichier…",
|
||||
"ui.extract_design_changed": "La conception a changé pendant le choix du fichier. Relancez Extraire dans un fichier.",
|
||||
@@ -4662,11 +4937,39 @@
|
||||
"ui.extrude_auto_to_object": "Extruder jusqu'à une cible choisie",
|
||||
"ui.extrude_auto_to_object_tip": "Dans Extrusion, avec un profil choisi, choisir une face, un sommet ou un plan parallèle hors de son plan fait passer la limite à Jusqu'à l'objet",
|
||||
"ui.factor": "Facteur",
|
||||
"ui.fade": "Atténuation",
|
||||
"ui.fade_length": "Longueur d'atténuation",
|
||||
"ui.feature_history": "Historique des fonctions",
|
||||
"ui.feature_options": "Options de la fonction",
|
||||
"ui.features": "Fonctions",
|
||||
"ui.file": "Fichier",
|
||||
"ui.fillet": "Congé",
|
||||
"ui.fillet_corner_ball": "Boule",
|
||||
"ui.fillet_corner_ball_tip": "Une portion de la sphère de la boule de raccordement, tangente (G1) à chaque arrondi.",
|
||||
"ui.fillet_corner_curvature_tip": "Courbure (G2) : un raccordement lisse. Le coin est reculé le long de chaque arête selon la valeur de retrait ({factor} × le rayon, sauf si vous saisissez une autre valeur), puis rempli par une surface de raccordement, afin que les reflets se prolongent sans cassure.",
|
||||
"ui.fillet_corner_needs_constant": "Les coins à raccordement lisse (G2) nécessitent un rayon constant et un ajustement exact.",
|
||||
"ui.fillet_corner_patch": "Raccordement lisse",
|
||||
"ui.fillet_corner_patch_tip": "Continuité de courbure (G2) : le coin est reculé le long de chaque arête puis rempli par une surface de raccordement, afin que les reflets se prolongent sans cassure.",
|
||||
"ui.fillet_corner_tangent_tip": "Tangence (G1) : un coin formé par une boule de raccordement, c'est-à-dire une portion de la sphère tangente à chaque arrondi.",
|
||||
"ui.fillet_error_corner": "Impossible de construire le raccordement lisse à cet endroit. Essayez une autre valeur de retrait ou des coins tangents.",
|
||||
"ui.fillet_error_failed": "Impossible de créer ce congé sur ces arêtes. Essayez un autre rayon ou arrondissez moins d'arêtes à la fois.",
|
||||
"ui.fillet_error_setback_short": "Le retrait est trop court pour le raccordement de ce coin : la construction commence à partir de {least}. Essayez un retrait plus long.",
|
||||
"ui.fillet_error_too_large": "Le rayon est trop grand pour les faces adjacentes à ces arêtes. Essayez un rayon plus petit ou réglez les limites des faces sur le rayon maximal.",
|
||||
"ui.fillet_fit": "Limites des faces",
|
||||
"ui.fillet_fit_exact": "Rayon exact",
|
||||
"ui.fillet_fit_needs_constant": "L'ajustement du rayon nécessite un rayon constant.",
|
||||
"ui.fillet_fit_reduce": "Rayon maximal",
|
||||
"ui.fillet_fit_taper": "Rayon réduit localement",
|
||||
"ui.fillet_fit_tip": "Lorsque le rayon dépasse ce que permettent les faces adjacentes à une arête :\nRayon exact : conserve le rayon demandé, ou ne crée aucun arrondi et indique pourquoi.\nRayon maximal : arrondit chaque arête avec le plus grand rayon compatible.\nRayon réduit localement : conserve le rayon demandé, mais réduit l'arrondi uniquement là où les faces ne le permettent plus.",
|
||||
"ui.fillet_options_tip": "Chaîne tangente : arrondit également les arêtes qui prolongent régulièrement celles sélectionnées.\nAperçu : affiche le résultat dans la vue pendant la modification.",
|
||||
"ui.fillet_setback": "Retrait",
|
||||
"ui.fillet_setback_hint": "{factor} × rayon",
|
||||
"ui.fillet_setback_least": "Supérieur à {least}",
|
||||
"ui.fillet_setback_tip": "Position de départ du raccordement lisse : distance mesurée depuis le coin le long de chaque arête. La valeur par défaut est {factor} × le rayon. Elle doit dépasser le retrait minimal, là où les arrondis se rejoignent sans raccordement supplémentaire : le rayon lorsque les faces sont perpendiculaires.",
|
||||
"ui.fillet_smooth_radius": "Variation progressive du rayon",
|
||||
"ui.fillet_type_choices_tip": "Rayon constant : un seul rayon sur toute l'arête.\nLongueur de corde : la largeur de l'arrondi reste identique, quel que soit l'angle entre les faces.\nRayon variable : un rayon à chaque extrémité, et d'autres le long de l'arête si vous en ajoutez.\nContinuité de courbure : une section sans cassure des reflets à la jonction avec les faces planes (G2).\nSpline : le rayon le long de l'arête suit les rayons de contrôle que vous définissez.",
|
||||
"ui.fillet_type_curvature": "Continuité de courbure",
|
||||
"ui.fillet_type_tip": "Section transversale de l'arête. Continuité de courbure : section à continuité de courbure (G2) entre les faces planes, afin que les reflets passent des faces à l'arrondi sans cassure.",
|
||||
"ui.filter_commands_or_keys": "Filtrer les commandes ou les touches",
|
||||
"ui.findInTimeline": "Trouver dans la chronologie",
|
||||
"ui.findInWindow": "Trouver dans la fenêtre",
|
||||
@@ -4799,6 +5102,7 @@
|
||||
"ui.history_sketch_listed_under": "Listé sous {feature}",
|
||||
"ui.history_title": "Historique",
|
||||
"ui.history_toggle_names": "Afficher ou masquer les noms des fonctions",
|
||||
"ui.history_waits_for_editor": "Les commandes Annuler, Rétablir et Historique attendent l'ouverture de l'éditeur de fonction.",
|
||||
"ui.hole": "Perçage",
|
||||
"ui.hole_tap_type": "Type de taraudage",
|
||||
"ui.hole_type": "Type de perçage",
|
||||
@@ -4816,6 +5120,7 @@
|
||||
"ui.inspect": "Inspecter",
|
||||
"ui.instances": "Instances",
|
||||
"ui.intersect": "Intersection",
|
||||
"ui.iso_4753": "ISO 4753",
|
||||
"ui.isolate": "Isoler",
|
||||
"ui.join": "Joindre",
|
||||
"ui.joint_play": "▶ Lire",
|
||||
@@ -4823,14 +5128,14 @@
|
||||
"ui.joints": "Liaisons",
|
||||
"ui.keyboard_shortcuts": "Raccourcis clavier",
|
||||
"ui.language": "Langue",
|
||||
"ui.lasso_select": "Lasso (faire glisser une boucle libre : prend ce qui est entièrement à l'intérieur)",
|
||||
"ui.lasso_select": "Lasso (dessinez une boucle à main levée : sélectionne les éléments entièrement à l'intérieur)",
|
||||
"ui.layout_compact": "Compacte",
|
||||
"ui.layout_floating": "Flottante",
|
||||
"ui.length": "Longueur",
|
||||
"ui.length_decimals": "Décimales des longueurs",
|
||||
"ui.light": "Clair",
|
||||
"ui.line": "Ligne",
|
||||
"ui.line_arc_hint": "Arc tangent : cliquer sur l'extrémité de l'arc. S'arrêter de nouveau sur le dernier point pour revenir aux lignes ; clic droit ou Échap pour terminer",
|
||||
"ui.line_arc_hint": "Arc tangent : cliquez sur l'extrémité de l'arc. Immobilisez de nouveau le pointeur sur le dernier point pour tracer des lignes ; clic droit ou Échap pour terminer.",
|
||||
"ui.link_copies": "Lier les copies identiques",
|
||||
"ui.link_copies_keep": "Conserver",
|
||||
"ui.link_copies_link": "Lier",
|
||||
@@ -4920,6 +5225,7 @@
|
||||
"ui.part_size_needs_a_part": "Sélectionnez une pièce standard insérée (vis, écrou, rondelle ou goupille) pour changer sa taille. Pour agrandir ou réduire un corps, utilisez Échelle.",
|
||||
"ui.part_size_shared": "Reconstruit la pièce en remplaçant les entités ajoutées. Toutes les occurrences de ce composant sont mises à jour.",
|
||||
"ui.paste": "Coller",
|
||||
"ui.patch_continuity_corner_tip": "La surface de raccordement rejoint les faces environnantes avec la continuité choisie le long de chaque côté. À un coin où ces faces se rejoignent avec des courbures différentes, elle reste tangente (G1).",
|
||||
"ui.path": "Trajectoire",
|
||||
"ui.pattern_object_type_tip": "Corps : formes pleines, choisies dans la vue ou le Navigateur ; chacun est copié en entier.\nFonctions : étapes de l'Historique, comme une extrusion ou un perçage, choisies dans l'Historique ou sur une face qu'elles ont créée ; l'étape est répétée.\nUne esquisse n'est ni l'un ni l'autre : répétez ses courbes avec la Répétition ou la Symétrie de l'esquisse, ou extrudez-la d'abord.",
|
||||
"ui.pattern_on_path": "Répétition sur trajectoire",
|
||||
@@ -5101,6 +5407,8 @@
|
||||
"ui.sketch_intersect_geometry": "Géométrie",
|
||||
"ui.sketch_intersect_projection_link": "Lien de projection",
|
||||
"ui.sketch_intersect_selection_filter": "Filtre de sélection",
|
||||
"ui.sketch_keys_only": "Désactiver les raccourcis du modèle dans les esquisses",
|
||||
"ui.sketch_keys_only_tip": "Pendant la modification d'une esquisse, seules les touches propres aux esquisses et celles qui fonctionnent partout sont actives. Une touche du modèle, comme E ou F, n'a aucun effet, évitant ainsi de fermer accidentellement une esquisse complexe.",
|
||||
"ui.sketch_modifiers": "Modificateurs d’esquisse",
|
||||
"ui.sketch_project_geometry": "Géométrie",
|
||||
"ui.sketch_report.all_constrained": "Tout est entièrement contraint.",
|
||||
@@ -5211,7 +5519,7 @@
|
||||
"ui.view_angles_roll": "Roulis",
|
||||
"ui.view_angles_unlock": "Déverrouiller {axis}",
|
||||
"ui.view_angles_yaw": "Lacet",
|
||||
"ui.view_angles_zero": "Mettre {axis} à 0°",
|
||||
"ui.view_angles_zero": "Régler {axis} sur 0°",
|
||||
"ui.view_centre": "Centre de la vue",
|
||||
"ui.viewport_status_clear": "Désactiver {name}",
|
||||
"ui.viewport_status_clear_hint": "Désactiver {name} · Échap",
|
||||
@@ -5313,7 +5621,7 @@
|
||||
"web.open_link": "Ouvrir la conception liée ?",
|
||||
"web.open_link_confirm": "Il y a des modifications non enregistrées. Ouvrir la conception liée dans un nouvel onglet ?",
|
||||
"↑ ↓ choose · Enter / Tab complete · Esc dismiss": "↑ ↓ choisir · Entrée / Tab compléter · Échap fermer",
|
||||
"↑ ↓ choose · Enter applies this value": "↑ ↓ choisir · Entrée applique cette valeur",
|
||||
"↑ ↓ choose · Enter applies this value": "↑ ↓ pour choisir · Entrée pour appliquer cette valeur",
|
||||
"↑ ↓ choose · Enter applies what you typed · Esc dismiss": "↑ ↓ choisir · Entrée applique la saisie · Échap fermer",
|
||||
"⌘Enter continues on GitHub.": "⌘Entrée continue sur GitHub."
|
||||
}
|
||||
|
||||
@@ -5041,7 +5041,7 @@
|
||||
"ui.agent_chat_permission": "エージェントが実行の許可を求めています: {title}",
|
||||
"ui.agent_chat_pick": "エージェント",
|
||||
"ui.agent_chat_pick_context": "コンテキストを選ぶ",
|
||||
"ui.agent_chat_pick_context_tip": "エージェントに見てほしい面、エッジ、フィーチャ、ボディをモデルから選び、OK を押します",
|
||||
"ui.agent_chat_pick_context_tip": "モデルの面、エッジ、フィーチャ、ボディを選んで OK を押すと、カーソルの位置にピルとしてメッセージに入ります(@ を入力しても同じです)",
|
||||
"ui.agent_chat_placeholder": "デザインの変更をエージェントに依頼…",
|
||||
"ui.agent_chat_placeholder_busy": "エージェントの作業が終わったら送るメッセージを入力(Ctrl+Enter: 今すぐ送信)",
|
||||
"ui.agent_chat_pop_out": "独立したウィンドウで開く(別の画面に移動できます)",
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"en": {
|
||||
"prefs.sketch.select_3d_curve_points": "Select 3D sketch curve points",
|
||||
"prefs.sketch.select_3d_curve_points_help": "Show and select points on drawn 3D sketch curves for construction references."
|
||||
},
|
||||
"de": {
|
||||
"prefs.sketch.select_3d_curve_points": "Punkte von 3D-Skizzenkurven auswählen",
|
||||
"prefs.sketch.select_3d_curve_points_help": "Punkte auf gezeichneten 3D-Skizzenkurven als Referenzen für Konstruktionselemente anzeigen und auswählen."
|
||||
},
|
||||
"ja": {
|
||||
"prefs.sketch.select_3d_curve_points": "3Dスケッチ曲線の点を選択",
|
||||
"prefs.sketch.select_3d_curve_points_help": "描画した3Dスケッチ曲線の点を表示し、構築要素の参照として選択します。"
|
||||
},
|
||||
"ko": {
|
||||
"prefs.sketch.select_3d_curve_points": "3D 스케치 곡선의 점 선택",
|
||||
"prefs.sketch.select_3d_curve_points_help": "그린 3D 스케치 곡선의 점을 표시하고 구성 요소의 참조로 선택합니다."
|
||||
},
|
||||
"zh": {
|
||||
"prefs.sketch.select_3d_curve_points": "选择 3D 草图曲线上的点",
|
||||
"prefs.sketch.select_3d_curve_points_help": "显示绘制的 3D 草图曲线上的点,并将其选作构造参照。"
|
||||
},
|
||||
"ar": {
|
||||
"prefs.sketch.select_3d_curve_points": "تحديد نقاط منحنيات الرسم ثلاثي الأبعاد",
|
||||
"prefs.sketch.select_3d_curve_points_help": "إظهار نقاط منحنيات الرسم ثلاثي الأبعاد المرسومة وتحديدها كمراجع للإنشاء."
|
||||
},
|
||||
"he": {
|
||||
"prefs.sketch.select_3d_curve_points": "בחירת נקודות על עקומות סקיצה תלת־ממדית",
|
||||
"prefs.sketch.select_3d_curve_points_help": "הצגה ובחירה של נקודות על עקומות סקיצה תלת־ממדית שצוירו, לשימוש כהפניות בנייה."
|
||||
},
|
||||
"vi": {
|
||||
"prefs.sketch.select_3d_curve_points": "Chọn điểm trên đường cong phác thảo 3D",
|
||||
"prefs.sketch.select_3d_curve_points_help": "Hiển thị và chọn các điểm trên đường cong phác thảo 3D đã vẽ để làm tham chiếu dựng hình."
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"en": {
|
||||
"ui.agent_chat_ctx_gone": "No longer in the design: it was changed or deleted."
|
||||
},
|
||||
"ja": {
|
||||
"ui.agent_chat_ctx_gone": "デザインにはもうありません(変更または削除されました)。"
|
||||
},
|
||||
"zh": {
|
||||
"ui.agent_chat_ctx_gone": "已不在设计中:它被修改或删除了。"
|
||||
},
|
||||
"ar": {
|
||||
"ui.agent_chat_ctx_gone": "لم يعد في التصميم: تم تغييره أو حذفه."
|
||||
},
|
||||
"he": {
|
||||
"ui.agent_chat_ctx_gone": "כבר לא בעיצוב: הוא שונה או נמחק."
|
||||
},
|
||||
"vi": {
|
||||
"ui.agent_chat_ctx_gone": "Không còn trong thiết kế: nó đã bị thay đổi hoặc xóa."
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"en": { "ui.agent_chat_transcript_assistant": "Assistant:", "ui.agent_chat_transcript_user": "User:" },
|
||||
"ar": { "ui.agent_chat_transcript_assistant": "المساعد:", "ui.agent_chat_transcript_user": "المستخدم:" },
|
||||
"de": { "ui.agent_chat_transcript_assistant": "Assistent:", "ui.agent_chat_transcript_user": "Benutzer:" },
|
||||
"he": { "ui.agent_chat_transcript_assistant": "עוזר:", "ui.agent_chat_transcript_user": "משתמש:" },
|
||||
"ja": { "ui.agent_chat_transcript_assistant": "アシスタント:", "ui.agent_chat_transcript_user": "ユーザー:" },
|
||||
"ko": { "ui.agent_chat_transcript_assistant": "어시스턴트:", "ui.agent_chat_transcript_user": "사용자:" },
|
||||
"vi": { "ui.agent_chat_transcript_assistant": "Trợ lý:", "ui.agent_chat_transcript_user": "Người dùng:" },
|
||||
"zh": { "ui.agent_chat_transcript_assistant": "助手:", "ui.agent_chat_transcript_user": "用户:" }
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"en": {
|
||||
"ui.agent_chat_state_no_design": "No design access",
|
||||
"ui.agent_chat_no_design_hint": "The agent runs without SolidCraft's tools, so it can't read or change the design: solidcraft-cli was not found next to the app. Install SolidCraft with solidcraft-cli beside it (on Windows, the MSI or the portable zip), or set SOLIDCRAFT_CLI to its path, then connect again.",
|
||||
"ui.agent_chat_tools_not_started": "The agent runs without SolidCraft's tools, so it can't read or change the design: solidcraft-cli was found, but its tools did not start (the error in the chat says why). Connect again; if it keeps happening, reinstall SolidCraft."
|
||||
},
|
||||
"ar": {
|
||||
"ui.agent_chat_state_no_design": "لا وصول إلى التصميم",
|
||||
"ui.agent_chat_no_design_hint": "يعمل الوكيل دون أدوات SolidCraft، لذا لا يستطيع قراءة التصميم أو تغييره: لم يُعثر على solidcraft-cli بجانب التطبيق. ثبّت SolidCraft مع solidcraft-cli بجانبه (في Windows: حزمة MSI أو ملف zip المحمول)، أو اضبط SOLIDCRAFT_CLI على مساره، ثم اتصل مرة أخرى.",
|
||||
"ui.agent_chat_tools_not_started": "يعمل الوكيل دون أدوات SolidCraft، لذا لا يستطيع قراءة التصميم أو تغييره: عُثر على solidcraft-cli، لكن أدواته لم تبدأ (رسالة الخطأ في المحادثة توضح السبب). اتصل مرة أخرى، وإذا تكرر ذلك فأعد تثبيت SolidCraft."
|
||||
},
|
||||
"he": {
|
||||
"ui.agent_chat_state_no_design": "אין גישה לתכן",
|
||||
"ui.agent_chat_no_design_hint": "הסוכן פועל בלי הכלים של SolidCraft, ולכן אינו יכול לקרוא או לשנות את התכן: solidcraft-cli לא נמצא ליד היישום. התקינו את SolidCraft עם solidcraft-cli לצידו (ב-Windows: קובץ ה-MSI או ה-zip הנייד), או הגדירו את SOLIDCRAFT_CLI לנתיב שלו, ואז התחברו שוב.",
|
||||
"ui.agent_chat_tools_not_started": "הסוכן פועל בלי הכלים של SolidCraft, ולכן אינו יכול לקרוא או לשנות את התכן: solidcraft-cli נמצא, אבל הכלים שלו לא הופעלו (הודעת השגיאה בצ'אט מסבירה למה). התחברו שוב, ואם זה חוזר, התקינו מחדש את SolidCraft."
|
||||
},
|
||||
"ja": {
|
||||
"ui.agent_chat_state_no_design": "デザインにアクセスできません",
|
||||
"ui.agent_chat_no_design_hint": "エージェントは SolidCraft のツールなしで動作しているため、デザインを読み取ることも変更することもできません。アプリの隣に solidcraft-cli が見つかりませんでした。solidcraft-cli が同梱された SolidCraft をインストールするか(Windows では MSI またはポータブル zip)、SOLIDCRAFT_CLI にそのパスを設定してから、もう一度接続してください。",
|
||||
"ui.agent_chat_tools_not_started": "エージェントは SolidCraft のツールなしで動作しているため、デザインを読み取ることも変更することもできません。solidcraft-cli は見つかりましたが、そのツールが起動しませんでした(理由はチャットのエラーに表示されています)。もう一度接続してください。繰り返し起きる場合は SolidCraft を再インストールしてください。"
|
||||
},
|
||||
"vi": {
|
||||
"ui.agent_chat_state_no_design": "Không truy cập được thiết kế",
|
||||
"ui.agent_chat_no_design_hint": "Tác tử đang chạy mà không có công cụ của SolidCraft, nên không thể đọc hay thay đổi thiết kế: không tìm thấy solidcraft-cli cạnh ứng dụng. Hãy cài SolidCraft có solidcraft-cli đi kèm (trên Windows: bản MSI hoặc bản zip di động), hoặc đặt SOLIDCRAFT_CLI thành đường dẫn của nó, rồi kết nối lại.",
|
||||
"ui.agent_chat_tools_not_started": "Tác tử đang chạy mà không có công cụ của SolidCraft, nên không thể đọc hay thay đổi thiết kế: đã tìm thấy solidcraft-cli, nhưng công cụ của nó không khởi động được (lỗi trong cuộc trò chuyện cho biết lý do). Hãy kết nối lại; nếu vẫn xảy ra, hãy cài lại SolidCraft."
|
||||
},
|
||||
"zh": {
|
||||
"ui.agent_chat_state_no_design": "无法访问设计",
|
||||
"ui.agent_chat_no_design_hint": "代理在没有 SolidCraft 工具的情况下运行,因此无法读取或修改设计:在应用旁边找不到 solidcraft-cli。请安装附带 solidcraft-cli 的 SolidCraft(在 Windows 上为 MSI 或便携版 zip),或将 SOLIDCRAFT_CLI 设置为它的路径,然后重新连接。",
|
||||
"ui.agent_chat_tools_not_started": "代理在没有 SolidCraft 工具的情况下运行,因此无法读取或修改设计:已找到 solidcraft-cli,但其工具未能启动(聊天中的错误信息说明了原因)。请重新连接;如果问题仍然出现,请重新安装 SolidCraft。"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
{
|
||||
"en": {
|
||||
"browser.straighten_angle": "Edge direction",
|
||||
"browser.straighten_choose": "Choose Horizontal, Vertical or Angle for the edge, then press Straighten.",
|
||||
"browser.straighten_click_a": "Click the image at one end of an edge that should be straight, or type its coordinates.",
|
||||
"browser.straighten_click_b": "Click the other end of the edge, or type its coordinates.",
|
||||
"browser.straighten_horizontal": "Horizontal",
|
||||
"browser.straighten_title": "Straighten: {name}",
|
||||
"browser.straighten_vertical": "Vertical",
|
||||
"cmd.canvas_straighten": "Straighten Canvas",
|
||||
"ui.straighten": "Straighten"
|
||||
},
|
||||
"ar": {
|
||||
"browser.straighten_angle": "اتجاه الحافة",
|
||||
"browser.straighten_choose": "اختر ما تصبح عليه الحافة، أفقية أو رأسية أو بزاوية، ثم اضغط تقويم.",
|
||||
"browser.straighten_click_a": "انقر الصورة عند أحد طرفي حافة يجب أن تكون مستقيمة، أو اكتب إحداثياتها.",
|
||||
"browser.straighten_click_b": "انقر الطرف الآخر للحافة، أو اكتب إحداثياته.",
|
||||
"browser.straighten_horizontal": "أفقي",
|
||||
"browser.straighten_title": "تقويم: {name}",
|
||||
"browser.straighten_vertical": "رأسي",
|
||||
"cmd.canvas_straighten": "تقويم اللوحة",
|
||||
"ui.straighten": "تقويم"
|
||||
},
|
||||
"de": {
|
||||
"browser.straighten_angle": "Richtung der Kante",
|
||||
"browser.straighten_choose": "Wählen Sie, wie die Kante liegen soll (Horizontal, Vertikal oder ein Winkel), und klicken Sie dann auf Ausrichten.",
|
||||
"browser.straighten_click_a": "Klicken Sie im Bild auf ein Ende einer Kante, die gerade sein soll, oder geben Sie die Koordinaten ein.",
|
||||
"browser.straighten_click_b": "Klicken Sie auf das andere Ende der Kante, oder geben Sie die Koordinaten ein.",
|
||||
"browser.straighten_horizontal": "Horizontal",
|
||||
"browser.straighten_title": "Ausrichten: {name}",
|
||||
"browser.straighten_vertical": "Vertikal",
|
||||
"cmd.canvas_straighten": "Zeichenfläche ausrichten",
|
||||
"ui.straighten": "Ausrichten"
|
||||
},
|
||||
"he": {
|
||||
"browser.straighten_angle": "כיוון הקצה",
|
||||
"browser.straighten_choose": "בחר מה יהיה הקצה, אופקי, אנכי או בזווית, ואז לחץ על יישור.",
|
||||
"browser.straighten_click_a": "לחץ על התמונה בקצה אחד של קצה שאמור להיות ישר, או הקלד את הקואורדינטות שלו.",
|
||||
"browser.straighten_click_b": "לחץ על הקצה השני, או הקלד את הקואורדינטות שלו.",
|
||||
"browser.straighten_horizontal": "אופקי",
|
||||
"browser.straighten_title": "יישור: {name}",
|
||||
"browser.straighten_vertical": "אנכי",
|
||||
"cmd.canvas_straighten": "יישור קנבס",
|
||||
"ui.straighten": "יישור"
|
||||
},
|
||||
"ja": {
|
||||
"browser.straighten_angle": "エッジの向き",
|
||||
"browser.straighten_choose": "エッジの向き(水平、垂直、または角度)を選んでから、[傾き補正]を押してください。",
|
||||
"browser.straighten_click_a": "まっすぐにしたいエッジの一端を画像上でクリックするか、座標を入力してください。",
|
||||
"browser.straighten_click_b": "エッジのもう一端をクリックするか、座標を入力してください。",
|
||||
"browser.straighten_horizontal": "水平",
|
||||
"browser.straighten_title": "傾き補正: {name}",
|
||||
"browser.straighten_vertical": "垂直",
|
||||
"cmd.canvas_straighten": "キャンバスの傾き補正",
|
||||
"ui.straighten": "傾き補正"
|
||||
},
|
||||
"ko": {
|
||||
"browser.straighten_angle": "모서리 방향",
|
||||
"browser.straighten_choose": "모서리 방향(수평, 수직 또는 각도)을 고른 다음 수평 맞추기를 누르세요.",
|
||||
"browser.straighten_click_a": "곧아야 하는 모서리의 한쪽 끝을 이미지에서 클릭하거나 좌표를 입력하세요.",
|
||||
"browser.straighten_click_b": "모서리의 다른 쪽 끝을 클릭하거나 좌표를 입력하세요.",
|
||||
"browser.straighten_horizontal": "수평",
|
||||
"browser.straighten_title": "수평 맞추기: {name}",
|
||||
"browser.straighten_vertical": "수직",
|
||||
"cmd.canvas_straighten": "캔버스 수평 맞추기",
|
||||
"ui.straighten": "수평 맞추기"
|
||||
},
|
||||
"vi": {
|
||||
"browser.straighten_angle": "Hướng của cạnh",
|
||||
"browser.straighten_choose": "Chọn hướng cho cạnh (Ngang, Dọc hoặc một góc), rồi nhấn Làm thẳng.",
|
||||
"browser.straighten_click_a": "Nhấp vào ảnh tại một đầu của cạnh cần thẳng, hoặc nhập tọa độ của nó.",
|
||||
"browser.straighten_click_b": "Nhấp vào đầu kia của cạnh, hoặc nhập tọa độ của nó.",
|
||||
"browser.straighten_horizontal": "Ngang",
|
||||
"browser.straighten_title": "Làm thẳng: {name}",
|
||||
"browser.straighten_vertical": "Dọc",
|
||||
"cmd.canvas_straighten": "Làm thẳng hình ảnh Canvas",
|
||||
"ui.straighten": "Làm thẳng"
|
||||
},
|
||||
"zh": {
|
||||
"browser.straighten_angle": "边的方向",
|
||||
"browser.straighten_choose": "选择边的方向(水平、垂直或角度),然后按“拉直”。",
|
||||
"browser.straighten_click_a": "在图像上单击应为直线的边的一端,或输入其坐标。",
|
||||
"browser.straighten_click_b": "单击该边的另一端,或输入其坐标。",
|
||||
"browser.straighten_horizontal": "水平",
|
||||
"browser.straighten_title": "拉直:{name}",
|
||||
"browser.straighten_vertical": "垂直",
|
||||
"cmd.canvas_straighten": "拉直画布",
|
||||
"ui.straighten": "拉直"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"en": {
|
||||
"ui.colour_vision_bends": "Bends"
|
||||
},
|
||||
"ar": {
|
||||
"ui.colour_vision_bends": "الثنيات"
|
||||
},
|
||||
"cs": {
|
||||
"ui.colour_vision_bends": "Ohyby"
|
||||
},
|
||||
"da": {
|
||||
"ui.colour_vision_bends": "Bukninger"
|
||||
},
|
||||
"de": {
|
||||
"ui.colour_vision_bends": "Biegungen"
|
||||
},
|
||||
"he": {
|
||||
"ui.colour_vision_bends": "כיפופים"
|
||||
},
|
||||
"ja": {
|
||||
"ui.colour_vision_bends": "曲げ"
|
||||
},
|
||||
"ko": {
|
||||
"ui.colour_vision_bends": "벤딩"
|
||||
},
|
||||
"nb": {
|
||||
"ui.colour_vision_bends": "Bøyninger"
|
||||
},
|
||||
"pl": {
|
||||
"ui.colour_vision_bends": "Gięcia"
|
||||
},
|
||||
"ru": {
|
||||
"ui.colour_vision_bends": "Гибы"
|
||||
},
|
||||
"vi": {
|
||||
"ui.colour_vision_bends": "Các vị trí chấn"
|
||||
},
|
||||
"zh": {
|
||||
"ui.colour_vision_bends": "折弯"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"en": {
|
||||
"prefs.constraint_glyph_size": "Constraint glyph size",
|
||||
"prefs.constraint_glyph_size_note": "How large constraint glyphs and their letters or icons are drawn in a sketch. 100% is the usual size; glyphs keep this screen size at every zoom."
|
||||
},
|
||||
"ar": {
|
||||
"prefs.constraint_glyph_size": "حجم رموز القيود",
|
||||
"prefs.constraint_glyph_size_note": "حجم رسم رموز القيود وحروفها أو أيقوناتها في الرسم. 100% هو الحجم المعتاد؛ وتحتفظ الرموز بهذا الحجم على الشاشة عند أي مستوى تكبير."
|
||||
},
|
||||
"de": {
|
||||
"prefs.constraint_glyph_size": "Größe der Bindungssymbole",
|
||||
"prefs.constraint_glyph_size_note": "Wie groß Bindungssymbole samt Buchstaben oder Icons in einer Skizze gezeichnet werden. 100 % ist die übliche Größe; die Symbole behalten diese Bildschirmgröße bei jedem Zoom."
|
||||
},
|
||||
"fr": {
|
||||
"prefs.constraint_glyph_size": "Taille des symboles de contraintes",
|
||||
"prefs.constraint_glyph_size_note": "Taille à laquelle les symboles de contraintes, avec leurs lettres ou icônes, sont dessinés dans une esquisse. 100 % est la taille habituelle ; les symboles gardent cette taille à l'écran quel que soit le zoom."
|
||||
},
|
||||
"he": {
|
||||
"prefs.constraint_glyph_size": "גודל סמלי האילוצים",
|
||||
"prefs.constraint_glyph_size_note": "הגודל שבו מצוירים סמלי האילוצים, עם האותיות או הסמלונים שלהם, בשרטוט. 100% הוא הגודל הרגיל; הסמלים שומרים על גודל המסך הזה בכל זום."
|
||||
},
|
||||
"ja": {
|
||||
"prefs.constraint_glyph_size": "拘束グリフのサイズ",
|
||||
"prefs.constraint_glyph_size_note": "スケッチ内の拘束グリフとその文字やアイコンを描く大きさ。100% が通常のサイズです。グリフはどのズームでもこの画面サイズを保ちます。"
|
||||
},
|
||||
"ko": {
|
||||
"prefs.constraint_glyph_size": "구속 조건 기호 크기",
|
||||
"prefs.constraint_glyph_size_note": "스케치에서 구속 조건 기호와 그 문자나 아이콘을 그리는 크기입니다. 100%가 기본 크기이며, 기호는 확대/축소와 관계없이 이 화면 크기를 유지합니다."
|
||||
},
|
||||
"vi": {
|
||||
"prefs.constraint_glyph_size": "Kích thước biểu tượng ràng buộc",
|
||||
"prefs.constraint_glyph_size_note": "Kích thước vẽ biểu tượng ràng buộc cùng chữ cái hoặc biểu tượng bên trong trong bản phác. 100% là kích thước thông thường; biểu tượng giữ kích thước màn hình này ở mọi mức thu phóng."
|
||||
},
|
||||
"zh": {
|
||||
"prefs.constraint_glyph_size": "约束符号大小",
|
||||
"prefs.constraint_glyph_size_note": "草图中约束符号及其字母或图标的绘制大小。100% 为常规大小;任意缩放比例下符号都保持此屏幕大小。"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
{
|
||||
"en": {
|
||||
"ui.construct_planes": "Planes",
|
||||
"ui.construct_axes": "Axes",
|
||||
"ui.construct_points": "Points",
|
||||
"prefs.construct_menu_groups": "Group Construct tools by entity type",
|
||||
"prefs.construct_menu_groups_help": "Show Planes, Axes and Points headings. Off keeps the original menu order."
|
||||
},
|
||||
"ar": {
|
||||
"ui.construct_planes": "المستويات",
|
||||
"ui.construct_axes": "المحاور",
|
||||
"ui.construct_points": "النقاط",
|
||||
"prefs.construct_menu_groups": "تجميع أدوات الإنشاء حسب نوع العنصر",
|
||||
"prefs.construct_menu_groups_help": "إظهار عناوين المستويات والمحاور والنقاط. يحافظ التعطيل على ترتيب القائمة الأصلي."
|
||||
},
|
||||
"he": {
|
||||
"ui.construct_planes": "מישורים",
|
||||
"ui.construct_axes": "צירים",
|
||||
"ui.construct_points": "נקודות",
|
||||
"prefs.construct_menu_groups": "קיבוץ כלי הבנייה לפי סוג ישות",
|
||||
"prefs.construct_menu_groups_help": "הצגת כותרות מישורים, צירים ונקודות. כיבוי שומר על סדר התפריט המקורי."
|
||||
},
|
||||
"ja": {
|
||||
"ui.construct_planes": "平面",
|
||||
"ui.construct_axes": "軸",
|
||||
"ui.construct_points": "点",
|
||||
"prefs.construct_menu_groups": "構築ツールを要素の種類でグループ化",
|
||||
"prefs.construct_menu_groups_help": "平面、軸、点の見出しを表示します。オフにすると元のメニュー順序を維持します。"
|
||||
},
|
||||
"zh": {
|
||||
"ui.construct_planes": "平面",
|
||||
"ui.construct_axes": "轴",
|
||||
"ui.construct_points": "点",
|
||||
"prefs.construct_menu_groups": "按实体类型分组构造工具",
|
||||
"prefs.construct_menu_groups_help": "显示平面、轴和点标题。关闭时保留原始菜单顺序。"
|
||||
},
|
||||
"de": {
|
||||
"ui.construct_planes": "Ebenen",
|
||||
"ui.construct_axes": "Achsen",
|
||||
"ui.construct_points": "Punkte",
|
||||
"prefs.construct_menu_groups": "Konstruktionswerkzeuge nach Elementtyp gruppieren",
|
||||
"prefs.construct_menu_groups_help": "Zeigt Überschriften für Ebenen, Achsen und Punkte. Aus behält die ursprüngliche Menüreihenfolge bei."
|
||||
},
|
||||
"ko": {
|
||||
"ui.construct_planes": "평면",
|
||||
"ui.construct_axes": "축",
|
||||
"ui.construct_points": "점",
|
||||
"prefs.construct_menu_groups": "요소 유형별로 구성 도구 그룹화",
|
||||
"prefs.construct_menu_groups_help": "평면, 축, 점 제목을 표시합니다. 끄면 원래 메뉴 순서를 유지합니다."
|
||||
},
|
||||
"vi": {
|
||||
"ui.construct_planes": "Các mặt phẳng",
|
||||
"ui.construct_axes": "Các trục",
|
||||
"ui.construct_points": "Các điểm",
|
||||
"prefs.construct_menu_groups": "Nhóm công cụ dựng theo loại đối tượng",
|
||||
"prefs.construct_menu_groups_help": "Hiện tiêu đề Mặt phẳng, Trục và Điểm. Tắt để giữ thứ tự menu ban đầu."
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
{
|
||||
"en": {
|
||||
"prefs.export": "Export",
|
||||
"prefs.export_name": "Export file name",
|
||||
"prefs.export_name.body": "Exported body's name (the first one when there are several)",
|
||||
"prefs.export_name.design": "Design name",
|
||||
"prefs.export_name_hint": "e.g. {design}-{body}",
|
||||
"prefs.export_name_sample": "Exporting this design offers: {name}",
|
||||
"prefs.export_name_tip": "The file name File › Export and Save As Mesh offer. These placeholders are replaced:\n{placeholders}\nA design property that is not set is left out. Leave the field empty to offer the design's name, or the body's for a mesh."
|
||||
},
|
||||
"ar": {
|
||||
"prefs.export": "التصدير",
|
||||
"prefs.export_name": "اسم ملف التصدير",
|
||||
"prefs.export_name.body": "اسم الجسم المُصدَّر (الأول إن تعددت الأجسام)",
|
||||
"prefs.export_name.design": "اسم التصميم",
|
||||
"prefs.export_name_hint": "مثلاً {design}-{body}",
|
||||
"prefs.export_name_sample": "تصدير هذا التصميم يقترح: {name}",
|
||||
"prefs.export_name_tip": "اسم الملف الذي يقترحه ملف › تصدير وحفظ كشبكة. تُستبدل هذه العناصر النائبة:\n{placeholders}\nتُحذف خاصية التصميم غير المعيّنة. اترك الحقل فارغاً لاقتراح اسم التصميم، أو اسم الجسم للشبكة."
|
||||
},
|
||||
"de": {
|
||||
"prefs.export": "Export",
|
||||
"prefs.export_name": "Dateiname beim Export",
|
||||
"prefs.export_name.body": "Name des exportierten Körpers (des ersten, wenn es mehrere sind)",
|
||||
"prefs.export_name.design": "Name des Designs",
|
||||
"prefs.export_name_hint": "z. B. {design}-{body}",
|
||||
"prefs.export_name_sample": "Beim Export dieses Designs vorgeschlagen: {name}",
|
||||
"prefs.export_name_tip": "Der Dateiname, den Datei › Exportieren und Als Netz speichern vorschlagen. Diese Platzhalter werden ersetzt:\n{placeholders}\nEine nicht gesetzte Konstruktionseigenschaft entfällt. Leer lassen, um den Namen des Designs vorzuschlagen, bei einem Netz den des Körpers."
|
||||
},
|
||||
"he": {
|
||||
"prefs.export": "ייצוא",
|
||||
"prefs.export_name": "שם קובץ הייצוא",
|
||||
"prefs.export_name.body": "שם הגוף המיוצא (הראשון כשיש כמה)",
|
||||
"prefs.export_name.design": "שם התכן",
|
||||
"prefs.export_name_hint": "לדוגמה {design}-{body}",
|
||||
"prefs.export_name_sample": "ייצוא התכן הזה מציע: {name}",
|
||||
"prefs.export_name_tip": "שם הקובץ שמציעים קובץ › ייצוא ושמירה כרשת משולשים. מצייני המיקום האלה מוחלפים:\n{placeholders}\nמאפיין תכן שלא הוגדר מושמט. השאירו את השדה ריק כדי להציע את שם התכן, או את שם הגוף לרשת."
|
||||
},
|
||||
"ja": {
|
||||
"prefs.export": "エクスポート",
|
||||
"prefs.export_name": "エクスポートのファイル名",
|
||||
"prefs.export_name.body": "エクスポートするボディ名(複数ある場合は最初のボディ)",
|
||||
"prefs.export_name.design": "デザイン名",
|
||||
"prefs.export_name_hint": "例: {design}-{body}",
|
||||
"prefs.export_name_sample": "このデザインのエクスポート時の名前: {name}",
|
||||
"prefs.export_name_tip": "ファイル › エクスポートとメッシュとして保存が提案するファイル名です。次のプレースホルダーが置き換えられます:\n{placeholders}\n設定されていないデザインのプロパティは省かれます。空のままにすると、デザイン名(メッシュではボディ名)を提案します。"
|
||||
},
|
||||
"ko": {
|
||||
"prefs.export": "내보내기",
|
||||
"prefs.export_name": "내보내기 파일 이름",
|
||||
"prefs.export_name.body": "내보내는 바디 이름(여러 개면 첫 번째 바디)",
|
||||
"prefs.export_name.design": "디자인 이름",
|
||||
"prefs.export_name_hint": "예: {design}-{body}",
|
||||
"prefs.export_name_sample": "이 디자인을 내보낼 때 제안되는 이름: {name}",
|
||||
"prefs.export_name_tip": "파일 › 내보내기와 메쉬로 저장이 제안하는 파일 이름입니다. 다음 자리 표시자가 바뀝니다:\n{placeholders}\n설정되지 않은 설계 속성은 빠집니다. 비워 두면 디자인 이름(메쉬의 경우 바디 이름)을 제안합니다."
|
||||
},
|
||||
"vi": {
|
||||
"prefs.export": "Xuất",
|
||||
"prefs.export_name": "Tên tệp khi xuất",
|
||||
"prefs.export_name.body": "Tên khối được xuất (khối đầu tiên nếu có nhiều)",
|
||||
"prefs.export_name.design": "Tên thiết kế",
|
||||
"prefs.export_name_hint": "vd. {design}-{body}",
|
||||
"prefs.export_name_sample": "Xuất thiết kế này sẽ đề xuất: {name}",
|
||||
"prefs.export_name_tip": "Tên tệp mà Tệp › Xuất tệp và Lưu dưới dạng lưới đa giác đề xuất. Các phần giữ chỗ này được thay thế:\n{placeholders}\nThuộc tính thiết kế chưa đặt sẽ bị bỏ qua. Để trống để đề xuất tên thiết kế, hoặc tên khối với lưới."
|
||||
},
|
||||
"zh": {
|
||||
"prefs.export": "导出",
|
||||
"prefs.export_name": "导出文件名",
|
||||
"prefs.export_name.body": "导出实体的名称(有多个时取第一个)",
|
||||
"prefs.export_name.design": "设计名称",
|
||||
"prefs.export_name_hint": "例如 {design}-{body}",
|
||||
"prefs.export_name_sample": "导出此设计时建议的名称:{name}",
|
||||
"prefs.export_name_tip": "文件 › 导出和另存为网格时建议的文件名。以下占位符会被替换:\n{placeholders}\n未设置的设计属性会被省略。留空则建议设计名称,网格则建议实体名称。"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"en": {
|
||||
"ui.export_selects_only_body": "Select the only body when exporting a mesh",
|
||||
"ui.export_selects_only_body_tip": "Export STL, Export 3MF and Send to Slicer start with the design's body selected when it has just one."
|
||||
},
|
||||
"de": {
|
||||
"ui.export_selects_only_body": "Einzigen Körper beim Mesh-Export auswählen",
|
||||
"ui.export_selects_only_body_tip": "Als STL exportieren, Als 3MF exportieren und An Slicer senden starten mit dem Körper des Designs ausgewählt, wenn es nur einen hat."
|
||||
},
|
||||
"ar": {
|
||||
"ui.export_selects_only_body": "تحديد الجسم الوحيد عند تصدير شبكة",
|
||||
"ui.export_selects_only_body_tip": "تبدأ أوامر تصدير STL وتصدير 3MF والإرسال إلى برنامج التقطيع بتحديد جسم التصميم عندما لا يحتوي إلا على جسم واحد."
|
||||
},
|
||||
"he": {
|
||||
"ui.export_selects_only_body": "בחירת הגוף היחיד בייצוא רשת",
|
||||
"ui.export_selects_only_body_tip": "ייצוא STL, ייצוא 3MF ושליחה לסלייסר מתחילים כשגוף התכנון כבר נבחר, כשיש בו גוף אחד בלבד."
|
||||
},
|
||||
"ja": {
|
||||
"ui.export_selects_only_body": "メッシュのエクスポート時に唯一のボディを選択する",
|
||||
"ui.export_selects_only_body_tip": "デザインのボディが 1 つだけのとき、STL をエクスポート、3MF をエクスポート、スライサーに送るはそのボディを選択した状態で始まります。"
|
||||
},
|
||||
"ko": {
|
||||
"ui.export_selects_only_body": "메시 내보내기 시 유일한 바디 선택",
|
||||
"ui.export_selects_only_body_tip": "디자인에 바디가 하나뿐이면 STL 내보내기, 3MF 내보내기, 슬라이서로 보내기가 그 바디를 선택한 상태로 시작합니다."
|
||||
},
|
||||
"vi": {
|
||||
"ui.export_selects_only_body": "Chọn khối duy nhất khi xuất lưới",
|
||||
"ui.export_selects_only_body_tip": "Xuất tệp STL, Xuất tệp 3MF và Gửi sang phần mềm cắt lớp bắt đầu với khối của thiết kế đã được chọn khi thiết kế chỉ có một khối."
|
||||
},
|
||||
"zh": {
|
||||
"ui.export_selects_only_body": "导出网格时选中唯一的实体",
|
||||
"ui.export_selects_only_body_tip": "设计只有一个实体时,导出 STL、导出 3MF 和发送到切片软件会在打开时选中该实体。"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"ar": {
|
||||
"prefs.fillet_legacy_radius": "استخدم نصف قطر Fillet الصلب الافتراضي السابق",
|
||||
"prefs.fillet_legacy_radius.help": "مطفأ افتراضيًا. عند التشغيل، يفتح Fillet الصلب الجديد عند الرقم 2 مقروءًا بوحدات التصميم (\"2 بوصة\" في تصميم بالبوصة)، كما كان سابقًا؛ وعند الإيقاف، يفتح عند نصف القطر الذي تُسلَّم به الأداة، 2 مم، معروضًا بوحدات التصميم (\"0.07874 بوصة\" في تصميم بالبوصة)."
|
||||
},
|
||||
"de": {
|
||||
"prefs.fillet_legacy_radius": "Den vorherigen Standardradius für Solid-Fillet verwenden",
|
||||
"prefs.fillet_legacy_radius.help": "Standardmäßig aus. Ein: Ein neuer Solid-Fillet öffnet mit der in den Einheiten des Designs gelesenen Zahl 2 (\"2 in\" in einem Design in Zoll), wie zuvor; aus: Er öffnet mit dem Radius, mit dem das Werkzeug ausgeliefert wird, 2 mm, in den Einheiten des Designs angezeigt (\"0.07874 in\" in einem Design in Zoll)."
|
||||
},
|
||||
"en": {
|
||||
"prefs.fillet_legacy_radius": "Use the previous Solid Fillet radius default",
|
||||
"prefs.fillet_legacy_radius.help": "Off by default. When on, a new Solid Fillet opens at the number 2 read in the design's units (\"2 in\" in an inch design), as before; when off, it opens at the radius the tool ships with, 2 mm, shown in the design's units (\"0.07874 in\" in an inch design)."
|
||||
},
|
||||
"he": {
|
||||
"prefs.fillet_legacy_radius": "השתמש בברירת המחדש הקודמת לרדיוס Fillet מוצק",
|
||||
"prefs.fillet_legacy_radius.help": "כבוי כברירת מחדש. כשהוא פעיל, Solid Fillet חדש נפתח במספר 2 שנקרא ביחידות התכנון (\"2 אינץ\" בתכנון באינצ'ים), כמו קודם; כשהוא כבוי, הוא נפתח ברדיוס שבו הכלי נמסר, 2 מ\"מ, מוצג ביחידות התכנון (\"0.07874 אינץ\" בתכנון באינצ'ים)."
|
||||
},
|
||||
"ja": {
|
||||
"prefs.fillet_legacy_radius": "以前のフィレット半径の既定値を使う",
|
||||
"prefs.fillet_legacy_radius.help": "既定ではオフです。オンのとき:新しい Solid Fillet は設計の単位として読み取った数値 2(「2 in」)で始まり、以前と同じです。オフのとき:そのツールが標準で持つ半径 2 mm を設計の単位に換算した値(「0.07874 in」)で始まります。"
|
||||
},
|
||||
"ko": {
|
||||
"prefs.fillet_legacy_radius": "이전 필렛 반지름 기본값 사용",
|
||||
"prefs.fillet_legacy_radius.help": "기본적으로 꺼짐입니다. 켜면: 새 Solid Fillet은 설계 단위로 읽힌 숫자 2(\"2 in\")로 시작하며 이전과 같습니다. 끄면: 그 도구가 기본으로 제공하는 반지름 2 mm를 설계 단위로 표시한 값(\"0.07874 in\")으로 시작합니다."
|
||||
},
|
||||
"vi": {
|
||||
"prefs.fillet_legacy_radius": "Dùng giá trị mặc định bán kính Fillet trước đây",
|
||||
"prefs.fillet_legacy_radius.help": "Mặc định tắt. Khi bật: Solid Fillet mới bắt đầu với số 2 được đọc theo đơn vị của thiết kế (\"2 in\"), như trước; khi tắt: nó bắt đầu với bán kính mà công cụ được giao, 2 mm, hiển thị theo đơn vị của thiết kế (\"0.07874 in\")."
|
||||
},
|
||||
"zh": {
|
||||
"prefs.fillet_legacy_radius": "使用之前的圆角半径默认值",
|
||||
"prefs.fillet_legacy_radius.help": "默认关闭。开启时:新的 Solid Fillet 以按设计单位读取的数字 2(\"2 in\")开始,与之前相同。关闭时:它以该工具自带的半径 2 mm 开始,并按设计的单位显示(\"0.07874 in\")。"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"en": {
|
||||
"ui.first_dimension_scales_about_origin": "Scale about the sketch origin",
|
||||
"ui.first_dimension_scales_about_origin_tip": "On: the drawing always grows or shrinks about the sketch origin, so a shape drawn away from the origin moves. Off: a drawing that nothing ties to the origin scales about its own middle and stays where it was drawn."
|
||||
},
|
||||
"ar": {
|
||||
"ui.first_dimension_scales_about_origin": "تغيير المقياس حول أصل الرسم التخطيطي",
|
||||
"ui.first_dimension_scales_about_origin_tip": "عند التفعيل: يكبر الرسم أو يصغر دائمًا حول أصل الرسم التخطيطي، فيتحرك الشكل المرسوم بعيدًا عن الأصل. عند الإيقاف: الرسم غير المرتبط بالأصل يتغير مقياسه حول منتصفه ويبقى في مكانه."
|
||||
},
|
||||
"de": {
|
||||
"ui.first_dimension_scales_about_origin": "Um den Skizzenursprung skalieren",
|
||||
"ui.first_dimension_scales_about_origin_tip": "Ein: Die Zeichnung wird immer um den Skizzenursprung vergrößert oder verkleinert, eine vom Ursprung entfernt gezeichnete Form verschiebt sich also. Aus: Eine Zeichnung, die nichts an den Ursprung bindet, wird um ihre eigene Mitte skaliert und bleibt an ihrem Platz."
|
||||
},
|
||||
"he": {
|
||||
"ui.first_dimension_scales_about_origin": "שינוי קנה מידה סביב ראשית הסקיצה",
|
||||
"ui.first_dimension_scales_about_origin_tip": "מופעל: הציור תמיד גדל או קטן סביב ראשית הסקיצה, כך שצורה שצוירה הרחק מהראשית זזה. כבוי: ציור שדבר אינו קושר לראשית משנה קנה מידה סביב מרכזו ונשאר במקומו."
|
||||
},
|
||||
"ja": {
|
||||
"ui.first_dimension_scales_about_origin": "スケッチ原点を中心にスケールする",
|
||||
"ui.first_dimension_scales_about_origin_tip": "オン: 図形は常にスケッチ原点を中心に拡大・縮小されるため、原点から離れて描いた図形は移動します。オフ: 原点に拘束されていない図形は自身の中心を基準にスケールし、描いた位置に留まります。"
|
||||
},
|
||||
"ko": {
|
||||
"ui.first_dimension_scales_about_origin": "스케치 원점을 기준으로 배율 조정",
|
||||
"ui.first_dimension_scales_about_origin_tip": "켜기: 도면이 항상 스케치 원점을 기준으로 커지거나 작아지므로 원점에서 떨어져 그린 도형은 이동합니다. 끄기: 원점에 묶이지 않은 도면은 자신의 중심을 기준으로 배율이 바뀌고 그린 자리에 그대로 있습니다."
|
||||
},
|
||||
"vi": {
|
||||
"ui.first_dimension_scales_about_origin": "Co giãn quanh gốc phác thảo",
|
||||
"ui.first_dimension_scales_about_origin_tip": "Bật: bản vẽ luôn phóng to hoặc thu nhỏ quanh gốc phác thảo, nên hình vẽ cách xa gốc sẽ di chuyển. Tắt: bản vẽ không gắn với gốc sẽ co giãn quanh tâm của chính nó và giữ nguyên vị trí."
|
||||
},
|
||||
"zh": {
|
||||
"ui.first_dimension_scales_about_origin": "以草图原点为中心缩放",
|
||||
"ui.first_dimension_scales_about_origin_tip": "开启:图形总是以草图原点为中心放大或缩小,因此远离原点绘制的形状会移动。关闭:未与原点关联的图形以其自身中心缩放,并保持在绘制的位置。"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,206 @@
|
||||
{
|
||||
"en": {
|
||||
"cmd.frame_end_cap": "End Cap",
|
||||
"error.end_cap_faces": "Pick at least one open end face of a frame member",
|
||||
"error.end_cap_unresolved": "End {ends} of this cap is no longer on the model. Pick the end faces again",
|
||||
"help.frame.end_cap": "Closes the open ends of frame members with plates shaped like the profile's outline. Use it to seal tubes, angles and beams, on top of the end or set into it.",
|
||||
"ui.end_cap.chamfer": "Corner Chamfer",
|
||||
"ui.end_cap.direction": "Direction",
|
||||
"ui.end_cap.faces": "End Faces",
|
||||
"ui.end_cap.inset": "Inset",
|
||||
"ui.end_cap.inset_kind": "Inset By",
|
||||
"ui.end_cap.inset_ratio": "Inset Ratio",
|
||||
"ui.end_cap.inward": "Inward",
|
||||
"ui.end_cap.length": "Length",
|
||||
"ui.end_cap.outward": "Outward",
|
||||
"ui.end_cap.ratio": "Ratio of thickness",
|
||||
"ui.end_cap_title": "END CAP"
|
||||
},
|
||||
"ar": {
|
||||
"cmd.frame_end_cap": "غطاء طرفي",
|
||||
"error.end_cap_faces": "اختر وجهًا طرفيًا مفتوحًا واحدًا على الأقل لعضو إطار",
|
||||
"error.end_cap_unresolved": "الطرف {ends} لهذا الغطاء لم يعد موجودًا في النموذج. اختر الأوجه الطرفية مرة أخرى",
|
||||
"help.frame.end_cap": "يغلق الأطراف المفتوحة لأعضاء الإطار بألواح على شكل محيط المقطع. استخدمه لسد الأنابيب والزوايا والعوارض، فوق الطرف أو مغروسًا فيه.",
|
||||
"ui.end_cap.chamfer": "شطف الزوايا",
|
||||
"ui.end_cap.direction": "الاتجاه",
|
||||
"ui.end_cap.faces": "الوجوه الطرفية",
|
||||
"ui.end_cap.inset": "الإزاحة للداخل",
|
||||
"ui.end_cap.inset_kind": "الإزاحة حسب",
|
||||
"ui.end_cap.inset_ratio": "نسبة الإزاحة",
|
||||
"ui.end_cap.inward": "للداخل",
|
||||
"ui.end_cap.length": "الطول",
|
||||
"ui.end_cap.outward": "للخارج",
|
||||
"ui.end_cap.ratio": "نسبة من السماكة",
|
||||
"ui.end_cap_title": "غطاء طرفي"
|
||||
},
|
||||
"de": {
|
||||
"cmd.frame_end_cap": "Endkappe",
|
||||
"error.end_cap_faces": "Mindestens eine offene Stirnfläche eines Rahmenelements auswählen",
|
||||
"error.end_cap_unresolved": "Ende {ends} dieser Abdeckung ist nicht mehr im Modell. Stirnflächen erneut auswählen",
|
||||
"help.frame.end_cap": "Schließt offene Enden von Rahmenelementen mit Platten in der Form des Profilumrisses. Damit verschließen Sie Rohre, Winkel und Träger, auf dem Ende oder darin eingelassen.",
|
||||
"ui.end_cap.chamfer": "Eckfase",
|
||||
"ui.end_cap.direction": "Richtung",
|
||||
"ui.end_cap.faces": "Stirnflächen",
|
||||
"ui.end_cap.inset": "Einzug",
|
||||
"ui.end_cap.inset_kind": "Einzug als",
|
||||
"ui.end_cap.inset_ratio": "Einzugsverhältnis",
|
||||
"ui.end_cap.inward": "Nach innen",
|
||||
"ui.end_cap.length": "Länge",
|
||||
"ui.end_cap.outward": "Nach außen",
|
||||
"ui.end_cap.ratio": "Anteil der Dicke",
|
||||
"ui.end_cap_title": "ENDKAPPE"
|
||||
},
|
||||
"es": {
|
||||
"cmd.frame_end_cap": "Tapa de extremo",
|
||||
"error.end_cap_faces": "Selecciona al menos una cara de extremo abierta de un miembro",
|
||||
"error.end_cap_unresolved": "El extremo {ends} de esta tapa ya no está en el modelo. Vuelve a seleccionar las caras de extremo",
|
||||
"help.frame.end_cap": "Cierra los extremos abiertos de los miembros de una estructura con placas con la forma del contorno del perfil. Úsalo para tapar tubos, angulares y vigas, sobre el extremo o embutidas en él.",
|
||||
"ui.end_cap.chamfer": "Chaflán de esquina",
|
||||
"ui.end_cap.direction": "Dirección",
|
||||
"ui.end_cap.faces": "Caras de extremo",
|
||||
"ui.end_cap.inset": "Retranqueo",
|
||||
"ui.end_cap.inset_kind": "Retranqueo por",
|
||||
"ui.end_cap.inset_ratio": "Proporción de retranqueo",
|
||||
"ui.end_cap.inward": "Hacia dentro",
|
||||
"ui.end_cap.length": "Longitud",
|
||||
"ui.end_cap.outward": "Hacia fuera",
|
||||
"ui.end_cap.ratio": "Proporción del espesor",
|
||||
"ui.end_cap_title": "TAPA DE EXTREMO"
|
||||
},
|
||||
"fr": {
|
||||
"cmd.frame_end_cap": "Bouchon d'extrémité",
|
||||
"error.end_cap_faces": "Sélectionnez au moins une face d'extrémité ouverte d'un élément de structure",
|
||||
"error.end_cap_unresolved": "L'extrémité {ends} de ce bouchon n'est plus sur le modèle. Sélectionnez à nouveau les faces d'extrémité",
|
||||
"help.frame.end_cap": "Ferme les extrémités ouvertes des éléments de structure avec des plaques à la forme du contour du profil. Utilisez-le pour boucher tubes, cornières et poutres, sur l'extrémité ou encastrées.",
|
||||
"ui.end_cap.chamfer": "Chanfrein d'angle",
|
||||
"ui.end_cap.direction": "Direction",
|
||||
"ui.end_cap.faces": "Faces d'extrémité",
|
||||
"ui.end_cap.inset": "Retrait",
|
||||
"ui.end_cap.inset_kind": "Retrait en",
|
||||
"ui.end_cap.inset_ratio": "Rapport de retrait",
|
||||
"ui.end_cap.inward": "Vers l'intérieur",
|
||||
"ui.end_cap.length": "Longueur",
|
||||
"ui.end_cap.outward": "Vers l'extérieur",
|
||||
"ui.end_cap.ratio": "Rapport de l'épaisseur",
|
||||
"ui.end_cap_title": "BOUCHON D'EXTRÉMITÉ"
|
||||
},
|
||||
"he": {
|
||||
"cmd.frame_end_cap": "מכסה קצה",
|
||||
"error.end_cap_faces": "בחר לפחות פאת קצה פתוחה אחת של איבר מסגרת",
|
||||
"error.end_cap_unresolved": "קצה {ends} של מכסה זה כבר אינו במודל. בחר שוב את פאות הקצה",
|
||||
"help.frame.end_cap": "סוגר קצוות פתוחים של איברי מסגרת בלוחות בצורת קו המתאר של הפרופיל. השתמש בו כדי לאטום צינורות, זוויתנים וקורות, מעל הקצה או שקוע בו.",
|
||||
"ui.end_cap.chamfer": "שיפוע פינות",
|
||||
"ui.end_cap.direction": "כיוון",
|
||||
"ui.end_cap.faces": "פאות קצה",
|
||||
"ui.end_cap.inset": "היסט פנימה",
|
||||
"ui.end_cap.inset_kind": "היסט לפי",
|
||||
"ui.end_cap.inset_ratio": "יחס היסט",
|
||||
"ui.end_cap.inward": "פנימה",
|
||||
"ui.end_cap.length": "אורך",
|
||||
"ui.end_cap.outward": "החוצה",
|
||||
"ui.end_cap.ratio": "יחס מהעובי",
|
||||
"ui.end_cap_title": "מכסה קצה"
|
||||
},
|
||||
"it": {
|
||||
"cmd.frame_end_cap": "Tappo di estremità",
|
||||
"error.end_cap_faces": "Seleziona almeno una faccia di estremità aperta di un elemento",
|
||||
"error.end_cap_unresolved": "L'estremità {ends} di questa chiusura non è più nel modello. Seleziona di nuovo le facce di estremità",
|
||||
"help.frame.end_cap": "Chiude le estremità aperte degli elementi con piastre sagomate sul contorno del profilo. Usalo per chiudere tubi, angolari e travi, sopra l'estremità o incassate.",
|
||||
"ui.end_cap.chamfer": "Smusso degli angoli",
|
||||
"ui.end_cap.direction": "Direzione",
|
||||
"ui.end_cap.faces": "Facce di estremità",
|
||||
"ui.end_cap.inset": "Rientro",
|
||||
"ui.end_cap.inset_kind": "Rientro come",
|
||||
"ui.end_cap.inset_ratio": "Rapporto di rientro",
|
||||
"ui.end_cap.inward": "Verso l'interno",
|
||||
"ui.end_cap.length": "Lunghezza",
|
||||
"ui.end_cap.outward": "Verso l'esterno",
|
||||
"ui.end_cap.ratio": "Rapporto dello spessore",
|
||||
"ui.end_cap_title": "TAPPO DI ESTREMITÀ"
|
||||
},
|
||||
"ja": {
|
||||
"cmd.frame_end_cap": "エンドキャップ",
|
||||
"error.end_cap_faces": "フレーム部材の開いた端面を1つ以上選択してください",
|
||||
"error.end_cap_unresolved": "このエンドキャップの端 {ends} はモデル上にありません。端面を選択し直してください",
|
||||
"help.frame.end_cap": "フレーム部材の開いた端を、プロファイルの外形に沿ったプレートで閉じます。パイプ、アングル、梁の端をふさぐときに、端の上に載せるか端に埋め込んで使います。",
|
||||
"ui.end_cap.chamfer": "角の面取り",
|
||||
"ui.end_cap.direction": "方向",
|
||||
"ui.end_cap.faces": "端面",
|
||||
"ui.end_cap.inset": "内側オフセット",
|
||||
"ui.end_cap.inset_kind": "オフセットの指定",
|
||||
"ui.end_cap.inset_ratio": "オフセット比",
|
||||
"ui.end_cap.inward": "内向き",
|
||||
"ui.end_cap.length": "長さ",
|
||||
"ui.end_cap.outward": "外向き",
|
||||
"ui.end_cap.ratio": "厚さに対する比",
|
||||
"ui.end_cap_title": "エンドキャップ"
|
||||
},
|
||||
"pt-BR": {
|
||||
"cmd.frame_end_cap": "Tampa de extremidade",
|
||||
"error.end_cap_faces": "Selecione pelo menos uma face de extremidade aberta de um membro",
|
||||
"error.end_cap_unresolved": "A extremidade {ends} desta tampa não está mais no modelo. Selecione as faces de extremidade novamente",
|
||||
"help.frame.end_cap": "Fecha as extremidades abertas dos membros com placas no formato do contorno do perfil. Use para tampar tubos, cantoneiras e vigas, sobre a extremidade ou embutidas nela.",
|
||||
"ui.end_cap.chamfer": "Chanfro dos cantos",
|
||||
"ui.end_cap.direction": "Direção",
|
||||
"ui.end_cap.faces": "Faces de extremidade",
|
||||
"ui.end_cap.inset": "Recuo",
|
||||
"ui.end_cap.inset_kind": "Recuo por",
|
||||
"ui.end_cap.inset_ratio": "Proporção de recuo",
|
||||
"ui.end_cap.inward": "Para dentro",
|
||||
"ui.end_cap.length": "Comprimento",
|
||||
"ui.end_cap.outward": "Para fora",
|
||||
"ui.end_cap.ratio": "Proporção da espessura",
|
||||
"ui.end_cap_title": "TAMPA DE EXTREMIDADE"
|
||||
},
|
||||
"vi": {
|
||||
"cmd.frame_end_cap": "Nắp đầu",
|
||||
"error.end_cap_faces": "Chọn ít nhất một mặt đầu hở của một thanh khung",
|
||||
"error.end_cap_unresolved": "Đầu {ends} của nắp này không còn trên mô hình. Hãy chọn lại các mặt đầu",
|
||||
"help.frame.end_cap": "Đóng các đầu hở của thanh khung bằng tấm có hình đường bao của tiết diện. Dùng để bịt ống, thép góc và dầm, đặt lên đầu hoặc lắp chìm vào đầu.",
|
||||
"ui.end_cap.chamfer": "Vát góc",
|
||||
"ui.end_cap.direction": "Hướng",
|
||||
"ui.end_cap.faces": "Mặt đầu",
|
||||
"ui.end_cap.inset": "Thụt vào",
|
||||
"ui.end_cap.inset_kind": "Thụt vào theo",
|
||||
"ui.end_cap.inset_ratio": "Tỉ lệ thụt vào",
|
||||
"ui.end_cap.inward": "Vào trong",
|
||||
"ui.end_cap.length": "Chiều dài",
|
||||
"ui.end_cap.outward": "Ra ngoài",
|
||||
"ui.end_cap.ratio": "Tỉ lệ theo độ dày",
|
||||
"ui.end_cap_title": "NẮP ĐẦU"
|
||||
},
|
||||
"zh": {
|
||||
"cmd.frame_end_cap": "端盖",
|
||||
"error.end_cap_faces": "请至少选择一个框架构件的开放端面",
|
||||
"error.end_cap_unresolved": "此端盖的端 {ends} 已不在模型上。请重新选择端面",
|
||||
"help.frame.end_cap": "用符合型材外形的板封闭框架构件的开放端。用于封住管材、角钢和梁的端部,可盖在端面上或嵌入端部。",
|
||||
"ui.end_cap.chamfer": "角部倒角",
|
||||
"ui.end_cap.direction": "方向",
|
||||
"ui.end_cap.faces": "端面",
|
||||
"ui.end_cap.inset": "内缩",
|
||||
"ui.end_cap.inset_kind": "内缩方式",
|
||||
"ui.end_cap.inset_ratio": "内缩比例",
|
||||
"ui.end_cap.inward": "向内",
|
||||
"ui.end_cap.length": "长度",
|
||||
"ui.end_cap.outward": "向外",
|
||||
"ui.end_cap.ratio": "厚度比例",
|
||||
"ui.end_cap_title": "端盖"
|
||||
},
|
||||
"zh-TW": {
|
||||
"cmd.frame_end_cap": "端蓋",
|
||||
"error.end_cap_faces": "請至少選取一個框架構件的開放端面",
|
||||
"error.end_cap_unresolved": "此端蓋的端 {ends} 已不在模型上。請重新選取端面",
|
||||
"help.frame.end_cap": "以符合型材外形的板封閉框架構件的開放端。用於封住管材、角鋼與樑的端部,可蓋在端面上或嵌入端部。",
|
||||
"ui.end_cap.chamfer": "角落倒角",
|
||||
"ui.end_cap.direction": "方向",
|
||||
"ui.end_cap.faces": "端面",
|
||||
"ui.end_cap.inset": "內縮",
|
||||
"ui.end_cap.inset_kind": "內縮方式",
|
||||
"ui.end_cap.inset_ratio": "內縮比例",
|
||||
"ui.end_cap.inward": "向內",
|
||||
"ui.end_cap.length": "長度",
|
||||
"ui.end_cap.outward": "向外",
|
||||
"ui.end_cap.ratio": "厚度比例",
|
||||
"ui.end_cap_title": "端蓋"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
{
|
||||
"en": {
|
||||
"prefs.graphics_api": "Graphics API",
|
||||
"prefs.graphics_api_auto": "Automatic",
|
||||
"prefs.graphics_api_help": "Choose the graphics API used to open SolidCraft. If the next start cannot open the window, the previous choice is restored.",
|
||||
"prefs.graphics_api_override": "A launch override is controlling the graphics API. The saved choice will apply when SolidCraft is opened normally.",
|
||||
"prefs.graphics_api_restart_note": "Applies after a restart. Unsaved designs are handled before closing.",
|
||||
"prefs.graphics_api_restart_unavailable": "Restart SolidCraft to apply the saved graphics API.",
|
||||
"prefs.graphics_api_running": "Current: {current}. Selected for next start: {selected}.",
|
||||
"prefs.graphics_api_save_failed": "The graphics API choice could not be saved: {error}",
|
||||
"prefs.graphics_api_start_failed": "The selected graphics API could not be prepared: {error}",
|
||||
"prefs.graphics_api_start_reverted": "The previous start with {requested} did not open the window. SolidCraft restored {previous}.",
|
||||
"prefs.graphics_api_unavailable": "Graphics API selection is available in the desktop app.",
|
||||
"render.graphics_api_restart_vulkan": "Restart with Vulkan",
|
||||
"render.graphics_api_restart_warning": "Changing graphics API restarts SolidCraft and asks you to save unsaved designs. If the new API cannot open the window, the previous choice is restored on the next start.",
|
||||
"render.graphics_api_settings": "Graphics settings",
|
||||
"render.graphics_api_vulkan_required": "GPU path tracing needs Vulkan in this session. Restart with Vulkan, or keep using a CPU image method."
|
||||
},
|
||||
"ar": {
|
||||
"prefs.graphics_api": "واجهة برمجة تطبيقات الرسوميات",
|
||||
"prefs.graphics_api_auto": "تلقائي",
|
||||
"prefs.graphics_api_help": "اختر واجهة الرسوميات المستخدمة لفتح SolidCraft. إذا تعذّر فتح النافذة عند التشغيل التالي، فستُستعاد السابقة.",
|
||||
"prefs.graphics_api_override": "يتحكم إعداد عند التشغيل في واجهة الرسوميات. سيُطبّق الاختيار المحفوظ عند فتح SolidCraft بالطريقة العادية.",
|
||||
"prefs.graphics_api_restart_note": "يُطبّق بعد إعادة التشغيل. تُعالَج التصميمات غير المحفوظة قبل الإغلاق.",
|
||||
"prefs.graphics_api_restart_unavailable": "أعد تشغيل SolidCraft لتطبيق واجهة الرسوميات المحفوظة.",
|
||||
"prefs.graphics_api_running": "الحالية: {current}. المختارة للتشغيل التالي: {selected}.",
|
||||
"prefs.graphics_api_save_failed": "تعذّر حفظ اختيار واجهة الرسوميات: {error}",
|
||||
"prefs.graphics_api_start_failed": "تعذّر تجهيز واجهة الرسوميات المختارة: {error}",
|
||||
"prefs.graphics_api_start_reverted": "لم يفتح التشغيل السابق باستخدام {requested} النافذة. استعاد SolidCraft الاختيار {previous}.",
|
||||
"prefs.graphics_api_unavailable": "اختيار واجهة الرسوميات متاح في تطبيق سطح المكتب.",
|
||||
"render.graphics_api_restart_vulkan": "إعادة التشغيل باستخدام Vulkan",
|
||||
"render.graphics_api_restart_warning": "يؤدي تغيير واجهة الرسوميات إلى إعادة تشغيل SolidCraft ويطلب منك حفظ التصميمات غير المحفوظة. إذا تعذّر فتح النافذة بالواجهة الجديدة، فسيُستعاد الاختيار السابق عند التشغيل التالي.",
|
||||
"render.graphics_api_settings": "إعدادات الرسوميات",
|
||||
"render.graphics_api_vulkan_required": "يتطلب تتبّع المسارات بمعالج الرسوميات Vulkan في هذه الجلسة. أعد التشغيل باستخدام Vulkan، أو واصل استخدام طريقة صور بمعالج CPU."
|
||||
},
|
||||
"he": {
|
||||
"prefs.graphics_api": "ממשק גרפי",
|
||||
"prefs.graphics_api_auto": "אוטומטי",
|
||||
"prefs.graphics_api_help": "בחרו את הממשק הגרפי המשמש לפתיחת SolidCraft. אם ההפעלה הבאה לא תצליח לפתוח את החלון, הבחירה הקודמת תשוחזר.",
|
||||
"prefs.graphics_api_override": "הגדרת הפעלה עוקפת קובעת את הממשק הגרפי. הבחירה השמורה תחול כאשר SolidCraft ייפתח כרגיל.",
|
||||
"prefs.graphics_api_restart_note": "חל לאחר הפעלה מחדש. עיצובים שלא נשמרו יטופלו לפני הסגירה.",
|
||||
"prefs.graphics_api_restart_unavailable": "הפעילו מחדש את SolidCraft כדי להחיל את הממשק הגרפי השמור.",
|
||||
"prefs.graphics_api_running": "נוכחי: {current}. נבחר להפעלה הבאה: {selected}.",
|
||||
"prefs.graphics_api_save_failed": "לא ניתן לשמור את בחירת הממשק הגרפי: {error}",
|
||||
"prefs.graphics_api_start_failed": "לא ניתן להכין את הממשק הגרפי שנבחר: {error}",
|
||||
"prefs.graphics_api_start_reverted": "ההפעלה הקודמת עם {requested} לא פתחה את החלון. SolidCraft שחזר את {previous}.",
|
||||
"prefs.graphics_api_unavailable": "בחירת ממשק גרפי זמינה ביישום שולחן העבודה.",
|
||||
"render.graphics_api_restart_vulkan": "הפעלה מחדש עם Vulkan",
|
||||
"render.graphics_api_restart_warning": "שינוי הממשק הגרפי מפעיל מחדש את SolidCraft ומבקש לשמור עיצובים שלא נשמרו. אם הממשק החדש לא יצליח לפתוח את החלון, הבחירה הקודמת תשוחזר בהפעלה הבאה.",
|
||||
"render.graphics_api_settings": "הגדרות גרפיקה",
|
||||
"render.graphics_api_vulkan_required": "מעקב נתיבים ב־GPU דורש Vulkan בהפעלה זו. הפעילו מחדש עם Vulkan, או המשיכו להשתמש בשיטת תמונה ב־CPU."
|
||||
},
|
||||
"ja": {
|
||||
"prefs.graphics_api": "グラフィックスAPI",
|
||||
"prefs.graphics_api_auto": "自動",
|
||||
"prefs.graphics_api_help": "SolidCraftの起動に使用するグラフィックスAPIを選択します。次回起動時にウィンドウを開けなかった場合は、以前の選択に戻ります。",
|
||||
"prefs.graphics_api_override": "起動時の上書き設定がグラフィックスAPIを指定しています。SolidCraftを通常どおり開くと、保存した選択が適用されます。",
|
||||
"prefs.graphics_api_restart_note": "再起動後に適用されます。閉じる前に未保存のデザインを確認します。",
|
||||
"prefs.graphics_api_restart_unavailable": "保存したグラフィックスAPIを適用するには、SolidCraftを再起動してください。",
|
||||
"prefs.graphics_api_running": "現在: {current}。次回起動時の選択: {selected}。",
|
||||
"prefs.graphics_api_save_failed": "グラフィックスAPIの選択を保存できませんでした: {error}",
|
||||
"prefs.graphics_api_start_failed": "選択したグラフィックスAPIを準備できませんでした: {error}",
|
||||
"prefs.graphics_api_start_reverted": "前回は{requested}でウィンドウを開けませんでした。SolidCraftは{previous}に戻しました。",
|
||||
"prefs.graphics_api_unavailable": "グラフィックスAPIの選択はデスクトップアプリで利用できます。",
|
||||
"render.graphics_api_restart_vulkan": "Vulkanで再起動",
|
||||
"render.graphics_api_restart_warning": "グラフィックスAPIを変更するとSolidCraftが再起動し、未保存のデザインの保存を確認します。新しいAPIでウィンドウを開けない場合は、次回起動時に以前の選択に戻ります。",
|
||||
"render.graphics_api_settings": "グラフィックス設定",
|
||||
"render.graphics_api_vulkan_required": "このセッションでGPUパストレーシングを使用するにはVulkanが必要です。Vulkanで再起動するか、CPUの画像方式を引き続き使用してください。"
|
||||
},
|
||||
"vi": {
|
||||
"prefs.graphics_api": "API đồ họa",
|
||||
"prefs.graphics_api_auto": "Tự động",
|
||||
"prefs.graphics_api_help": "Chọn API đồ họa dùng để mở SolidCraft. Nếu lần khởi động tiếp theo không mở được cửa sổ, lựa chọn trước sẽ được khôi phục.",
|
||||
"prefs.graphics_api_override": "Một thiết lập ghi đè khi khởi chạy đang điều khiển API đồ họa. Lựa chọn đã lưu sẽ áp dụng khi mở SolidCraft bình thường.",
|
||||
"prefs.graphics_api_restart_note": "Áp dụng sau khi khởi động lại. Các thiết kế chưa lưu được xử lý trước khi đóng.",
|
||||
"prefs.graphics_api_restart_unavailable": "Khởi động lại SolidCraft để áp dụng API đồ họa đã lưu.",
|
||||
"prefs.graphics_api_running": "Hiện tại: {current}. Đã chọn cho lần khởi động tiếp theo: {selected}.",
|
||||
"prefs.graphics_api_save_failed": "Không thể lưu lựa chọn API đồ họa: {error}",
|
||||
"prefs.graphics_api_start_failed": "Không thể chuẩn bị API đồ họa đã chọn: {error}",
|
||||
"prefs.graphics_api_start_reverted": "Lần khởi động trước với {requested} không mở được cửa sổ. SolidCraft đã khôi phục {previous}.",
|
||||
"prefs.graphics_api_unavailable": "Có thể chọn API đồ họa trong ứng dụng máy tính.",
|
||||
"render.graphics_api_restart_vulkan": "Khởi động lại với Vulkan",
|
||||
"render.graphics_api_restart_warning": "Đổi API đồ họa sẽ khởi động lại SolidCraft và yêu cầu lưu các thiết kế chưa lưu. Nếu API mới không mở được cửa sổ, lựa chọn trước sẽ được khôi phục ở lần khởi động tiếp theo.",
|
||||
"render.graphics_api_settings": "Cài đặt đồ họa",
|
||||
"render.graphics_api_vulkan_required": "Truy vết đường đi bằng GPU cần Vulkan trong phiên này. Khởi động lại với Vulkan hoặc tiếp tục dùng phương pháp tạo ảnh bằng CPU."
|
||||
},
|
||||
"zh": {
|
||||
"prefs.graphics_api": "图形 API",
|
||||
"prefs.graphics_api_auto": "自动",
|
||||
"prefs.graphics_api_help": "选择用于启动 SolidCraft 的图形 API。如果下次启动无法打开窗口,将恢复之前的选择。",
|
||||
"prefs.graphics_api_override": "启动覆盖设置正在控制图形 API。正常打开 SolidCraft 时将应用已保存的选择。",
|
||||
"prefs.graphics_api_restart_note": "重启后生效。关闭前会处理未保存的设计。",
|
||||
"prefs.graphics_api_restart_unavailable": "重启 SolidCraft 以应用已保存的图形 API。",
|
||||
"prefs.graphics_api_running": "当前:{current}。下次启动的选择:{selected}。",
|
||||
"prefs.graphics_api_save_failed": "无法保存图形 API 选择:{error}",
|
||||
"prefs.graphics_api_start_failed": "无法准备所选图形 API:{error}",
|
||||
"prefs.graphics_api_start_reverted": "上次使用 {requested} 启动时未能打开窗口。SolidCraft 已恢复为 {previous}。",
|
||||
"prefs.graphics_api_unavailable": "图形 API 选择功能可在桌面应用中使用。",
|
||||
"render.graphics_api_restart_vulkan": "使用 Vulkan 重启",
|
||||
"render.graphics_api_restart_warning": "更改图形 API 将重启 SolidCraft,并提示保存未保存的设计。如果新 API 无法打开窗口,下次启动时将恢复之前的选择。",
|
||||
"render.graphics_api_settings": "图形设置",
|
||||
"render.graphics_api_vulkan_required": "本次会话的 GPU 路径追踪需要 Vulkan。请使用 Vulkan 重启,或继续使用 CPU 图像方式。"
|
||||
},
|
||||
"de": {
|
||||
"prefs.graphics_api": "Grafik-API",
|
||||
"prefs.graphics_api_auto": "Automatisch",
|
||||
"prefs.graphics_api_help": "Wählen Sie die Grafik-API zum Starten von SolidCraft. Wenn sich beim nächsten Start kein Fenster öffnen lässt, wird die vorherige Auswahl wiederhergestellt.",
|
||||
"prefs.graphics_api_override": "Eine Startvorgabe bestimmt die Grafik-API. Die gespeicherte Auswahl gilt, wenn SolidCraft normal geöffnet wird.",
|
||||
"prefs.graphics_api_restart_note": "Gilt nach einem Neustart. Ungespeicherte Entwürfe werden vor dem Schließen berücksichtigt.",
|
||||
"prefs.graphics_api_restart_unavailable": "Starten Sie SolidCraft neu, um die gespeicherte Grafik-API anzuwenden.",
|
||||
"prefs.graphics_api_running": "Aktuell: {current}. Für den nächsten Start ausgewählt: {selected}.",
|
||||
"prefs.graphics_api_save_failed": "Die Auswahl der Grafik-API konnte nicht gespeichert werden: {error}",
|
||||
"prefs.graphics_api_start_failed": "Die ausgewählte Grafik-API konnte nicht vorbereitet werden: {error}",
|
||||
"prefs.graphics_api_start_reverted": "Der vorherige Start mit {requested} konnte kein Fenster öffnen. SolidCraft hat {previous} wiederhergestellt.",
|
||||
"prefs.graphics_api_unavailable": "Die Grafik-API kann in der Desktop-App ausgewählt werden.",
|
||||
"render.graphics_api_restart_vulkan": "Mit Vulkan neu starten",
|
||||
"render.graphics_api_restart_warning": "Ein Wechsel der Grafik-API startet SolidCraft neu und fragt nach dem Speichern ungespeicherter Entwürfe. Wenn die neue API kein Fenster öffnen kann, wird beim nächsten Start die vorherige Auswahl wiederhergestellt.",
|
||||
"render.graphics_api_settings": "Grafikeinstellungen",
|
||||
"render.graphics_api_vulkan_required": "GPU-Pathtracing benötigt Vulkan in dieser Sitzung. Starten Sie mit Vulkan neu oder verwenden Sie weiterhin ein CPU-Bildverfahren."
|
||||
},
|
||||
"ko": {
|
||||
"prefs.graphics_api": "그래픽 API",
|
||||
"prefs.graphics_api_auto": "자동",
|
||||
"prefs.graphics_api_help": "SolidCraft를 시작할 그래픽 API를 선택합니다. 다음 시작에서 창을 열지 못하면 이전 선택으로 복원됩니다.",
|
||||
"prefs.graphics_api_override": "시작 시 재정의 설정이 그래픽 API를 제어하고 있습니다. SolidCraft를 일반적인 방법으로 열면 저장된 선택이 적용됩니다.",
|
||||
"prefs.graphics_api_restart_note": "다시 시작한 후 적용됩니다. 닫기 전에 저장하지 않은 설계를 처리합니다.",
|
||||
"prefs.graphics_api_restart_unavailable": "저장된 그래픽 API를 적용하려면 SolidCraft를 다시 시작하세요.",
|
||||
"prefs.graphics_api_running": "현재: {current}. 다음 시작 시 선택: {selected}.",
|
||||
"prefs.graphics_api_save_failed": "그래픽 API 선택을 저장할 수 없습니다: {error}",
|
||||
"prefs.graphics_api_start_failed": "선택한 그래픽 API를 준비할 수 없습니다: {error}",
|
||||
"prefs.graphics_api_start_reverted": "{requested}을(를) 사용한 이전 시작에서 창을 열지 못했습니다. SolidCraft가 {previous}(으)로 복원했습니다.",
|
||||
"prefs.graphics_api_unavailable": "그래픽 API는 데스크톱 앱에서 선택할 수 있습니다.",
|
||||
"render.graphics_api_restart_vulkan": "Vulkan으로 다시 시작",
|
||||
"render.graphics_api_restart_warning": "그래픽 API를 변경하면 SolidCraft가 다시 시작되고 저장하지 않은 설계를 저장할지 묻습니다. 새 API로 창을 열지 못하면 다음 시작에서 이전 선택으로 복원됩니다.",
|
||||
"render.graphics_api_settings": "그래픽 설정",
|
||||
"render.graphics_api_vulkan_required": "이 세션의 GPU 경로 추적에는 Vulkan이 필요합니다. Vulkan으로 다시 시작하거나 CPU 이미지 방식을 계속 사용하세요."
|
||||
},
|
||||
"es": {
|
||||
"prefs.graphics_api": "API gráfica",
|
||||
"prefs.graphics_api_auto": "Automático",
|
||||
"prefs.graphics_api_help": "Elige la API gráfica usada para abrir SolidCraft. Si el próximo inicio no puede abrir la ventana, se restaurará la selección anterior.",
|
||||
"prefs.graphics_api_override": "Una configuración de arranque está imponiendo la API gráfica. La selección guardada se aplicará al abrir SolidCraft de forma normal.",
|
||||
"prefs.graphics_api_restart_note": "Se aplica después de reiniciar. Antes de cerrar se revisan los diseños sin guardar.",
|
||||
"prefs.graphics_api_restart_unavailable": "Reinicia SolidCraft para aplicar la API gráfica guardada.",
|
||||
"prefs.graphics_api_running": "Actual: {current}. Seleccionada para el próximo inicio: {selected}.",
|
||||
"prefs.graphics_api_save_failed": "No se pudo guardar la selección de API gráfica: {error}",
|
||||
"prefs.graphics_api_start_failed": "No se pudo preparar la API gráfica seleccionada: {error}",
|
||||
"prefs.graphics_api_start_reverted": "El inicio anterior con {requested} no abrió la ventana. SolidCraft ha restaurado {previous}.",
|
||||
"prefs.graphics_api_unavailable": "La selección de API gráfica está disponible en la aplicación de escritorio.",
|
||||
"render.graphics_api_restart_vulkan": "Reiniciar con Vulkan",
|
||||
"render.graphics_api_restart_warning": "Cambiar la API gráfica reinicia SolidCraft y te pide guardar los diseños sin guardar. Si la nueva API no puede abrir la ventana, se restaurará la selección anterior en el próximo inicio.",
|
||||
"render.graphics_api_settings": "Ajustes gráficos",
|
||||
"render.graphics_api_vulkan_required": "El trazado de trayectorias por GPU necesita Vulkan en esta sesión. Reinicia con Vulkan o sigue usando un método de imagen por CPU."
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"en": {
|
||||
"dialog.hole_held_off_its_line": "The reference edge holds this hole on a line that leaves the face before the picked point. Pick where the line crosses the face, or take the edge out to move the hole freely."
|
||||
},
|
||||
"ar": {
|
||||
"dialog.hole_held_off_its_line": "الحافة المرجعية تُبقي هذا الثقب على خط يغادر الوجه قبل النقطة المختارة. اختر حيث يعبر الخط الوجه، أو أزل الحافة لتحريك الثقب بحرية."
|
||||
},
|
||||
"he": {
|
||||
"dialog.hole_held_off_its_line": "קצה הייחוס מחזיק את החור על קו שיוצא מהפאה לפני הנקודה שנבחרה. יש לבחור במקום שבו הקו עובר על הפאה, או להסיר את הקצה כדי להזיז את החור בחופשיות."
|
||||
},
|
||||
"ja": {
|
||||
"dialog.hole_held_off_its_line": "参照エッジがこの穴を直線上に固定していますが、その直線は選択した点より手前で面の外に出ます。直線が面の上を通る位置を選択するか、エッジを外すと穴を自由に移動できます。"
|
||||
},
|
||||
"vi": {
|
||||
"dialog.hole_held_off_its_line": "Cạnh tham chiếu giữ lỗ này trên một đường thẳng ra khỏi mặt trước điểm đã chọn. Hãy chọn chỗ đường thẳng đi qua mặt, hoặc bỏ cạnh để di chuyển lỗ tự do."
|
||||
},
|
||||
"zh": {
|
||||
"dialog.hole_held_off_its_line": "参考边将此孔固定在一条直线上,该直线在所选点之前就离开了该面。请在直线经过该面的位置选取,或移除该边以自由移动孔。"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"en": {
|
||||
"nav.maya_horizontal_zoom.help": "Alt+right drag: right zooms in, left zooms out. Turn off to restore vertical drag zoom.",
|
||||
"nav.maya_horizontal_zoom.label": "Maya: horizontal drag zoom"
|
||||
},
|
||||
"ar": {
|
||||
"nav.maya_horizontal_zoom.help": "اسحب مع Alt وزر الفأرة الأيمن: إلى اليمين للتكبير وإلى اليسار للتصغير. عطّل هذا الخيار لاستعادة التكبير بالسحب العمودي.",
|
||||
"nav.maya_horizontal_zoom.label": "Maya: التكبير بالسحب الأفقي"
|
||||
},
|
||||
"he": {
|
||||
"nav.maya_horizontal_zoom.help": "Alt וגרירה עם לחצן העכבר הימני: ימינה לקירוב, שמאלה להרחקה. כבו כדי לחזור לזום בגרירה אנכית.",
|
||||
"nav.maya_horizontal_zoom.label": "Maya: זום בגרירה אופקית"
|
||||
},
|
||||
"ja": {
|
||||
"nav.maya_horizontal_zoom.help": "Alt+右ドラッグで右に動かすと拡大、左に動かすと縮小します。オフにすると従来の垂直ドラッグに戻ります。",
|
||||
"nav.maya_horizontal_zoom.label": "Maya: 水平方向のドラッグでズーム"
|
||||
},
|
||||
"vi": {
|
||||
"nav.maya_horizontal_zoom.help": "Alt+kéo chuột phải: kéo sang phải để phóng to, sang trái để thu nhỏ. Tắt để khôi phục thu phóng bằng cách kéo dọc.",
|
||||
"nav.maya_horizontal_zoom.label": "Maya: thu phóng bằng cách kéo ngang"
|
||||
},
|
||||
"zh": {
|
||||
"nav.maya_horizontal_zoom.help": "Alt+右键拖动:向右放大,向左缩小。关闭此选项可恢复垂直拖动缩放。",
|
||||
"nav.maya_horizontal_zoom.label": "Maya:水平拖动缩放"
|
||||
},
|
||||
"de": {
|
||||
"nav.maya_horizontal_zoom.help": "Alt+Rechtsziehen: nach rechts vergrößern, nach links verkleinern. Ausschalten, um wieder vertikal zu zoomen.",
|
||||
"nav.maya_horizontal_zoom.label": "Maya: horizontal ziehen zum Zoomen"
|
||||
},
|
||||
"ko": {
|
||||
"nav.maya_horizontal_zoom.help": "Alt+오른쪽 버튼 드래그: 오른쪽으로 움직이면 확대하고 왼쪽으로 움직이면 축소합니다. 끄면 세로 드래그 확대/축소로 돌아갑니다.",
|
||||
"nav.maya_horizontal_zoom.label": "Maya: 가로 드래그로 확대/축소"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
{
|
||||
"en": {
|
||||
"ai.prefs.control_port": "Port",
|
||||
"ai.prefs.control_port_note": "The port AI agents connect to on this computer (127.0.0.1). 27878 is the default: when it is in use, the next free port is taken. Any other port is used exactly. Point your MCP client at the same port, for example solidcraft-cli mcp --connect 127.0.0.1:7878.",
|
||||
"ai.prefs.control_listening": "Listening on 127.0.0.1:{port}",
|
||||
"ai.prefs.control_not_listening": "Not listening",
|
||||
"ai.prefs.control_port_taken": "Port {port} is in use by another program (or another SolidCraft window). Choose another port.",
|
||||
"ai.prefs.control_failed": "The control channel could not start: {error}",
|
||||
"ai.prefs.control_from_launch": "Started with --control on port {port} for this run. Changes here take effect the next time SolidCraft starts without --control."
|
||||
},
|
||||
"de": {
|
||||
"ai.prefs.control_port": "Port",
|
||||
"ai.prefs.control_port_note": "Der Port, über den sich KI-Agenten auf diesem Computer verbinden (127.0.0.1). Standard ist 27878: Ist er belegt, wird der nächste freie Port genommen. Jeder andere Port wird genau so verwendet. Richte deinen MCP-Client auf denselben Port, zum Beispiel solidcraft-cli mcp --connect 127.0.0.1:7878.",
|
||||
"ai.prefs.control_listening": "Wartet auf 127.0.0.1:{port}",
|
||||
"ai.prefs.control_not_listening": "Nicht aktiv",
|
||||
"ai.prefs.control_port_taken": "Port {port} wird von einem anderen Programm (oder einem anderen SolidCraft-Fenster) verwendet. Wähle einen anderen Port.",
|
||||
"ai.prefs.control_failed": "Der Steuerkanal konnte nicht starten: {error}",
|
||||
"ai.prefs.control_from_launch": "Für diese Sitzung mit --control auf Port {port} gestartet. Änderungen hier gelten beim nächsten Start von SolidCraft ohne --control."
|
||||
},
|
||||
"ja": {
|
||||
"ai.prefs.control_port": "ポート",
|
||||
"ai.prefs.control_port_note": "このコンピューター上で AI エージェントが接続するポート (127.0.0.1)。既定は 27878 で、使用中の場合は次の空いているポートを使います。それ以外のポートはそのまま使います。MCP クライアントも同じポートに向けてください (例: solidcraft-cli mcp --connect 127.0.0.1:7878)。",
|
||||
"ai.prefs.control_listening": "127.0.0.1:{port} で待機中",
|
||||
"ai.prefs.control_not_listening": "待機していません",
|
||||
"ai.prefs.control_port_taken": "ポート {port} は別のプログラム (または別の SolidCraft ウィンドウ) が使用しています。別のポートを選んでください。",
|
||||
"ai.prefs.control_failed": "コントロールチャネルを開始できませんでした: {error}",
|
||||
"ai.prefs.control_from_launch": "この実行は --control でポート {port} を使って開始されました。ここでの変更は、次に --control なしで SolidCraft を起動したときに反映されます。"
|
||||
},
|
||||
"zh": {
|
||||
"ai.prefs.control_port": "端口",
|
||||
"ai.prefs.control_port_note": "AI 代理在本机上连接的端口 (127.0.0.1)。默认为 27878:若被占用,则使用下一个空闲端口。其他端口按原样使用。请让 MCP 客户端指向同一端口,例如 solidcraft-cli mcp --connect 127.0.0.1:7878。",
|
||||
"ai.prefs.control_listening": "正在监听 127.0.0.1:{port}",
|
||||
"ai.prefs.control_not_listening": "未在监听",
|
||||
"ai.prefs.control_port_taken": "端口 {port} 已被其他程序(或另一个 SolidCraft 窗口)占用。请选择其他端口。",
|
||||
"ai.prefs.control_failed": "控制通道无法启动:{error}",
|
||||
"ai.prefs.control_from_launch": "本次运行通过 --control 在端口 {port} 上启动。此处的更改将在下次不带 --control 启动 SolidCraft 时生效。"
|
||||
},
|
||||
"ko": {
|
||||
"ai.prefs.control_port": "포트",
|
||||
"ai.prefs.control_port_note": "이 컴퓨터에서 AI 에이전트가 연결하는 포트(127.0.0.1)입니다. 기본값은 27878이며, 사용 중이면 다음 빈 포트를 사용합니다. 다른 포트는 그대로 사용합니다. MCP 클라이언트도 같은 포트를 가리키게 하세요(예: solidcraft-cli mcp --connect 127.0.0.1:7878).",
|
||||
"ai.prefs.control_listening": "127.0.0.1:{port}에서 대기 중",
|
||||
"ai.prefs.control_not_listening": "대기하지 않음",
|
||||
"ai.prefs.control_port_taken": "포트 {port}을(를) 다른 프로그램(또는 다른 SolidCraft 창)이 사용 중입니다. 다른 포트를 선택하세요.",
|
||||
"ai.prefs.control_failed": "제어 채널을 시작할 수 없습니다: {error}",
|
||||
"ai.prefs.control_from_launch": "이번 실행은 --control로 포트 {port}에서 시작되었습니다. 여기서 바꾼 내용은 다음에 --control 없이 SolidCraft를 시작할 때 적용됩니다."
|
||||
},
|
||||
"vi": {
|
||||
"ai.prefs.control_port": "Cổng",
|
||||
"ai.prefs.control_port_note": "Cổng mà các tác tử AI kết nối trên máy tính này (127.0.0.1). Mặc định là 27878: nếu cổng đang được dùng, cổng trống tiếp theo sẽ được dùng. Mọi cổng khác được dùng đúng như vậy. Hãy trỏ ứng dụng MCP của bạn đến cùng cổng, ví dụ solidcraft-cli mcp --connect 127.0.0.1:7878.",
|
||||
"ai.prefs.control_listening": "Đang lắng nghe trên 127.0.0.1:{port}",
|
||||
"ai.prefs.control_not_listening": "Không lắng nghe",
|
||||
"ai.prefs.control_port_taken": "Cổng {port} đang được một chương trình khác (hoặc một cửa sổ SolidCraft khác) sử dụng. Hãy chọn cổng khác.",
|
||||
"ai.prefs.control_failed": "Không thể khởi động kênh điều khiển: {error}",
|
||||
"ai.prefs.control_from_launch": "Lần chạy này được khởi động với --control trên cổng {port}. Các thay đổi ở đây có hiệu lực vào lần tới SolidCraft khởi động mà không có --control."
|
||||
},
|
||||
"ar": {
|
||||
"ai.prefs.control_port": "المنفذ",
|
||||
"ai.prefs.control_port_note": "المنفذ الذي يتصل عبره وكلاء الذكاء الاصطناعي على هذا الحاسوب (127.0.0.1). الافتراضي هو 27878: إذا كان مستخدمًا يُستخدم المنفذ الحر التالي. أي منفذ آخر يُستخدم كما هو. وجّه عميل MCP إلى المنفذ نفسه، مثل solidcraft-cli mcp --connect 127.0.0.1:7878.",
|
||||
"ai.prefs.control_listening": "يستمع على 127.0.0.1:{port}",
|
||||
"ai.prefs.control_not_listening": "لا يستمع",
|
||||
"ai.prefs.control_port_taken": "المنفذ {port} يستخدمه برنامج آخر (أو نافذة SolidCraft أخرى). اختر منفذًا آخر.",
|
||||
"ai.prefs.control_failed": "تعذّر بدء قناة التحكم: {error}",
|
||||
"ai.prefs.control_from_launch": "بدأ هذا التشغيل باستخدام --control على المنفذ {port}. تسري التغييرات هنا عند تشغيل SolidCraft في المرة القادمة دون --control."
|
||||
},
|
||||
"he": {
|
||||
"ai.prefs.control_port": "פורט",
|
||||
"ai.prefs.control_port_note": "הפורט שאליו סוכני AI מתחברים במחשב זה (127.0.0.1). ברירת המחדל היא 27878: אם הוא תפוס, נלקח הפורט הפנוי הבא. כל פורט אחר משמש בדיוק כפי שהוא. כוונו את לקוח ה-MCP לאותו פורט, למשל solidcraft-cli mcp --connect 127.0.0.1:7878.",
|
||||
"ai.prefs.control_listening": "מאזין ב-127.0.0.1:{port}",
|
||||
"ai.prefs.control_not_listening": "לא מאזין",
|
||||
"ai.prefs.control_port_taken": "פורט {port} בשימוש של תוכנה אחרת (או חלון SolidCraft אחר). בחרו פורט אחר.",
|
||||
"ai.prefs.control_failed": "לא ניתן היה להפעיל את ערוץ הבקרה: {error}",
|
||||
"ai.prefs.control_from_launch": "הפעלה זו התחילה עם --control בפורט {port}. שינויים כאן ייכנסו לתוקף בפעם הבאה ש-SolidCraft יופעל ללא --control."
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
{
|
||||
"en": {
|
||||
"operations.cancel": "Cancel {name}",
|
||||
"operations.cancelled": "{name} cancelled",
|
||||
"operations.cancelling": "Cancelling…",
|
||||
"operations.cannot_cancel": "{name} can't be cancelled",
|
||||
"operations.feature": "Feature",
|
||||
"operations.feature_edit": "Edit feature",
|
||||
"operations.meshing": "Loading parts",
|
||||
"operations.queued": "Queued",
|
||||
"operations.stopped": "Cancelled",
|
||||
"prefs.operations_panel": "Show operations in the view",
|
||||
"prefs.operations_panel_note": "Long operations (opening a file, computing a feature, an agent's command) show in the view's bottom-right corner with their progress and a button that cancels them. Off: a Computing notice, as before."
|
||||
},
|
||||
"de": {
|
||||
"operations.cancel": "{name} abbrechen",
|
||||
"operations.cancelled": "{name} abgebrochen",
|
||||
"operations.cancelling": "Wird abgebrochen…",
|
||||
"operations.cannot_cancel": "{name} kann nicht abgebrochen werden",
|
||||
"operations.feature": "Feature",
|
||||
"operations.feature_edit": "Feature bearbeiten",
|
||||
"operations.meshing": "Teile werden geladen",
|
||||
"operations.queued": "Wartet",
|
||||
"operations.stopped": "Abgebrochen",
|
||||
"prefs.operations_panel": "Vorgänge in der Ansicht zeigen",
|
||||
"prefs.operations_panel_note": "Lange Vorgänge (eine Datei öffnen, ein Feature berechnen, der Befehl eines Agenten) erscheinen unten rechts in der Ansicht mit ihrem Fortschritt und einer Schaltfläche zum Abbrechen. Aus: wie bisher ein Hinweis „Berechnung“."
|
||||
},
|
||||
"ja": {
|
||||
"operations.cancel": "{name} をキャンセル",
|
||||
"operations.cancelled": "{name} をキャンセルしました",
|
||||
"operations.cancelling": "キャンセル中…",
|
||||
"operations.cannot_cancel": "{name} はキャンセルできません",
|
||||
"operations.feature": "フィーチャー",
|
||||
"operations.feature_edit": "フィーチャーを編集",
|
||||
"operations.meshing": "パーツを読み込み中",
|
||||
"operations.queued": "待機中",
|
||||
"operations.stopped": "キャンセル済み",
|
||||
"prefs.operations_panel": "ビューに処理を表示",
|
||||
"prefs.operations_panel_note": "時間のかかる処理(ファイルを開く、フィーチャーの計算、エージェントのコマンド)が、進行状況とキャンセルボタンとともにビューの右下に表示されます。オフ:従来どおり「計算中」の通知を表示します。"
|
||||
},
|
||||
"ko": {
|
||||
"operations.cancel": "{name} 취소",
|
||||
"operations.cancelled": "{name} 취소됨",
|
||||
"operations.cancelling": "취소하는 중…",
|
||||
"operations.cannot_cancel": "{name}은(는) 취소할 수 없습니다",
|
||||
"operations.feature": "피처",
|
||||
"operations.feature_edit": "피처 편집",
|
||||
"operations.meshing": "파트 불러오는 중",
|
||||
"operations.queued": "대기 중",
|
||||
"operations.stopped": "취소됨",
|
||||
"prefs.operations_panel": "뷰에 작업 표시",
|
||||
"prefs.operations_panel_note": "오래 걸리는 작업(파일 열기, 피처 계산, 에이전트 명령)이 진행 상황과 취소 버튼과 함께 뷰의 오른쪽 아래에 표시됩니다. 끄면: 이전처럼 계산 중 알림이 표시됩니다."
|
||||
},
|
||||
"zh": {
|
||||
"operations.cancel": "取消{name}",
|
||||
"operations.cancelled": "已取消{name}",
|
||||
"operations.cancelling": "正在取消…",
|
||||
"operations.cannot_cancel": "无法取消{name}",
|
||||
"operations.feature": "特征",
|
||||
"operations.feature_edit": "编辑特征",
|
||||
"operations.meshing": "正在加载零件",
|
||||
"operations.queued": "排队中",
|
||||
"operations.stopped": "已取消",
|
||||
"prefs.operations_panel": "在视图中显示操作",
|
||||
"prefs.operations_panel_note": "耗时的操作(打开文件、计算特征、智能体的命令)会连同进度和取消按钮显示在视图右下角。关闭:与以前一样显示“正在计算”提示。"
|
||||
},
|
||||
"ar": {
|
||||
"operations.cancel": "إلغاء {name}",
|
||||
"operations.cancelled": "تم إلغاء {name}",
|
||||
"operations.cancelling": "جارٍ الإلغاء…",
|
||||
"operations.cannot_cancel": "لا يمكن إلغاء {name}",
|
||||
"operations.feature": "ميزة",
|
||||
"operations.feature_edit": "تحرير الميزة",
|
||||
"operations.meshing": "جارٍ تحميل الأجزاء",
|
||||
"operations.queued": "في الانتظار",
|
||||
"operations.stopped": "أُلغي",
|
||||
"prefs.operations_panel": "إظهار العمليات في العرض",
|
||||
"prefs.operations_panel_note": "تظهر العمليات الطويلة (فتح ملف، حساب ميزة، أمر من وكيل) في الزاوية السفلية اليمنى من العرض مع تقدّمها وزر لإلغائها. عند الإيقاف: إشعار «جارٍ الحساب» كما كان من قبل."
|
||||
},
|
||||
"he": {
|
||||
"operations.cancel": "ביטול {name}",
|
||||
"operations.cancelled": "{name} בוטל",
|
||||
"operations.cancelling": "מבטל…",
|
||||
"operations.cannot_cancel": "לא ניתן לבטל את {name}",
|
||||
"operations.feature": "פיצ'ר",
|
||||
"operations.feature_edit": "עריכת פיצ'ר",
|
||||
"operations.meshing": "טוען חלקים",
|
||||
"operations.queued": "ממתין",
|
||||
"operations.stopped": "בוטל",
|
||||
"prefs.operations_panel": "הצגת פעולות בתצוגה",
|
||||
"prefs.operations_panel_note": "פעולות ארוכות (פתיחת קובץ, חישוב פיצ'ר, פקודה של סוכן) מוצגות בפינה הימנית התחתונה של התצוגה עם ההתקדמות שלהן וכפתור לביטולן. כבוי: הודעת „מחשב” כמו קודם."
|
||||
},
|
||||
"vi": {
|
||||
"operations.cancel": "Hủy {name}",
|
||||
"operations.cancelled": "Đã hủy {name}",
|
||||
"operations.cancelling": "Đang hủy…",
|
||||
"operations.cannot_cancel": "Không thể hủy {name}",
|
||||
"operations.feature": "Đặc trưng",
|
||||
"operations.feature_edit": "Sửa đặc trưng",
|
||||
"operations.meshing": "Đang tải chi tiết",
|
||||
"operations.queued": "Đang chờ",
|
||||
"operations.stopped": "Đã hủy",
|
||||
"prefs.operations_panel": "Hiện các thao tác trong khung nhìn",
|
||||
"prefs.operations_panel_note": "Các thao tác dài (mở tệp, tính đặc trưng, lệnh của tác tử) hiện ở góc dưới bên phải khung nhìn cùng tiến độ và nút hủy. Tắt: thông báo Đang tính như trước."
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"en": {
|
||||
"Drag to place it on another face.": "Drag to place it on another face."
|
||||
},
|
||||
"ar": {
|
||||
"Drag to place it on another face.": "اسحب لوضعه على وجه آخر."
|
||||
},
|
||||
"de": {
|
||||
"Drag to place it on another face.": "Ziehen, um es auf eine andere Fläche zu setzen."
|
||||
},
|
||||
"he": {
|
||||
"Drag to place it on another face.": "יש לגרור כדי להציב אותו על פאה אחרת."
|
||||
},
|
||||
"ja": {
|
||||
"Drag to place it on another face.": "ドラッグして別の面に配置します。"
|
||||
},
|
||||
"ko": {
|
||||
"Drag to place it on another face.": "드래그하여 다른 면에 배치합니다."
|
||||
},
|
||||
"pl": {
|
||||
"Drag to place it on another face.": "Przeciągnij, aby umieścić go na innej ścianie."
|
||||
},
|
||||
"vi": {
|
||||
"Drag to place it on another face.": "Kéo để đặt nó lên một bề mặt khác."
|
||||
},
|
||||
"zh": {
|
||||
"Drag to place it on another face.": "拖动以将其放置到另一个面上。"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"en": { "cmd.ui.toggle_visibility": "Show/Hide Selection" },
|
||||
"de": { "cmd.ui.toggle_visibility": "Auswahl ein-/ausblenden" },
|
||||
"ar": { "cmd.ui.toggle_visibility": "إظهار/إخفاء التحديد" },
|
||||
"he": { "cmd.ui.toggle_visibility": "הצגה/הסתרה של הבחירה" },
|
||||
"ja": { "cmd.ui.toggle_visibility": "選択項目の表示/非表示" },
|
||||
"ko": { "cmd.ui.toggle_visibility": "선택 항목 표시/숨기기" },
|
||||
"vi": { "cmd.ui.toggle_visibility": "Hiển thị/Ẩn mục đã chọn" },
|
||||
"zh": { "cmd.ui.toggle_visibility": "显示/隐藏所选项" }
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"en": {
|
||||
"ui.relink_one_done": "Source relinked for this instance.",
|
||||
"ui.relink_source_one": "Relink Source…"
|
||||
},
|
||||
"ar": {
|
||||
"ui.relink_one_done": "أُعيد ربط المصدر لهذه النسخة.",
|
||||
"ui.relink_source_one": "إعادة ربط المصدر…"
|
||||
},
|
||||
"de": {
|
||||
"ui.relink_one_done": "Quelle für diese Instanz neu verknüpft.",
|
||||
"ui.relink_source_one": "Quelle neu verknüpfen…"
|
||||
},
|
||||
"he": {
|
||||
"ui.relink_one_done": "המקור קושר מחדש למופע זה.",
|
||||
"ui.relink_source_one": "קישור מחדש למקור…"
|
||||
},
|
||||
"ja": {
|
||||
"ui.relink_one_done": "このインスタンスの参照元を再リンクしました。",
|
||||
"ui.relink_source_one": "参照元を再リンク…"
|
||||
},
|
||||
"vi": {
|
||||
"ui.relink_one_done": "Đã liên kết lại nguồn cho thể hiện này.",
|
||||
"ui.relink_source_one": "Liên kết lại nguồn…"
|
||||
},
|
||||
"zh": {
|
||||
"ui.relink_one_done": "已为此实例重新链接源文件。",
|
||||
"ui.relink_source_one": "重新链接源文件…"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
{
|
||||
"en": {
|
||||
"dialog.right_click_pick": "Select {input} first",
|
||||
"ui.right_click_confirms": "Right-click confirms dialog inputs",
|
||||
"ui.right_click_confirms_tip": "With a dialog open, a right-click in the view goes on to its next empty input, and on the last one runs OK"
|
||||
},
|
||||
"cs": {
|
||||
"dialog.right_click_pick": "Nejprve vyberte {input}",
|
||||
"ui.right_click_confirms": "Pravé kliknutí potvrzuje vstupy dialogu",
|
||||
"ui.right_click_confirms_tip": "Při otevřeném dialogu přejde pravé kliknutí v zobrazení na další prázdný vstup a u posledního provede OK"
|
||||
},
|
||||
"da": {
|
||||
"dialog.right_click_pick": "Vælg først {input}",
|
||||
"ui.right_click_confirms": "Højreklik bekræfter dialogens input",
|
||||
"ui.right_click_confirms_tip": "Med en dialog åben går et højreklik i visningen videre til næste tomme input, og ved det sidste udføres OK"
|
||||
},
|
||||
"de": {
|
||||
"dialog.right_click_pick": "Zuerst {input} auswählen",
|
||||
"ui.right_click_confirms": "Rechtsklick bestätigt Dialogeingaben",
|
||||
"ui.right_click_confirms_tip": "Bei offenem Dialog springt ein Rechtsklick in der Ansicht zur nächsten leeren Eingabe und führt bei der letzten OK aus"
|
||||
},
|
||||
"es": {
|
||||
"dialog.right_click_pick": "Selecciona primero {input}",
|
||||
"ui.right_click_confirms": "El clic derecho confirma las entradas del diálogo",
|
||||
"ui.right_click_confirms_tip": "Con un diálogo abierto, un clic derecho en la vista pasa a la siguiente entrada vacía y, en la última, ejecuta OK"
|
||||
},
|
||||
"fr": {
|
||||
"dialog.right_click_pick": "Sélectionner d’abord {input}",
|
||||
"ui.right_click_confirms": "Le clic droit valide les entrées du dialogue",
|
||||
"ui.right_click_confirms_tip": "Avec un dialogue ouvert, un clic droit dans la vue passe à l’entrée vide suivante et, sur la dernière, exécute OK"
|
||||
},
|
||||
"gl": {
|
||||
"dialog.right_click_pick": "Selecciona primeiro {input}",
|
||||
"ui.right_click_confirms": "O clic dereito confirma as entradas do diálogo",
|
||||
"ui.right_click_confirms_tip": "Cun diálogo aberto, un clic dereito na vista pasa á seguinte entrada baleira e, na última, executa OK"
|
||||
},
|
||||
"hu": {
|
||||
"dialog.right_click_pick": "Előbb jelölje ki ezt: {input}",
|
||||
"ui.right_click_confirms": "A jobb kattintás jóváhagyja a párbeszédablak bemeneteit",
|
||||
"ui.right_click_confirms_tip": "Nyitott párbeszédablaknál a nézetben a jobb kattintás a következő üres bemenetre lép, az utolsónál pedig OK-t nyom"
|
||||
},
|
||||
"id": {
|
||||
"dialog.right_click_pick": "Pilih {input} terlebih dahulu",
|
||||
"ui.right_click_confirms": "Klik kanan mengonfirmasi input dialog",
|
||||
"ui.right_click_confirms_tip": "Saat dialog terbuka, klik kanan di tampilan berpindah ke input kosong berikutnya, dan pada input terakhir menjalankan OK"
|
||||
},
|
||||
"it": {
|
||||
"dialog.right_click_pick": "Seleziona prima {input}",
|
||||
"ui.right_click_confirms": "Il clic destro conferma gli input della finestra di dialogo",
|
||||
"ui.right_click_confirms_tip": "Con una finestra di dialogo aperta, un clic destro nella vista passa al successivo input vuoto e, sull’ultimo, esegue OK"
|
||||
},
|
||||
"ja": {
|
||||
"dialog.right_click_pick": "先に {input} を選択",
|
||||
"ui.right_click_confirms": "右クリックでダイアログの入力を確定",
|
||||
"ui.right_click_confirms_tip": "ダイアログが開いているとき、ビューで右クリックすると次の空の入力へ進み、最後の入力では OK を実行します"
|
||||
},
|
||||
"ko": {
|
||||
"dialog.right_click_pick": "먼저 {input} 선택",
|
||||
"ui.right_click_confirms": "오른쪽 클릭으로 대화 상자 입력 확인",
|
||||
"ui.right_click_confirms_tip": "대화 상자가 열려 있을 때 뷰에서 오른쪽 클릭하면 다음 빈 입력으로 이동하고, 마지막 입력에서는 OK를 실행합니다"
|
||||
},
|
||||
"ms": {
|
||||
"dialog.right_click_pick": "Pilih {input} dahulu",
|
||||
"ui.right_click_confirms": "Klik kanan mengesahkan input dialog",
|
||||
"ui.right_click_confirms_tip": "Apabila dialog dibuka, klik kanan dalam paparan beralih ke input kosong seterusnya, dan pada input terakhir menjalankan OK"
|
||||
},
|
||||
"nl": {
|
||||
"dialog.right_click_pick": "Eerst {input} selecteren",
|
||||
"ui.right_click_confirms": "Rechtsklik bevestigt dialooginvoer",
|
||||
"ui.right_click_confirms_tip": "Met een dialoog open gaat een rechtsklik in de weergave naar de volgende lege invoer, en bij de laatste voert hij OK uit"
|
||||
},
|
||||
"pl": {
|
||||
"dialog.right_click_pick": "Najpierw zaznacz {input}",
|
||||
"ui.right_click_confirms": "Prawy klik zatwierdza pola okna dialogowego",
|
||||
"ui.right_click_confirms_tip": "Przy otwartym oknie dialogowym prawy klik w widoku przechodzi do następnego pustego pola, a przy ostatnim wykonuje OK"
|
||||
},
|
||||
"pt-BR": {
|
||||
"dialog.right_click_pick": "Selecione {input} primeiro",
|
||||
"ui.right_click_confirms": "O clique direito confirma as entradas da caixa de diálogo",
|
||||
"ui.right_click_confirms_tip": "Com uma caixa de diálogo aberta, um clique direito na vista passa para a próxima entrada vazia e, na última, executa OK"
|
||||
},
|
||||
"ro": {
|
||||
"dialog.right_click_pick": "Selectați mai întâi {input}",
|
||||
"ui.right_click_confirms": "Clicul dreapta confirmă intrările dialogului",
|
||||
"ui.right_click_confirms_tip": "Cu un dialog deschis, un clic dreapta în vedere trece la următoarea intrare goală, iar la ultima rulează OK"
|
||||
},
|
||||
"ru": {
|
||||
"dialog.right_click_pick": "Сначала выберите {input}",
|
||||
"ui.right_click_confirms": "Правый щелчок подтверждает поля диалога",
|
||||
"ui.right_click_confirms_tip": "При открытом диалоге правый щелчок в виде переходит к следующему пустому полю, а на последнем выполняет OK"
|
||||
},
|
||||
"sv": {
|
||||
"dialog.right_click_pick": "Markera {input} först",
|
||||
"ui.right_click_confirms": "Högerklick bekräftar dialogens indata",
|
||||
"ui.right_click_confirms_tip": "Med en dialog öppen går ett högerklick i vyn vidare till nästa tomma indata, och vid den sista körs OK"
|
||||
},
|
||||
"tr": {
|
||||
"dialog.right_click_pick": "Önce {input} seçin",
|
||||
"ui.right_click_confirms": "Sağ tıklama iletişim kutusu girişlerini onaylar",
|
||||
"ui.right_click_confirms_tip": "Bir iletişim kutusu açıkken görünümde sağ tıklama bir sonraki boş girişe geçer, sonuncusunda ise OK çalıştırır"
|
||||
},
|
||||
"uk": {
|
||||
"dialog.right_click_pick": "Спочатку виберіть {input}",
|
||||
"ui.right_click_confirms": "Правий клік підтверджує поля діалогу",
|
||||
"ui.right_click_confirms_tip": "Коли діалог відкрито, правий клік у вигляді переходить до наступного порожнього поля, а на останньому виконує OK"
|
||||
},
|
||||
"vi": {
|
||||
"dialog.right_click_pick": "Chọn {input} trước",
|
||||
"ui.right_click_confirms": "Nhấp chuột phải xác nhận đầu vào của hộp thoại",
|
||||
"ui.right_click_confirms_tip": "Khi hộp thoại đang mở, nhấp chuột phải trong khung nhìn chuyển sang đầu vào trống tiếp theo, và ở đầu vào cuối cùng sẽ chạy OK"
|
||||
},
|
||||
"zh": {
|
||||
"dialog.right_click_pick": "请先选择{input}",
|
||||
"ui.right_click_confirms": "右键确认对话框输入",
|
||||
"ui.right_click_confirms_tip": "对话框打开时,在视图中右键单击会转到下一个空输入,在最后一个输入上执行 OK"
|
||||
},
|
||||
"zh-TW": {
|
||||
"dialog.right_click_pick": "請先選擇{input}",
|
||||
"ui.right_click_confirms": "右鍵確認對話方塊輸入",
|
||||
"ui.right_click_confirms_tip": "對話方塊開啟時,在視圖中按右鍵會轉到下一個空白輸入,在最後一個輸入上執行 OK"
|
||||
},
|
||||
"ar": {
|
||||
"dialog.right_click_pick": "اختر {input} أولاً",
|
||||
"ui.right_click_confirms": "النقر بزر الماوس الأيمن يؤكد مدخلات مربع الحوار",
|
||||
"ui.right_click_confirms_tip": "عندما يكون مربع حوار مفتوحاً، ينتقل النقر بزر الماوس الأيمن في العرض إلى المدخل الفارغ التالي، وعند المدخل الأخير ينفّذ موافق"
|
||||
},
|
||||
"he": {
|
||||
"dialog.right_click_pick": "יש לבחור תחילה {input}",
|
||||
"ui.right_click_confirms": "לחיצה ימנית מאשרת קלטים בתיבת דו-שיח",
|
||||
"ui.right_click_confirms_tip": "כאשר תיבת דו-שיח פתוחה, לחיצה ימנית בתצוגה עוברת לקלט הריק הבא, ובקלט האחרון מבצעת אישור"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"en": { "cmd.selection_get": "Get Selection" },
|
||||
"ar": { "cmd.selection_get": "الحصول على التحديد" },
|
||||
"he": { "cmd.selection_get": "קבלת הבחירה" },
|
||||
"ja": { "cmd.selection_get": "選択を取得" },
|
||||
"vi": { "cmd.selection_get": "Lấy vùng chọn" },
|
||||
"zh": { "cmd.selection_get": "获取选择" }
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
{
|
||||
"en": {
|
||||
"prefs.sketch.cursor_coordinates": "Show the cursor's coordinates in a sketch",
|
||||
"prefs.sketch.cursor_coordinates_note": "Beside the pointer, its X and Y from the sketch origin, also with no tool running. Off: only while a tool places a point."
|
||||
},
|
||||
"ar": {
|
||||
"prefs.sketch.cursor_coordinates": "إظهار إحداثيات المؤشر في الرسم",
|
||||
"prefs.sketch.cursor_coordinates_note": "بجانب المؤشر، قيمتا X وY من أصل الرسم، حتى دون تشغيل أي أداة. إيقاف: فقط أثناء وضع أداة لنقطة."
|
||||
},
|
||||
"de": {
|
||||
"prefs.sketch.cursor_coordinates": "Cursorkoordinaten in der Skizze anzeigen",
|
||||
"prefs.sketch.cursor_coordinates_note": "Neben dem Zeiger seine X- und Y-Werte vom Skizzenursprung, auch ohne aktives Werkzeug. Aus: nur während ein Werkzeug einen Punkt setzt."
|
||||
},
|
||||
"es": {
|
||||
"prefs.sketch.cursor_coordinates": "Mostrar las coordenadas del cursor en un croquis",
|
||||
"prefs.sketch.cursor_coordinates_note": "Junto al puntero, su X e Y desde el origen del croquis, también sin ninguna herramienta activa. Desactivado: solo mientras una herramienta coloca un punto."
|
||||
},
|
||||
"fr": {
|
||||
"prefs.sketch.cursor_coordinates": "Afficher les coordonnées du curseur dans une esquisse",
|
||||
"prefs.sketch.cursor_coordinates_note": "À côté du pointeur, ses X et Y depuis l'origine de l'esquisse, même sans outil actif. Désactivé : seulement pendant qu'un outil place un point."
|
||||
},
|
||||
"he": {
|
||||
"prefs.sketch.cursor_coordinates": "הצגת קואורדינטות הסמן בסקיצה",
|
||||
"prefs.sketch.cursor_coordinates_note": "ליד הסמן, ערכי X ו-Y שלו מראשית הסקיצה, גם כשאין כלי פעיל. כבוי: רק בזמן שכלי ממקם נקודה."
|
||||
},
|
||||
"it": {
|
||||
"prefs.sketch.cursor_coordinates": "Mostra le coordinate del cursore in uno schizzo",
|
||||
"prefs.sketch.cursor_coordinates_note": "Accanto al puntatore, la sua X e Y dall'origine dello schizzo, anche senza strumenti attivi. Disattivato: solo mentre uno strumento posiziona un punto."
|
||||
},
|
||||
"ja": {
|
||||
"prefs.sketch.cursor_coordinates": "スケッチでカーソル座標を表示",
|
||||
"prefs.sketch.cursor_coordinates_note": "ツールを実行していないときも、ポインターの横にスケッチ原点からの X と Y を表示します。オフ: ツールで点を配置している間だけ表示します。"
|
||||
},
|
||||
"ko": {
|
||||
"prefs.sketch.cursor_coordinates": "스케치에서 커서 좌표 표시",
|
||||
"prefs.sketch.cursor_coordinates_note": "도구를 실행하지 않을 때도 포인터 옆에 스케치 원점 기준 X와 Y를 표시합니다. 끄기: 도구로 점을 배치하는 동안에만 표시합니다."
|
||||
},
|
||||
"pl": {
|
||||
"prefs.sketch.cursor_coordinates": "Pokazuj współrzędne kursora w szkicu",
|
||||
"prefs.sketch.cursor_coordinates_note": "Obok wskaźnika jego X i Y od początku szkicu, także gdy żadne narzędzie nie działa. Wyłączone: tylko gdy narzędzie umieszcza punkt."
|
||||
},
|
||||
"pt-BR": {
|
||||
"prefs.sketch.cursor_coordinates": "Mostrar as coordenadas do cursor em um esboço",
|
||||
"prefs.sketch.cursor_coordinates_note": "Ao lado do ponteiro, seu X e Y a partir da origem do esboço, também sem nenhuma ferramenta ativa. Desativado: só enquanto uma ferramenta posiciona um ponto."
|
||||
},
|
||||
"ru": {
|
||||
"prefs.sketch.cursor_coordinates": "Показывать координаты курсора в эскизе",
|
||||
"prefs.sketch.cursor_coordinates_note": "Рядом с указателем его X и Y от начала координат эскиза, даже без активного инструмента. Выкл.: только пока инструмент ставит точку."
|
||||
},
|
||||
"vi": {
|
||||
"prefs.sketch.cursor_coordinates": "Hiển thị tọa độ con trỏ trong bản phác thảo",
|
||||
"prefs.sketch.cursor_coordinates_note": "Bên cạnh con trỏ, X và Y của nó tính từ gốc bản phác thảo, kể cả khi không có công cụ nào chạy. Tắt: chỉ khi một công cụ đang đặt điểm."
|
||||
},
|
||||
"zh": {
|
||||
"prefs.sketch.cursor_coordinates": "在草图中显示光标坐标",
|
||||
"prefs.sketch.cursor_coordinates_note": "即使没有运行工具,也在指针旁显示其相对于草图原点的 X 和 Y。关闭:仅在工具放置点时显示。"
|
||||
},
|
||||
"zh-TW": {
|
||||
"prefs.sketch.cursor_coordinates": "在草圖中顯示游標座標",
|
||||
"prefs.sketch.cursor_coordinates_note": "即使沒有執行工具,也在指標旁顯示其相對於草圖原點的 X 和 Y。關閉:僅在工具放置點時顯示。"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
{
|
||||
"en": {
|
||||
"ui.sketch_links_added_curve": "{command} added 1 curve to the sketch.",
|
||||
"ui.sketch_links_added_curves": "{command} added {count} curves to the sketch.",
|
||||
"ui.sketch_links_added_point": "{command} added 1 point to the sketch.",
|
||||
"ui.sketch_links_added_points": "{command} added {count} points to the sketch.",
|
||||
"ui.sketch_links_hidden": "The result is hidden because {option} is off in the sketch palette.",
|
||||
"ui.sketch_links_added_curves_and_points": "{command} added {curves} and {points} to the sketch.",
|
||||
"ui.sketch_links_curve_count_one": "1 curve",
|
||||
"ui.sketch_links_curve_count": "{count} curves",
|
||||
"ui.sketch_links_point_count_one": "1 point",
|
||||
"ui.sketch_links_point_count": "{count} points"
|
||||
},
|
||||
"ar": {
|
||||
"ui.sketch_links_added_curve": "أضاف {command} منحنى واحدًا إلى الرسم.",
|
||||
"ui.sketch_links_added_curves": "أضاف {command} منحنيات إلى الرسم (العدد: {count}).",
|
||||
"ui.sketch_links_added_point": "أضاف {command} نقطة واحدة إلى الرسم.",
|
||||
"ui.sketch_links_added_points": "أضاف {command} نقاطًا إلى الرسم (العدد: {count}).",
|
||||
"ui.sketch_links_hidden": "النتيجة مخفية لأن خيار {option} مُعطَّل في خيارات الرسم.",
|
||||
"ui.sketch_links_added_curves_and_points": "أضاف {command} إلى الرسم {curves} و{points}.",
|
||||
"ui.sketch_links_curve_count_one": "منحنى واحدًا",
|
||||
"ui.sketch_links_curve_count": "منحنيات (العدد: {count})",
|
||||
"ui.sketch_links_point_count_one": "نقطة واحدة",
|
||||
"ui.sketch_links_point_count": "نقاطًا (العدد: {count})"
|
||||
},
|
||||
"he": {
|
||||
"ui.sketch_links_added_curve": "{command} הוסיף עקומה אחת לסקיצה.",
|
||||
"ui.sketch_links_added_curves": "{command} הוסיף {count} עקומות לסקיצה.",
|
||||
"ui.sketch_links_added_point": "{command} הוסיף נקודה אחת לסקיצה.",
|
||||
"ui.sketch_links_added_points": "{command} הוסיף {count} נקודות לסקיצה.",
|
||||
"ui.sketch_links_hidden": "התוצאה מוסתרת כי האפשרות {option} כבויה באפשרויות הסקיצה.",
|
||||
"ui.sketch_links_added_curves_and_points": "{command} הוסיף לסקיצה {curves} ו־{points}.",
|
||||
"ui.sketch_links_curve_count_one": "עקומה אחת",
|
||||
"ui.sketch_links_curve_count": "{count} עקומות",
|
||||
"ui.sketch_links_point_count_one": "נקודה אחת",
|
||||
"ui.sketch_links_point_count": "{count} נקודות"
|
||||
},
|
||||
"ja": {
|
||||
"ui.sketch_links_added_curve": "{command} でスケッチに曲線を 1 本追加しました。",
|
||||
"ui.sketch_links_added_curves": "{command} でスケッチに曲線を {count} 本追加しました。",
|
||||
"ui.sketch_links_added_point": "{command} でスケッチに点を 1 個追加しました。",
|
||||
"ui.sketch_links_added_points": "{command} でスケッチに点を {count} 個追加しました。",
|
||||
"ui.sketch_links_hidden": "スケッチオプションの {option} がオフのため、結果は表示されていません。",
|
||||
"ui.sketch_links_added_curves_and_points": "{command} でスケッチに{curves}と{points}を追加しました。",
|
||||
"ui.sketch_links_curve_count_one": "曲線 1 本",
|
||||
"ui.sketch_links_curve_count": "曲線 {count} 本",
|
||||
"ui.sketch_links_point_count_one": "点 1 個",
|
||||
"ui.sketch_links_point_count": "点 {count} 個"
|
||||
},
|
||||
"vi": {
|
||||
"ui.sketch_links_added_curve": "{command} đã thêm 1 đường cong vào bản phác thảo.",
|
||||
"ui.sketch_links_added_curves": "{command} đã thêm {count} đường cong vào bản phác thảo.",
|
||||
"ui.sketch_links_added_point": "{command} đã thêm 1 điểm vào bản phác thảo.",
|
||||
"ui.sketch_links_added_points": "{command} đã thêm {count} điểm vào bản phác thảo.",
|
||||
"ui.sketch_links_hidden": "Kết quả bị ẩn vì {option} đang tắt trong Tùy chọn phác thảo.",
|
||||
"ui.sketch_links_added_curves_and_points": "{command} đã thêm {curves} và {points} vào bản phác thảo.",
|
||||
"ui.sketch_links_curve_count_one": "1 đường cong",
|
||||
"ui.sketch_links_curve_count": "{count} đường cong",
|
||||
"ui.sketch_links_point_count_one": "1 điểm",
|
||||
"ui.sketch_links_point_count": "{count} điểm"
|
||||
},
|
||||
"zh": {
|
||||
"ui.sketch_links_added_curve": "{command} 已向草图添加 1 条曲线。",
|
||||
"ui.sketch_links_added_curves": "{command} 已向草图添加 {count} 条曲线。",
|
||||
"ui.sketch_links_added_point": "{command} 已向草图添加 1 个点。",
|
||||
"ui.sketch_links_added_points": "{command} 已向草图添加 {count} 个点。",
|
||||
"ui.sketch_links_hidden": "结果已隐藏,因为草图选项中的“{option}”已关闭。",
|
||||
"ui.sketch_links_added_curves_and_points": "{command} 已向草图添加{curves}和{points}。",
|
||||
"ui.sketch_links_curve_count_one": "1 条曲线",
|
||||
"ui.sketch_links_curve_count": "{count} 条曲线",
|
||||
"ui.sketch_links_point_count_one": "1 个点",
|
||||
"ui.sketch_links_point_count": "{count} 个点"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"en": {
|
||||
"prefs.sketch.max_points": "Largest sketch",
|
||||
"prefs.sketch.max_points_note": "The most points or curves one sketch holds: 20000 by default, at most 200000. Insert SVG and Insert DXF refuse a larger drawing. A large sketch solves and draws more slowly.",
|
||||
"prefs.sketch.max_points_unit": "points"
|
||||
},
|
||||
"ar": {
|
||||
"prefs.sketch.max_points": "أكبر رسم تخطيطي",
|
||||
"prefs.sketch.max_points_note": "أكبر عدد من النقاط أو المنحنيات في رسم تخطيطي واحد: 20000 افتراضيًا، و200000 كحد أقصى. يرفض إدراج SVG وإدراج DXF رسمًا أكبر. الرسم التخطيطي الكبير يُحل ويُعرض بشكل أبطأ.",
|
||||
"prefs.sketch.max_points_unit": "نقطة"
|
||||
},
|
||||
"de": {
|
||||
"prefs.sketch.max_points": "Größte Skizze",
|
||||
"prefs.sketch.max_points_note": "Die meisten Punkte oder Kurven, die eine Skizze aufnimmt: standardmäßig 20000, höchstens 200000. SVG einfügen und DXF einfügen lehnen eine größere Zeichnung ab. Eine große Skizze wird langsamer gelöst und gezeichnet.",
|
||||
"prefs.sketch.max_points_unit": "Punkte"
|
||||
},
|
||||
"he": {
|
||||
"prefs.sketch.max_points": "הסקיצה הגדולה ביותר",
|
||||
"prefs.sketch.max_points_note": "המספר המרבי של נקודות או עקומות בסקיצה אחת: 20000 כברירת מחדל, ועד 200000. הוספת SVG והוספת DXF דוחות שרטוט גדול יותר. סקיצה גדולה נפתרת ומוצגת לאט יותר.",
|
||||
"prefs.sketch.max_points_unit": "נקודות"
|
||||
},
|
||||
"ja": {
|
||||
"prefs.sketch.max_points": "最大スケッチ",
|
||||
"prefs.sketch.max_points_note": "1 つのスケッチに入る点または曲線の最大数です。既定は 20000、上限は 200000 です。SVG を挿入と DXF を挿入は、これより大きい図面を受け付けません。大きなスケッチは解決と描画が遅くなります。",
|
||||
"prefs.sketch.max_points_unit": "点"
|
||||
},
|
||||
"ko": {
|
||||
"prefs.sketch.max_points": "최대 스케치",
|
||||
"prefs.sketch.max_points_note": "스케치 하나에 들어가는 점 또는 곡선의 최대 개수입니다. 기본값은 20000, 최대 200000입니다. SVG 삽입과 DXF 삽입은 이보다 큰 도면을 거부합니다. 큰 스케치는 해석과 그리기가 느려집니다.",
|
||||
"prefs.sketch.max_points_unit": "점"
|
||||
},
|
||||
"vi": {
|
||||
"prefs.sketch.max_points": "Phác thảo lớn nhất",
|
||||
"prefs.sketch.max_points_note": "Số điểm hoặc đường cong tối đa trong một phác thảo: mặc định 20000, tối đa 200000. Chèn tệp SVG và Chèn tệp DXF từ chối bản vẽ lớn hơn. Phác thảo lớn được giải và vẽ chậm hơn.",
|
||||
"prefs.sketch.max_points_unit": "điểm"
|
||||
},
|
||||
"zh": {
|
||||
"prefs.sketch.max_points": "最大草图",
|
||||
"prefs.sketch.max_points_note": "一个草图可容纳的点或曲线的最大数量:默认 20000,最多 200000。插入 SVG 和插入 DXF 会拒绝更大的图形。大型草图的求解和绘制会更慢。",
|
||||
"prefs.sketch.max_points_unit": "点"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"en": {
|
||||
"prefs.sketch.snap_to_visible_grid": "Snap to the grid's visible crossings",
|
||||
"prefs.sketch_snap_to_visible_grid_note": "A point in a sketch snaps to the crossings of the lines the grid draws when the pointer means one, and to the finer lattice between them otherwise. Off: the point snaps to the finer lattice only, as before."
|
||||
},
|
||||
"ar": {
|
||||
"prefs.sketch.snap_to_visible_grid": "الالتقاط عند تقاطع الشبكة المرئي",
|
||||
"prefs.sketch_snap_to_visible_grid_note": "تلتصق النقطة في الرسم عند تقاطع الخطوط التي ترسمها الشبكة عندما يشير المؤشر إلى أحدها، وإلا تلتصق بالشبكة الأدق بينها. عند الإيقاف: تلتصق النقطة بالشبكة الأدق فقط، كما كان."
|
||||
},
|
||||
"de": {
|
||||
"prefs.sketch.snap_to_visible_grid": "Am sichtbaren Schnittpunkt des Rasters fangen",
|
||||
"prefs.sketch_snap_to_visible_grid_note": "Ein Punkt in einer Skizze rastet am Schnittpunkt der vom Raster gezeichneten Linien ein, wenn der Zeiger auf einen davon zeigt, sonst am feineren Gitter zwischen ihnen. Aus: Der Punkt rastet nur am feineren Gitter ein, wie zuvor."
|
||||
},
|
||||
"he": {
|
||||
"prefs.sketch.snap_to_visible_grid": "הצמדה למפגשים הנראים של הרשת",
|
||||
"prefs.sketch_snap_to_visible_grid_note": "נקודה בסקיצה נצמדת למפגש של הקווים שהרשת מציירת כשהמצביע מכוון לאחד מהם, ולרשת הדקה שביניהם אחרת. כבוי: הנקודה נצמדת לרשת הדקה בלבד, כמו קודם."
|
||||
},
|
||||
"ja": {
|
||||
"prefs.sketch.snap_to_visible_grid": "グリッドの交点にスナップ",
|
||||
"prefs.sketch_snap_to_visible_grid_note": "スケッチ内の点は、グリッドが描画する線の交点にポインターが指しているときはその交点にスナップし、それ以外ではその間のより細かい格子の交点にスナップします。オフ: 前也是一样で、点はより細かい格子の交点にだけスナップします。"
|
||||
},
|
||||
"ko": {
|
||||
"prefs.sketch.snap_to_visible_grid": "격자의 보이는 교차점에 스냅",
|
||||
"prefs.sketch_snap_to_visible_grid_note": "스케치의 점은 포인터가 가리키는 경우 격자가 그리는 선들의 교차점에 스냅되고, 그렇지 않으면 그 사이의 더 촘촘한 격자에 스냅됩니다. 끄기: 이전과 같이 점은 촘촘한 격자에만 스냅됩니다."
|
||||
},
|
||||
"vi": {
|
||||
"prefs.sketch.snap_to_visible_grid": "Bắt vào giao điểm nhìn thấy của lưới",
|
||||
"prefs.sketch_snap_to_visible_grid_note": "Một điểm trong phác thảo bắt vào giao điểm của các đường mà lưới vẽ khi con trỏ chỉ vào một giao điểm, và vào lưới mịn hơn giữa chúng trong trường hợp khác. Tắt: điểm chỉ bắt vào lưới mịn hơn, như trước."
|
||||
},
|
||||
"zh": {
|
||||
"prefs.sketch.snap_to_visible_grid": "捕捉网格可见的交点",
|
||||
"prefs.sketch_snap_to_visible_grid_note": "当指针指向网格绘制的线的交点时,草图中的点捕捉到该交点,否则捕捉到交点之间更细的网格。关闭:点只捕捉到更细的网格,与之前相同。"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
{
|
||||
"uk": {
|
||||
"prefs.render_legacy_memory_admission": "Використовувати попередні перевірки пам'яті рендерингу",
|
||||
"prefs.render_legacy_memory_admission_help": "Дозволяє нативний рендеринг у межах фіксованих бюджетів спільної пам'яті та пам'яті хоста, навіть коли оцінка перевищує доступну RAM. Обмеження пристрою й перевірки виділення пам'яті все одно діють.",
|
||||
"render.caustics_area_lights": "Каустика площинних джерел світла",
|
||||
"render.caustics_environment": "Каустика середовища",
|
||||
"render.cpu_threads": "Робочі потоки CPU",
|
||||
"render.cpu_threads_auto": "Авто",
|
||||
"render.cpu_threads_custom": "Власна",
|
||||
"render.cpu_threads_help": "«Авто» використовує доступні робочі потоки CPU. Один потік працює послідовно. Більше потоків може потребувати більше пам'яті.",
|
||||
"render.cpu_threads_single": "Один",
|
||||
"render.cpu_threads_web": "Рендеринг у браузері використовує один кооперативний робочий потік. Вибір робочих потоків, збережений для настільного застосунку, не змінюється.",
|
||||
"render.denoise_class_background": "Пропущено: фон",
|
||||
"render.denoise_class_coverage": "Пропущено: часткове покриття",
|
||||
"render.denoise_class_degenerate": "Пропущено: вироджений шлях",
|
||||
"render.denoise_class_depth": "Пропущено: ліміт глибини шляху",
|
||||
"render.denoise_class_emitter": "Пропущено: джерело світла",
|
||||
"render.denoise_class_exit": "Пропущено: несумісний вихід",
|
||||
"render.denoise_class_identity": "Пропущено: ліміт ідентичності напрямних даних",
|
||||
"render.denoise_class_lens": "Пропущено: глибина різкості",
|
||||
"render.denoise_class_material": "Пропущено: непідтримуваний матеріал",
|
||||
"render.denoise_class_nested": "Пропущено: вкладене середовище",
|
||||
"render.denoise_class_optical": "Придатне: заломлена поверхня",
|
||||
"render.denoise_class_reflection": "Пропущено: відбивна кінцева точка",
|
||||
"render.denoise_class_surface": "Придатне: поверхня",
|
||||
"render.denoise_class_tir": "Пропущено: повне внутрішнє відбиття",
|
||||
"render.denoise_class_transmission": "Пропущено: подальше пропускання",
|
||||
"render.denoise_class_unavailable": "Пропущено: немає напрямних даних",
|
||||
"render.denoise_class_volume": "Пропущено: об'ємне розсіювання",
|
||||
"render.denoise_diagnostics_counts": "Придатні: {eligible} · Пропущені: {skipped}",
|
||||
"render.denoise_diagnostics_enable": "Збирати діагностику шумозаглушення",
|
||||
"render.denoise_diagnostics_grid": "Кількість пікселів у внутрішньому розмірі {width} × {height}.",
|
||||
"render.denoise_diagnostics_help": "Збирає кількість придатних і пропущених пікселів, навіть коли шумозаглушення вимкнено. Лічба використовує внутрішній розмір рендерингу, а маска — вихідний розмір.",
|
||||
"render.denoise_diagnostics_title": "Діагностика шумозаглушення",
|
||||
"render.denoise_export_mask": "Експортувати маску PNG",
|
||||
"render.denoise_firefly": "Пригнічувати ізольовані яскраві пікселі",
|
||||
"render.denoise_format_mask": "Маска PNG",
|
||||
"render.denoise_mask_copy_help": "Експортуйте маску шумозаглушення як PNG або поверніться до відрендереного зображення, щоб скопіювати його.",
|
||||
"render.denoise_mask_unavailable": "Увімкніть діагностику шумозаглушення й відрендерте зображення, щоб оглянути його маску.",
|
||||
"render.denoise_optical_filter": "Фільтрувати дзеркала й скло",
|
||||
"render.denoise_optical_filter_help": "Фільтрувати придатне відбите й пропущене світло. Вимкніть, щоб шумозаглушувати лише непрозорі поверхні.",
|
||||
"render.denoise_passes": "Проходи фільтрації",
|
||||
"render.denoise_settings_help": "Більше проходів згладжує ширшу область. Сила визначає, скільки фільтрації застосовує кожен прохід. Непідтримувані оптичні шляхи залишаються нефільтрованими.",
|
||||
"render.denoise_strength": "Сила шумозаглушення",
|
||||
"render.denoise_view_image": "Відрендерене зображення",
|
||||
"render.denoise_view_mask": "Маска шумозаглушення",
|
||||
"render.metal_energy_compensation": "Відновлювати відбивну здатність шорсткого металу",
|
||||
"render.metal_energy_compensation_help": "Компенсує втрати світла між мікрогранями шорсткого металу. Рендеринг на CPU потребує непрямого освітлення.",
|
||||
"render.quality_legacy_samples": "Збережене значення: {samples} вибірок на піксель. Нові значення обмежено {maximum} вибірками на піксель.",
|
||||
"render.quality_preset_limit": "Цей пресет перевищує ліміт вибору 16384 вибірок на піксель. Виберіть кількість вибірок до 16384.",
|
||||
"render.size_8k_uhd": "8K UHD",
|
||||
"render.supersampling": "Наддискретизація",
|
||||
"render.supersampling_dimensions": "Рендерить {width} × {height} і зменшує до {output_width} × {output_height}. Використовує вчетверо більше пікселів.",
|
||||
"render.supersampling_help": "Рендерить із подвійною шириною та висотою, потім зменшує в лінійному світлі. Вихідний розмір не змінюється.",
|
||||
"render.supersampling_off": "Вимкнено",
|
||||
"render.supersampling_x2": "2×",
|
||||
"render.texture_filtering": "Фільтрувати деталі текстури",
|
||||
"render.texture_filtering_help": "Використовує mip-рівні й анізотропну фільтрацію, щоб зменшити аліасинг текстури під час мінімізації. Потребує більше пам'яті; вимкнено зберігає попередню фільтрацію.",
|
||||
"ui.construction.axis_hint": "Допоміжна пряма: клацніть точку або введіть її відстань від осі ескізу",
|
||||
"ui.construction.parallel_hint": "Допоміжна пряма: виберіть пряму, потім клацніть або введіть зсув; клацніть правою кнопкою, щоб змінити опорний об'єкт"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"en": {
|
||||
"ui.view_compass_tip": "View from {axis}. Click again to reverse. Drag to orbit.",
|
||||
"ui.view_compass_tip_snap": "View from {axis}. Click again to reverse. Drag to orbit; hold Shift to snap."
|
||||
},
|
||||
"ar": {
|
||||
"ui.view_compass_tip": "العرض من {axis}. انقر مرة أخرى للعكس. اسحب لتدوير العرض.",
|
||||
"ui.view_compass_tip_snap": "العرض من {axis}. انقر مرة أخرى للعكس. اسحب لتدوير العرض؛ اضغط مطولًا على Shift للالتقاط."
|
||||
},
|
||||
"de": {
|
||||
"ui.view_compass_tip": "Ansicht von {axis}. Erneut klicken zum Umkehren. Ziehen zum Drehen.",
|
||||
"ui.view_compass_tip_snap": "Ansicht von {axis}. Erneut klicken zum Umkehren. Ziehen zum Drehen; Umschalttaste halten zum Einrasten."
|
||||
},
|
||||
"he": {
|
||||
"ui.view_compass_tip": "מבט מ־{axis}. לחיצה נוספת הופכת את הכיוון. גרירה מסובבת את המבט.",
|
||||
"ui.view_compass_tip_snap": "מבט מ־{axis}. לחיצה נוספת הופכת את הכיוון. גרירה מסובבת את המבט; יש להחזיק את Shift כדי להצמיד."
|
||||
},
|
||||
"ja": {
|
||||
"ui.view_compass_tip": "{axis}方向から表示します。もう一度クリックすると反転します。ドラッグでオービットします。",
|
||||
"ui.view_compass_tip_snap": "{axis}方向から表示します。もう一度クリックすると反転します。ドラッグでオービットし、Shiftを押すとスナップします。"
|
||||
},
|
||||
"ko": {
|
||||
"ui.view_compass_tip": "{axis} 방향에서 봅니다. 다시 클릭하면 반대 방향으로 바뀝니다. 드래그하여 회전합니다.",
|
||||
"ui.view_compass_tip_snap": "{axis} 방향에서 봅니다. 다시 클릭하면 반대 방향으로 바뀝니다. 드래그하여 회전하고, Shift를 누르면 스냅됩니다."
|
||||
},
|
||||
"vi": {
|
||||
"ui.view_compass_tip": "Nhìn từ {axis}. Bấm lần nữa để đảo ngược. Kéo để xoay góc nhìn.",
|
||||
"ui.view_compass_tip_snap": "Nhìn từ {axis}. Bấm lần nữa để đảo ngược. Kéo để xoay góc nhìn; giữ Shift để bắt dính."
|
||||
},
|
||||
"zh": {
|
||||
"ui.view_compass_tip": "从 {axis} 方向查看。再次单击可反向。拖动可环绕。",
|
||||
"ui.view_compass_tip_snap": "从 {axis} 方向查看。再次单击可反向。拖动可环绕;按住 Shift 可吸附。"
|
||||
}
|
||||
}
|
||||
+289
-289
File diff suppressed because it is too large
Load Diff
@@ -265,6 +265,7 @@
|
||||
"Edge": "Aresta",
|
||||
"Edges": "Arestas",
|
||||
"Edit": "Editar",
|
||||
"Edit Holes": "Editar furos",
|
||||
"Edit Profile Sketch": "Editar esboço do perfil",
|
||||
"Edit shortcuts": "Editar atalhos",
|
||||
"Enable rule": "Ativar regra",
|
||||
@@ -976,6 +977,7 @@
|
||||
"browser.calibrate_click_a": "Clique na imagem para o ponto A ou digite suas coordenadas.",
|
||||
"browser.calibrate_click_b": "Clique na imagem para o ponto B ou digite suas coordenadas.",
|
||||
"browser.calibrate_title": "Calibrar: {name}",
|
||||
"browser.canvas_locked": "A tela está bloqueada. Desbloqueie-a primeiro.",
|
||||
"browser.capture_many": "{count} componentes foram movidos, mas suas posições não foram capturadas.",
|
||||
"browser.capture_note": "Capturar posição mantém a nova posição; Reverter posição restaura a anterior.",
|
||||
"browser.capture_one": "Um componente foi movido, mas sua posição não foi capturada.",
|
||||
@@ -1205,6 +1207,7 @@
|
||||
"cmd.material_properties_directional": "Módulo de elasticidade direcional",
|
||||
"cmd.material_properties_validate": "Validar dados do material físico",
|
||||
"cmd.mesh_convert": "Converter malha",
|
||||
"cmd.model_body_features": "Listar características do corpo",
|
||||
"cmd.model_edges": "Listar arestas",
|
||||
"cmd.model_faces": "Listar faces",
|
||||
"cmd.model_threads": "Listar roscas",
|
||||
@@ -1233,8 +1236,11 @@
|
||||
"cmd.panel.dismiss": "Dispensar prévia do painel",
|
||||
"cmd.panel.float": "Desacoplar painel",
|
||||
"cmd.panel.focus": "Focar painel",
|
||||
"cmd.panel.focus.next": "Focar no próximo painel",
|
||||
"cmd.panel.focus.previous": "Focar no painel anterior",
|
||||
"cmd.panel.list": "Listar painéis",
|
||||
"cmd.panel.move": "Mover painel",
|
||||
"cmd.panel.move.next_zone": "Mover painel para a próxima zona",
|
||||
"cmd.panel.native_close": "Reacoplar seção de painel nativo",
|
||||
"cmd.panel.open": "Abrir painel",
|
||||
"cmd.panel.peek": "Espiar painel recolhido",
|
||||
@@ -1242,6 +1248,12 @@
|
||||
"cmd.panel.reset_pair": "Redefinir divisor do painel",
|
||||
"cmd.panel.resize": "Redimensionar seção do painel",
|
||||
"cmd.panel.resize_pair": "Redimensionar divisor do painel",
|
||||
"cmd.panel.sash.down": "Redimensionar divisor do painel para baixo",
|
||||
"cmd.panel.sash.left": "Redimensionar divisor do painel para a esquerda",
|
||||
"cmd.panel.sash.reset": "Redefinir divisor do painel focado",
|
||||
"cmd.panel.sash.right": "Redimensionar divisor do painel para a direita",
|
||||
"cmd.panel.sash.up": "Redimensionar divisor do painel para cima",
|
||||
"cmd.panel.toggle": "Alternar o painel focado",
|
||||
"cmd.parameters_add": "Adicionar parâmetro do usuário",
|
||||
"cmd.parameters_change": "Alterar parâmetros",
|
||||
"cmd.parameters_comment": "Comentar parâmetro",
|
||||
@@ -1365,6 +1377,7 @@
|
||||
"cmd.sketch.construction_line.tangent_external": "Tangente por um ponto externo",
|
||||
"cmd.sketch.construction_line.tangent_two": "Tangente comum",
|
||||
"cmd.sketch.construction_line.vertical": "Reta de construção vertical",
|
||||
"cmd.sketch.replace": "Substituir esboço",
|
||||
"cmd.sketch_arc3d": "Arco 3D",
|
||||
"cmd.sketch_arc_center_point": "Arco por ponto central",
|
||||
"cmd.sketch_arc_tangent": "Arco tangente",
|
||||
@@ -1496,6 +1509,7 @@
|
||||
"cmd.timeline_stop": "Parar histórico",
|
||||
"cmd.timeline_suppress": "Suprimir recurso",
|
||||
"cmd.ui.assistant": "Alternar assistente",
|
||||
"cmd.ui.palette": "Pesquisar comandos",
|
||||
"cmd.view.navigator": "Navegador de vistas personalizadas",
|
||||
"cmd.view.render_browser": "Navegador de renderização",
|
||||
"cmd.view.render_dock": "Mover dock de renderização",
|
||||
@@ -2015,6 +2029,7 @@
|
||||
"help.view.visual_style": "Muda como o modelo é desenhado: sombreado com ou sem arestas, aramado ou com arestas ocultas. Use aramado para ver o interior e sombreado para uma aparência limpa.",
|
||||
"history.sketch_under_constrained": "Subrestrito ({count} graus de liberdade)",
|
||||
"history.sketch_under_constrained_one": "Subrestrito ({count} grau de liberdade)",
|
||||
"hole_folder.applies_to": "As alterações se aplicam aos {count} furos em {folder}; cada um mantém seu lugar.",
|
||||
"hole_presets.confirm_delete": "Confirmar exclusão",
|
||||
"hole_presets.delete": "Excluir",
|
||||
"hole_presets.delete_prompt": "Excluir esta predefinição pessoal? Os furos existentes não mudam.",
|
||||
@@ -2417,6 +2432,7 @@
|
||||
"parts.dimension.width": "Largura",
|
||||
"parts.family.bearing": "Rolamento rígido de esferas (envoltória)",
|
||||
"parts.family.button_head_cap_screw": "Parafuso de cabeça abaulada com sextavado interno",
|
||||
"parts.family.countersunk_socket_screw": "Parafuso de cabeça cônica com sextavado interno",
|
||||
"parts.family.dowel_pin": "Pino paralelo (cavilha)",
|
||||
"parts.family.hex_bolt": "Parafuso de cabeça sextavada",
|
||||
"parts.family.hex_cap_screw_inch": "Parafuso de cabeça sextavada (polegada)",
|
||||
@@ -2515,6 +2531,8 @@
|
||||
"prefs.bottom_centre": "Inferior central",
|
||||
"prefs.bottom_right": "Inferior direito",
|
||||
"prefs.browser": "Navegador",
|
||||
"prefs.browser_body_features": "Características sob os corpos",
|
||||
"prefs.browser_body_features_note": "Cada corpo no navegador expande para mostrar as características da linha do tempo que o construíram, na ordem da linha do tempo.",
|
||||
"prefs.browser_components_open": "Componentes começam abertos",
|
||||
"prefs.browser_components_open_note": "Cada componente no navegador começa aberto, como antes, em vez de fechado até que você o abra.",
|
||||
"prefs.browser_eye_left": "Olho ao lado da seta de recolher",
|
||||
@@ -2555,7 +2573,11 @@
|
||||
"prefs.design_tools.degrees": "Graus",
|
||||
"prefs.design_tools.double_click_help": "Ou para editar um vinculado no local.",
|
||||
"prefs.design_tools.ghost": "Mostrar o lugar antigo das peças movidas como fantasma",
|
||||
"prefs.design_tools.hole_group": "Agrupar furos feitos juntos",
|
||||
"prefs.design_tools.hole_group_help": "Furos feitos de uma vez compartilham uma pasta no Histórico, fechada inicialmente; abra-a para editar um furo separadamente.",
|
||||
"prefs.design_tools.hole_moves_help": "Escolher a face novamente move o furo em vez de removê-lo.",
|
||||
"prefs.design_tools.hole_several": "Vários furos em uma face",
|
||||
"prefs.design_tools.hole_several_help": "Clicar em outro lugar na face adiciona outro furo; clicar em um furo o remove.",
|
||||
"prefs.design_tools.hole_snaps_help": "O meio de uma face e os centros de suas arestas circulares.",
|
||||
"prefs.design_tools.imported_files": "Arquivos importados",
|
||||
"prefs.design_tools.note": "Observação",
|
||||
@@ -2637,6 +2659,8 @@
|
||||
"prefs.history": "Histórico",
|
||||
"prefs.history_bar_groups": "Agrupar a barra de histórico em grupos",
|
||||
"prefs.history_bar_groups_note": "Em um histórico longo, uma sequência de recursos de um componente se agrupa em um único indicador, e as pastas de recursos começam recolhidas. Uma montagem STEP inserida vai para uma pasta Grupo. Desativado mostra cada recurso, começa com as pastas abertas e não cria pasta.",
|
||||
"prefs.history_folder_kind_icon": "Ícone da pasta baseado em suas características",
|
||||
"prefs.history_folder_kind_icon_note": "Uma pasta do Histórico cujas características são todas do mesmo tipo mostra o ícone delas.",
|
||||
"prefs.history_group_joints": "Agrupar juntas no Histórico",
|
||||
"prefs.history_group_joints_note": "Duas ou mais juntas aparecem como um único botão com sua contagem, e um clique mostra cada uma. Desativado mostra cada junta.",
|
||||
"prefs.history_origin_bodies": "Mostrar origem e corpos no topo",
|
||||
@@ -2742,6 +2766,7 @@
|
||||
"prefs.origin_plane_names": "Nomes dos planos da origem",
|
||||
"prefs.origin_plane_names_note": "Nomes mostrados no navegador, nas caixas de diálogo e nas listas. {top} é XY, {front} é XZ e {right} é YZ, com Z para cima. Comandos, scripts e projetos salvos mantêm XY, XZ e YZ.",
|
||||
"prefs.overall_speed": "Velocidade geral",
|
||||
"prefs.panel_layout.recovery": "Não foi possível restaurar os layouts de painéis salvos. Os dados salvos são mantidos; o estilo Clássico permanece disponível.",
|
||||
"prefs.parameter_list_rows": "Linhas da lista de parâmetros",
|
||||
"prefs.parameter_list_rows_tip": "O máximo de parâmetros que a seta para baixo lista em uma caixa de expressão vazia.",
|
||||
"prefs.persistent_ribbon_pressed": "Destacar comandos ativos da faixa de opções",
|
||||
@@ -2803,6 +2828,8 @@
|
||||
"prefs.remember_dialog_values.help": "Desativado por padrão. Quando ativado, depois que um comando dá certo, seus valores e opções seguros são reutilizados na próxima vez que você abrir o mesmo comando, até o SolidCraft fechar.",
|
||||
"prefs.render_legacy_image_defaults": "Usar os padrões anteriores da imagem de Renderizar",
|
||||
"prefs.render_legacy_image_defaults_help": "Manter o fluxo manual anterior: novas configurações usam rasterização em CPU, o ray tracing em CPU mantém amostragem fixa e você abre os resultados renderizados manualmente. Reenquadrar ao entrar em Renderizar, trocar de tomada sem restaurar as câmeras e usar o enquadramento e a navegação anteriores. Desativar o retorno automático da imagem ao vivo. As configurações salvas não mudam.",
|
||||
"prefs.render_legacy_memory_admission": "Usar verificações de memória de renderizações anteriores",
|
||||
"prefs.render_legacy_memory_admission_help": "Permitir renderizações nativas dentro dos orçamentos fixos de memória compartilhada e do host mesmo quando a estimativa excede a RAM disponível. Limites do dispositivo e verificações de alocação ainda se aplicam.",
|
||||
"prefs.render_previous_geometry_budget": "Usar o orçamento de geometria anterior da prévia de Renderizar",
|
||||
"prefs.render_previous_geometry_budget_help": "Restaurar o limite fixo de geometria anterior (512 MiB em desktop de 64 bits, 128 MiB nos demais) em vez do orçamento baseado no dispositivo.",
|
||||
"prefs.reports_saved": "{n} salvos",
|
||||
@@ -2829,6 +2856,8 @@
|
||||
"prefs.select_other_hidden": "Selecionar geometria oculta com Selecionar outro",
|
||||
"prefs.select_other_hidden_help": "Ativado: incluir corpos ocultos, esboços e arestas encobertas perto do ponteiro. Desativado: usar a lista original de geometria visível sob o ponteiro.",
|
||||
"prefs.selecting": "Seleção",
|
||||
"prefs.shared_panel_layout": "Usar layout de painel compartilhado",
|
||||
"prefs.shared_panel_layout_help": "Mostrar o Navegador, Histórico e Assistente existentes em painéis móveis. A alteração tem efeito quando as preferências são aplicadas.",
|
||||
"prefs.shift": "Shift",
|
||||
"prefs.shift_add_ctrl_toggle": "Shift só adiciona; Ctrl / Cmd alterna",
|
||||
"prefs.shift_add_note": "Ativado: Shift adiciona, Ctrl / Cmd alterna. Desativado (padrão): ambos alternam.",
|
||||
@@ -2851,6 +2880,8 @@
|
||||
"prefs.sketch.drawing": "Desenho",
|
||||
"prefs.sketch.ellipse_axes": "Desenhar elipses com seus eixos",
|
||||
"prefs.sketch.ellipse_axes_note": "Os eixos maior e menor como linhas de construção, para que os semieixos e eixos possam ser cotados. Desativado: apenas a elipse, e D nela dá o raio menor onde quer que o valor seja puxado, desenhado e rotulado R como antes.",
|
||||
"prefs.sketch.escape_twice_finishes": "Duplo Esc finaliza o esboço",
|
||||
"prefs.sketch.escape_twice_finishes_note": "Dois toques rápidos no Esc encerram o esboço. Desligado: Esc apenas cancela a ferramenta ou a seleção, e Finalizar Esboço encerra o esboço.",
|
||||
"prefs.sketch.exit_keep": "Manter",
|
||||
"prefs.sketch.exit_previous": "Voltar à vista anterior",
|
||||
"prefs.sketch.exit_unless_rotated": "A menos que girada",
|
||||
@@ -3193,8 +3224,10 @@
|
||||
"render.category_paint": "Tinta",
|
||||
"render.category_plastic": "Plástico",
|
||||
"render.category_wood": "Madeira",
|
||||
"render.caustics_area_lights": "Cáusticas de luzes de área",
|
||||
"render.caustics_depth": "Profundidade de caminho das cáusticas",
|
||||
"render.caustics_enable": "Cáusticas de vidro a partir de luzes pontuais e direcionais",
|
||||
"render.caustics_environment": "Cáusticas do ambiente",
|
||||
"render.caustics_help": "A contagem de fótons controla o ruído e o trabalho. O raio de coleta troca detalhe nítido por uma estimativa mais suave. A CPU exige Iluminação indireta.",
|
||||
"render.caustics_path_required": "As cáusticas em CPU exigem Iluminação indireta.",
|
||||
"render.caustics_photons": "Fótons",
|
||||
@@ -3411,6 +3444,12 @@
|
||||
"render.cpu_subsurface_denoise_reason": "O espalhamento subsuperficial em CPU precisa de Redução de ruído desativada. Suas configurações são mantidas.",
|
||||
"render.cpu_subsurface_help": "O espalhamento redireciona a luz dentro do Vidro fechado. Taxas positivas precisam de Iluminação indireta com Redução de ruído desativada. A taxa é de colisões por mm; 0 não adiciona espalhamento. Um viés de fase positivo favorece direções para a frente; negativo favorece para trás.",
|
||||
"render.cpu_summary": "Ray tracing em CPU · reflexos · HDR · luzes direcionais e pontuais",
|
||||
"render.cpu_threads": "CPU workers",
|
||||
"render.cpu_threads_auto": "Automático",
|
||||
"render.cpu_threads_custom": "Personalizado",
|
||||
"render.cpu_threads_help": "Automático usa CPU workers disponíveis. Um worker roda em série. Mais workers podem precisar de mais memória.",
|
||||
"render.cpu_threads_single": "Único",
|
||||
"render.cpu_threads_web": "Renderização no navegador usa um cooperative worker. A escolha de worker do desktop salva é preservada.",
|
||||
"render.cpu_transparent_help": "PNG transparente remove o fundo e mantém a cobertura das bordas. A opacidade de corpos e faces deve ficar em 100%.",
|
||||
"render.cpu_volume_enable_path": "Ativar Iluminação indireta",
|
||||
"render.cpu_volume_enable_path_plan": "Ray tracing em CPU · profundidade de caminho {depth} · {spp} amostras/pixel · semente {seed} · sombras traçadas. Mantém a atmosfera criada e o orçamento da imagem.",
|
||||
@@ -3419,6 +3458,40 @@
|
||||
"render.cpu_volume_method_incompatible": "Estas configurações de luz, amostragem ou atmosfera não podem ser transferidas para este método. Suas configurações são mantidas.",
|
||||
"render.cpu_volume_path_required": "Ative Iluminação indireta para usar a Atmosfera em CPU.",
|
||||
"render.cpu_warm_cool": "Quente e frio",
|
||||
"render.denoise_class_background": "Ignorado: fundo",
|
||||
"render.denoise_class_coverage": "Ignorado: cobertura parcial",
|
||||
"render.denoise_class_degenerate": "Ignorado: caminho degenerado",
|
||||
"render.denoise_class_depth": "Ignorado: limite de profundidade do caminho",
|
||||
"render.denoise_class_emitter": "Ignorado: emissor de luz",
|
||||
"render.denoise_class_exit": "Ignorado: saída incompatível",
|
||||
"render.denoise_class_identity": "Ignorado: limite de identidade do guia",
|
||||
"render.denoise_class_lens": "Ignorado: profundidade de campo",
|
||||
"render.denoise_class_material": "Ignorado: material não suportado",
|
||||
"render.denoise_class_nested": "Ignorado: meio aninhado",
|
||||
"render.denoise_class_optical": "Elegível: superfície refratada",
|
||||
"render.denoise_class_reflection": "Ignorado: ponto final reflexivo",
|
||||
"render.denoise_class_surface": "Elegível: superfície",
|
||||
"render.denoise_class_tir": "Ignorado: reflexão total interna",
|
||||
"render.denoise_class_transmission": "Ignorado: transmissão adicional",
|
||||
"render.denoise_class_unavailable": "Ignorado: sem guia",
|
||||
"render.denoise_class_volume": "Ignorado: espalhamento de volume",
|
||||
"render.denoise_diagnostics_counts": "Elegíveis: {eligible} · Ignorados: {skipped}",
|
||||
"render.denoise_diagnostics_enable": "Coletar diagnósticos de redução de ruído",
|
||||
"render.denoise_diagnostics_grid": "Contagens de pixels no tamanho interno {width} × {height}.",
|
||||
"render.denoise_diagnostics_help": "Coleta contagens de pixels elegíveis e ignorados mesmo quando a redução de ruído está desligada. As contagens usam o tamanho de renderização interno; a máscara usa o tamanho de saída.",
|
||||
"render.denoise_diagnostics_title": "Diagnósticos de redução de ruído",
|
||||
"render.denoise_export_mask": "Exportar máscara PNG",
|
||||
"render.denoise_firefly": "Suprimir pixels brilhantes isolados",
|
||||
"render.denoise_format_mask": "Máscara PNG",
|
||||
"render.denoise_mask_copy_help": "Exportar a máscara de redução de ruído como PNG, ou voltar à imagem renderizada para copiá-la.",
|
||||
"render.denoise_mask_unavailable": "Ative diagnósticos de redução de ruído e renderize uma imagem para inspecionar sua máscara.",
|
||||
"render.denoise_optical_filter": "Filtrar espelho e vidro",
|
||||
"render.denoise_optical_filter_help": "Filtrar luz refletida e transmitida elegível. Desligue para redução de ruído apenas em superfícies opacas.",
|
||||
"render.denoise_passes": "Passagens de filtro",
|
||||
"render.denoise_settings_help": "Mais passagens suavizam uma área maior. A intensidade controla quanto cada passagem aplica de filtro. Caminhos ópticos não suportados permanecem sem filtro.",
|
||||
"render.denoise_strength": "Intensidade da redução de ruído",
|
||||
"render.denoise_view_image": "Imagem renderizada",
|
||||
"render.denoise_view_mask": "Máscara de redução de ruído",
|
||||
"render.diag_bodies": "Corpos visíveis",
|
||||
"render.diag_job_details": "Detalhes do trabalho capturado",
|
||||
"render.diag_last_check": "Última pré-verificação",
|
||||
@@ -3624,6 +3697,7 @@
|
||||
"render.glass_model_help": "A rugosidade do vidro espalha os raios transmitidos. A dispersão e a cor da película usam três bandas de comprimento de onda. Chapas ásperas exigem sombras transmitidas retas desativadas.",
|
||||
"render.glass_roughness": "Rugosidade do vidro",
|
||||
"render.gpu_depth": "Profundidade máxima de caminho",
|
||||
"render.gpu_job_shader_wait": "Configuração do shader pode levar minutos",
|
||||
"render.gpu_options_help": "Amostras, profundidade, semente e exposição são salvas com esta configuração. Apenas o método de imagem ativo é salvo.",
|
||||
"render.gpu_path_crashed": "O SolidCraft fechou durante a configuração neste adaptador gráfico da última vez, muito provavelmente dentro do driver gráfico, então ele não é configurado de novo sozinho. Escolha ray tracing em CPU ou tente novamente (uma atualização do driver também tenta de novo).",
|
||||
"render.gpu_path_failed": "Path tracer em GPU indisponível",
|
||||
@@ -3972,6 +4046,8 @@
|
||||
"render.material_transient": "Substituições ópticas temporárias para esta aba de documento. Elas não são salvas no projeto, na configuração de renderização nem na biblioteca de materiais.",
|
||||
"render.material_v_up": "O V da textura aponta para cima na imagem",
|
||||
"render.material_weight": "Peso do verniz (0–1)",
|
||||
"render.metal_energy_compensation": "Recuperar reflectância de metal rugoso",
|
||||
"render.metal_energy_compensation_help": "Compensar luz perdida entre microfaceta de metal rugoso. Renderização CPU precisa de Iluminação indireta.",
|
||||
"render.method_cpu": "Ray tracing em CPU",
|
||||
"render.method_gpu": "Path tracing em GPU",
|
||||
"render.method_limit_raster": "A rasterização usa a prévia de estúdio opaca fixa. Selecione um método de ray tracing explícito para os controles ópticos suportados.",
|
||||
@@ -4100,6 +4176,8 @@
|
||||
"render.quality_denoise_on": "Redução de ruído: Ativada",
|
||||
"render.quality_draft": "Rascunho",
|
||||
"render.quality_high": "Alta",
|
||||
"render.quality_legacy_samples": "Valor salvo: {samples} spp. Novas seleções são limitadas a {maximum} spp.",
|
||||
"render.quality_preset_limit": "Esta predefinição excede o limite de seleção de 16384 spp. Escolha uma contagem de amostras até 16384.",
|
||||
"render.quality_projection_help": "Esta revisão altera apenas resolução, orçamento de amostras, profundidade de caminho, semente e redução de ruído. As outras configurações são mantidas; o orçamento não certifica a convergência.",
|
||||
"render.quality_review": "Revisar orçamento de amostragem",
|
||||
"render.quality_summary": "{width} × {height} · {samples} amostras · profundidade {depth} · semente {seed} · {denoise}",
|
||||
@@ -4247,6 +4325,7 @@
|
||||
"render.show_shots_label": "Mostrar faixa de tomadas",
|
||||
"render.size_4k": "4K",
|
||||
"render.size_4k_uhd": "4K UHD",
|
||||
"render.size_8k_uhd": "8K UHD",
|
||||
"render.size_custom": "Personalizado…",
|
||||
"render.size_full_hd": "Full HD",
|
||||
"render.size_hd": "HD",
|
||||
@@ -4409,6 +4488,11 @@
|
||||
"render.subsurface_enable": "Passeio aleatório de espalhamento interior",
|
||||
"render.subsurface_help": "Apenas dielétrico fechado. O espalhamento e a absorção RGB são coeficientes separados por mm. Os caminhos se espalham dentro da geometria real e depois refratam ou refletem no contorno. Desative a transmissão de sombra reta, a redução de ruído de superfície e o volume exterior; use um estrato de Fresnel. Não é um shader de difusão, uma grade de densidade nem um material medido. Meios densos podem precisar de mais amostras e profundidade de caminho.",
|
||||
"render.subsurface_rate": "Taxa de colisão de espalhamento",
|
||||
"render.supersampling": "Superamostragem",
|
||||
"render.supersampling_dimensions": "Renderiza {width} × {height} e reduz para {output_width} × {output_height}. Usa quatro vezes os pixels.",
|
||||
"render.supersampling_help": "Renderiza com o dobro da largura e altura, depois reduz em luz linear. O tamanho de saída permanece inalterado.",
|
||||
"render.supersampling_off": "Desligado",
|
||||
"render.supersampling_x2": "2×",
|
||||
"render.surface_import.author": "Autor",
|
||||
"render.surface_import.busy": "Importando imagem…",
|
||||
"render.surface_import.complete": "Escolha uma imagem e informe seu autor, fonte e licença.",
|
||||
@@ -4422,6 +4506,8 @@
|
||||
"render.surface_import.saved_cpu": "Salve os mapas para usá-los com a renderização em CPU.",
|
||||
"render.surface_import.source": "Fonte",
|
||||
"render.surface_import.title": "Importar imagem",
|
||||
"render.texture_filtering": "Filtrar detalhes de textura",
|
||||
"render.texture_filtering_help": "Usa níveis mip e filtragem anisotrópica para reduzir aliasing de textura sob minificação. Usa mais memória; desligado mantém a filtragem anterior.",
|
||||
"render.tone_aces_fitted": "ACES ajustado",
|
||||
"render.tone_reinhard": "Reinhard",
|
||||
"render.transmission_scope": "O vidro em GPU suporta meios disjuntos certificados. Meios aninhados irrestritos e um estimador de transmissão sem ruído não são fornecidos.",
|
||||
@@ -5516,6 +5602,7 @@
|
||||
"ui.heading_plastic": "PLÁSTICO",
|
||||
"ui.heading_position": "POSIÇÃO",
|
||||
"ui.heading_prepare": "PREPARAR",
|
||||
"ui.heading_press_pull": "Puxar / Empurrar",
|
||||
"ui.heading_rectangular_pattern": "PADRÃO RETANGULAR",
|
||||
"ui.heading_revolve": "REVOLUÇÃO",
|
||||
"ui.heading_right": "DIREITA",
|
||||
@@ -5758,6 +5845,42 @@
|
||||
"ui.panel_host.surface": "Painel",
|
||||
"ui.panel_host.tab": "Aba do painel",
|
||||
"ui.panel_host.tabs": "Todas as abas",
|
||||
"ui.panel_layout.applied": "Aplicado {name} a {workspace}",
|
||||
"ui.panel_layout.cancel": "Cancelar",
|
||||
"ui.panel_layout.confirm_replace": "Substituir \"{name}\"?",
|
||||
"ui.panel_layout.copy": "Copiar",
|
||||
"ui.panel_layout.current": "Layout atual",
|
||||
"ui.panel_layout.custom": "Personalizado",
|
||||
"ui.panel_layout.custom_hint": "Painéis foram movidos desde {name}.",
|
||||
"ui.panel_layout.details": "Detalhes",
|
||||
"ui.panel_layout.layout_workspace": "Layout do espaço de trabalho",
|
||||
"ui.panel_layout.page_defaults_hint": "Redefine as configurações desta página. Arranjos de painéis e layouts salvos são mantidos.",
|
||||
"ui.panel_layout.panel_layout": "Layout de painéis",
|
||||
"ui.panel_layout.panel_style": "Estilo do painel",
|
||||
"ui.panel_layout.replace": "Substituir layout",
|
||||
"ui.panel_layout.replace_current": "Substituir pelo atual",
|
||||
"ui.panel_layout.replace_short": "Substituir",
|
||||
"ui.panel_layout.reset": "Redefinir espaço de trabalho",
|
||||
"ui.panel_layout.reset_hint": "Redefinir {workspace} para seu arranjo padrão. Layouts salvos são mantidos.",
|
||||
"ui.panel_layout.reset_short": "Redefinir",
|
||||
"ui.panel_layout.restore_failed": "Não foi possível restaurar seu layout",
|
||||
"ui.panel_layout.save": "Salvar layout",
|
||||
"ui.panel_layout.save_as": "Salvar como",
|
||||
"ui.panel_layout.save_as_tile": "Salvar como…",
|
||||
"ui.panel_layout.selected": "selecionado",
|
||||
"ui.panel_layout.suggested_name": "Layout {n}",
|
||||
"ui.panel_layout.try_again": "Tentar novamente",
|
||||
"ui.panel_layout.validation.builtin": "Layouts integrados não podem ser alterados",
|
||||
"ui.panel_layout.validation.duplicate": "Você já tem este nome",
|
||||
"ui.panel_layout.validation.empty": "Insira um nome",
|
||||
"ui.panel_layout.validation.full": "64 de 64 salvos. Escolha um para substituir.",
|
||||
"ui.panel_layout.validation.invalid": "Use 1–64 caracteres, sem caracteres de controle",
|
||||
"ui.panel_layout.workspace.classic": "Clássico",
|
||||
"ui.panel_layout.workspace.modelling": "Modelagem",
|
||||
"ui.panel_layout.workspace.render": "Renderização",
|
||||
"ui.panel_layout.workspace.review": "Revisão",
|
||||
"ui.panel_layout.workspace.sketch": "Esboço",
|
||||
"ui.panel_layout.your_layout": "seu layout",
|
||||
"ui.parallel": "Paralelo",
|
||||
"ui.parameters": "Parâmetros",
|
||||
"ui.part_size_needs_a_part": "Selecione uma peça padrão inserida (um parafuso, uma porca, uma arruela ou um pino) para alterar o tamanho. Para aumentar ou diminuir um corpo, use Escala.",
|
||||
@@ -5823,6 +5946,8 @@
|
||||
"ui.profiles": "Perfis",
|
||||
"ui.project": "Projetar",
|
||||
"ui.project_face_edges_sketch": "Projetar arestas da face em novos esboços",
|
||||
"ui.project_references_construction": "Projetar referências como geometria de construção",
|
||||
"ui.project_references_construction_note": "Projetar, Intersectar, Incluir Geometria 3D e as arestas da face de um novo esboço em uma face criam geometria de construção: referências para desenhar, deixadas fora dos perfis. Elas permanecem vinculadas ao modelo.",
|
||||
"ui.properties": "Propriedades",
|
||||
"ui.properties.copy_matrix": "Copiar matriz",
|
||||
"ui.properties.first_moments": "Primeiros momentos",
|
||||
@@ -5866,6 +5991,8 @@
|
||||
"ui.renderer": "Renderizador",
|
||||
"ui.repeat": "Repetir",
|
||||
"ui.repeat_nothing": "Ainda não há nada para repetir: inicie primeiro uma ferramenta ou caixa de diálogo.",
|
||||
"ui.replace_sketch.from_file": "De um Arquivo de Projeto…",
|
||||
"ui.replace_sketch.no_sketches": "Esse projeto não tem esboço para usar",
|
||||
"ui.replace_with_link_done": "As cópias agora são posicionamentos do projeto vinculado.",
|
||||
"ui.report_a_bug": "Relatar um bug",
|
||||
"ui.report_characters_left_one": "{count} caractere restante",
|
||||
|
||||
+1214
-212
File diff suppressed because it is too large
Load Diff
@@ -5041,7 +5041,7 @@
|
||||
"ui.agent_chat_permission": "智能体请求运行:{title}",
|
||||
"ui.agent_chat_pick": "智能体",
|
||||
"ui.agent_chat_pick_context": "选择上下文",
|
||||
"ui.agent_chat_pick_context_tip": "在模型中选择要让智能体查看的面、边、特征和实体,然后点击确定",
|
||||
"ui.agent_chat_pick_context_tip": "在模型中选择面、边、特征和实体,然后点击确定:它们会作为标签放入消息中光标所在的位置(输入 @ 效果相同)",
|
||||
"ui.agent_chat_placeholder": "让智能体修改设计…",
|
||||
"ui.agent_chat_placeholder_busy": "输入消息,待智能体完成后发送(Ctrl+Enter:立即发送)",
|
||||
"ui.agent_chat_pop_out": "在独立窗口中打开(可移到另一个屏幕)",
|
||||
|
||||
@@ -23,7 +23,7 @@ from pathlib import Path
|
||||
from PIL import Image, ImageDraw, ImageFont
|
||||
|
||||
HERE = Path(__file__).resolve().parent
|
||||
FONTS = HERE.parents[2] / "fonts"
|
||||
FONTS = HERE.parents[3] / "crates/look/fonts"
|
||||
LAYOUT = json.loads((HERE / "layout.json").read_text())
|
||||
W, H = LAYOUT["window"]
|
||||
ICON = LAYOUT["icon_size"]
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
| assets/locales/pending/agent-chat-select-all.json | SolidCraft contributors | Original assistant chat select-all strings and translations | MIT OR Apache-2.0 |
|
||||
@@ -0,0 +1,5 @@
|
||||
| docs/book/src/media/ui-tour/window.light.png | SolidCraft contributors | screenshot of SolidCraft 0.29.0 itself (`solidcraft --sample`, light theme, software renderer, 1280x800) with original numbered callouts (digits set in DejaVu Sans Bold), captured with examples/demo/doc_shots.py --light | MIT OR Apache-2.0 |
|
||||
| docs/book/src/media/sketching/parts.light.png | SolidCraft contributors | screenshot of SolidCraft 0.29.0 itself (light theme, software renderer, 1280x800) showing a fully constrained sketch, with original numbered callouts (digits set in DejaVu Sans Bold), captured with examples/demo/doc_shots.py --light | MIT OR Apache-2.0 |
|
||||
| docs/book/src/media/parameters/dialog.light.png | SolidCraft contributors | screenshot of SolidCraft 0.29.0 itself (light theme, software renderer) showing the Parameters dialog, with original numbered callouts (digits set in DejaVu Sans Bold), captured with examples/demo/doc_shots.py --light | MIT OR Apache-2.0 |
|
||||
| docs/book/src/media/getting-started/start.light.png | SolidCraft contributors | screenshot of SolidCraft 0.29.0 itself (light theme, software renderer, 1280x800) showing the start page with its built-in sample thumbnails, with original numbered callouts (digits set in DejaVu Sans Bold), captured with examples/demo/doc_shots.py --light | MIT OR Apache-2.0 |
|
||||
| docs/book/src/media/files/menu.light.png | SolidCraft contributors | screenshot of SolidCraft 0.29.0 itself (`--sample`, light theme, software renderer) showing the File menu, with original numbered callouts (digits set in DejaVu Sans Bold), captured with examples/demo/doc_shots.py --light | MIT OR Apache-2.0 |
|
||||
@@ -0,0 +1 @@
|
||||
| assets/locales/pending/constraint-glyph-size.json | SolidCraft contributors | Original constraint glyph size preference label and help text | MIT OR Apache-2.0 |
|
||||
@@ -0,0 +1,3 @@
|
||||
| crates/look/icons/design/svg/model/end_cap.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/end_cap_inward.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
| crates/look/icons/design/svg/model/end_cap_outward.svg | SolidCraft contributors | original icon master (64 grid) | SolidCraft Brand and Interface Licence (LICENSE-BRAND) |
|
||||
@@ -94,28 +94,101 @@ impl Hub {
|
||||
/// on it). A listener that is not on a loopback address is refused: the channel never goes on
|
||||
/// the network.
|
||||
pub fn listen(self: &Arc<Self>, listener: TcpListener, token: String, requests: Sender<ControlRequest>, patient: bool) -> std::io::Result<()> {
|
||||
self.listen_stoppable(listener, token, requests, patient).map(drop)
|
||||
}
|
||||
|
||||
/// [`Hub::listen`], and a [`Stop`] that closes the listener and the connections it accepted
|
||||
/// (a channel turned off in the app's settings). Dropping the [`Stop`] leaves it serving.
|
||||
pub fn listen_stoppable(
|
||||
self: &Arc<Self>,
|
||||
listener: TcpListener,
|
||||
token: String,
|
||||
requests: Sender<ControlRequest>,
|
||||
patient: bool,
|
||||
) -> std::io::Result<Stop> {
|
||||
let addr = listener.local_addr()?;
|
||||
if !addr.ip().is_loopback() {
|
||||
return Err(std::io::Error::new(std::io::ErrorKind::InvalidInput, format!("the control channel listens on loopback only, not {addr}")));
|
||||
}
|
||||
let hub = Arc::clone(self);
|
||||
let token = Arc::new(token);
|
||||
let shared = Arc::new(Accepted::default());
|
||||
let (closed_tx, closed) = channel::<()>();
|
||||
let stop = Stop { addr, shared: Arc::clone(&shared), closed };
|
||||
std::thread::spawn(move || {
|
||||
// Dropped when this thread ends, with the listener: `Stop::stop` waits for that.
|
||||
let _closed = closed_tx;
|
||||
for stream in listener.incoming().flatten() {
|
||||
if shared.stopped.load(Ordering::SeqCst) {
|
||||
break;
|
||||
}
|
||||
if hub.open.fetch_add(1, Ordering::Relaxed) >= MAX_CONNECTIONS {
|
||||
hub.open.fetch_sub(1, Ordering::Relaxed);
|
||||
let mut refused = stream;
|
||||
let _ = send(&mut refused, &json!({"ok": false, "error": "too many connections"}));
|
||||
continue;
|
||||
}
|
||||
let (hub, tx, token) = (Arc::clone(&hub), requests.clone(), Arc::clone(&token));
|
||||
let id = shared.next.fetch_add(1, Ordering::Relaxed);
|
||||
if let Ok(copy) = stream.try_clone() {
|
||||
shared.lock().push((id, copy));
|
||||
}
|
||||
// Stopped while this one was being accepted: it is closed with the rest.
|
||||
if shared.stopped.load(Ordering::SeqCst) {
|
||||
shared.close_all();
|
||||
}
|
||||
let (hub, tx, token, shared) = (Arc::clone(&hub), requests.clone(), Arc::clone(&token), Arc::clone(&shared));
|
||||
std::thread::spawn(move || {
|
||||
hub.serve(stream, &token, tx, patient);
|
||||
hub.open.fetch_sub(1, Ordering::Relaxed);
|
||||
shared.lock().retain(|(i, _)| *i != id);
|
||||
});
|
||||
}
|
||||
});
|
||||
Ok(())
|
||||
Ok(stop)
|
||||
}
|
||||
}
|
||||
|
||||
/// The connections a stoppable listener accepted, so stopping it can close them too.
|
||||
#[derive(Default)]
|
||||
struct Accepted {
|
||||
stopped: AtomicBool,
|
||||
next: AtomicU64,
|
||||
streams: Mutex<Vec<(u64, TcpStream)>>,
|
||||
}
|
||||
|
||||
impl Accepted {
|
||||
fn lock(&self) -> MutexGuard<'_, Vec<(u64, TcpStream)>> {
|
||||
self.streams.lock().unwrap_or_else(PoisonError::into_inner)
|
||||
}
|
||||
|
||||
fn close_all(&self) {
|
||||
for (_, stream) in self.lock().drain(..) {
|
||||
let _ = stream.shutdown(std::net::Shutdown::Both);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Stops a listener started with [`Hub::listen_stoppable`].
|
||||
pub struct Stop {
|
||||
addr: std::net::SocketAddr,
|
||||
shared: Arc<Accepted>,
|
||||
closed: Receiver<()>,
|
||||
}
|
||||
|
||||
impl Stop {
|
||||
/// The port the listener is on.
|
||||
pub fn port(&self) -> u16 {
|
||||
self.addr.port()
|
||||
}
|
||||
|
||||
/// Stop accepting, close the port and end every connection it accepted. Returns once the
|
||||
/// port is closed (at most a couple of seconds), so the same port can be bound again at once.
|
||||
pub fn stop(self) {
|
||||
self.shared.stopped.store(true, Ordering::SeqCst);
|
||||
// The listener waits in `accept`: a connection of our own wakes it to see the flag.
|
||||
let _ = TcpStream::connect_timeout(&self.addr, Duration::from_secs(1));
|
||||
let _ = self.closed.recv_timeout(Duration::from_secs(2));
|
||||
self.shared.close_all();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1154,4 +1227,35 @@ mod tests {
|
||||
assert_eq!(out.bytes.last(), Some(&b'\n'));
|
||||
assert_eq!(serde_json::from_slice::<Value>(&out.bytes).unwrap(), reply);
|
||||
}
|
||||
|
||||
/// A stopped listener frees its port at once and ends the connections it had, so a channel
|
||||
/// turned off in the settings leaves nothing listening and can be turned on again on the
|
||||
/// same port.
|
||||
#[test]
|
||||
fn a_stopped_listener_closes_its_port_and_its_connections() {
|
||||
use std::io::Read;
|
||||
let listener = TcpListener::bind(("127.0.0.1", 0)).unwrap();
|
||||
let port = listener.local_addr().unwrap().port();
|
||||
let (tx, _rx) = channel();
|
||||
let stop = hub(Waits::default(), &DOCUMENT_WATCH).listen_stoppable(listener, "0123456789abcdef0123456789abcdef".into(), tx, false).unwrap();
|
||||
assert_eq!(stop.port(), port);
|
||||
let mut client = TcpStream::connect(("127.0.0.1", port)).unwrap();
|
||||
client.set_read_timeout(Some(Duration::from_secs(4))).unwrap();
|
||||
// Wait until the server holds the connection, so stopping has one to close.
|
||||
let held = Instant::now();
|
||||
while stop.shared.lock().is_empty() && held.elapsed() < Duration::from_secs(4) {
|
||||
std::thread::sleep(Duration::from_millis(5));
|
||||
}
|
||||
let started = Instant::now();
|
||||
stop.stop();
|
||||
let mut byte = [0u8; 1];
|
||||
match client.read(&mut byte) {
|
||||
Ok(n) => assert_eq!(n, 0, "the connection ends"),
|
||||
Err(e) => {
|
||||
assert!(!matches!(e.kind(), std::io::ErrorKind::WouldBlock | std::io::ErrorKind::TimedOut), "the connection ends, not waits: {e}")
|
||||
}
|
||||
}
|
||||
assert!(started.elapsed() < Duration::from_secs(3), "before the token wait runs out");
|
||||
assert!(TcpListener::bind(("127.0.0.1", port)).is_ok(), "the port is free again");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,8 +221,8 @@ fn map_plane_ref(m: &Mat, p: &mut PlaneRef) {
|
||||
map_geo_ref(m, g);
|
||||
}
|
||||
}
|
||||
// Named origin planes and construction planes are the component's own.
|
||||
PlaneRef::Origin { .. } | PlaneRef::Construction { .. } => {}
|
||||
// Named origin planes, construction planes and placement datums are the component's own.
|
||||
PlaneRef::Origin { .. } | PlaneRef::Datum { .. } | PlaneRef::Construction { .. } => {}
|
||||
PlaneRef::Tangent { face, at, reference, .. } => {
|
||||
*at = apply_point(m, *at);
|
||||
map_geo_ref(m, face);
|
||||
|
||||
@@ -213,6 +213,11 @@ impl crate::Feature {
|
||||
checked_link(&link.source, 0)?;
|
||||
}
|
||||
}
|
||||
K::FrameEndCap { ends, .. } => {
|
||||
for end in ends {
|
||||
checked_plane(&end.plane, 0)?;
|
||||
}
|
||||
}
|
||||
K::ConstructionPlane { plane }
|
||||
| K::Split { plane, .. }
|
||||
| K::SplitFace { plane, .. }
|
||||
@@ -283,6 +288,11 @@ impl crate::Feature {
|
||||
}
|
||||
}
|
||||
}
|
||||
K::FrameEndCap { ends, .. } => {
|
||||
for end in ends {
|
||||
remap_plane(&mut end.plane, ids, bodies, 0)?;
|
||||
}
|
||||
}
|
||||
K::ConstructionPlane { plane }
|
||||
| K::Split { plane, .. }
|
||||
| K::SplitFace { plane, .. }
|
||||
|
||||
@@ -78,7 +78,7 @@ impl Document {
|
||||
.assembly
|
||||
.joints
|
||||
.iter()
|
||||
.filter(|j| occurrences.contains(&j.a.occurrence) || occurrences.contains(&j.b.occurrence))
|
||||
.filter(|j| j.a.occurrences().chain(j.b.occurrences()).any(|o| occurrences.contains(&o)))
|
||||
.map(|j| j.id)
|
||||
.collect();
|
||||
for group in &mut self.timeline_groups {
|
||||
@@ -87,7 +87,7 @@ impl Document {
|
||||
let assembly = &mut self.assembly;
|
||||
assembly.joints.retain(|j| !joints.contains(&j.id));
|
||||
assembly.links.retain(|l| !joints.contains(&l.a) && !joints.contains(&l.b));
|
||||
assembly.origins.retain(|o| !occurrences.contains(&o.origin.occurrence));
|
||||
assembly.origins.retain(|o| !o.origin.occurrences().any(|o| occurrences.contains(&o)));
|
||||
for set in &mut assembly.contact_sets {
|
||||
set.occurrences.retain(|o| !occurrences.contains(o));
|
||||
}
|
||||
|
||||
@@ -211,7 +211,7 @@ pub enum FaceCertificate {
|
||||
},
|
||||
/// A flat face known by its exact history name (the target's `name`, without piece
|
||||
/// numbers): what the kernel's face history says it came from, followed through every
|
||||
/// feature since (a cut wall `F5:side:l1`, a chamfer `F7:blend:…`, a pattern copy
|
||||
/// feature since (a cut wall `F5:side:l1`, a chamfer `F7:blend(…)`, a pattern copy
|
||||
/// `F4:top@F6.2`, a face a join merged from two features). Used where no construction
|
||||
/// certificate above names the face uniquely. Its plane is the face's exact current plane in
|
||||
/// the frame [`lineage_frame`] gives it. See docs/face-attachments.md.
|
||||
|
||||
+177
-14
@@ -10,7 +10,7 @@ use solidcraft_geom::prelude::*;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use solidcore_record::{Plane, Vec2, Vec3};
|
||||
use solidcore_record::{Plane, Vec3};
|
||||
use solidcraft_kernel::{self as kernel, FaceSurface};
|
||||
|
||||
use crate::eval::{ModelBody, ModelState};
|
||||
@@ -23,6 +23,9 @@ use crate::{DocError, Document, PlaneRef, Result};
|
||||
pub enum GeoRef {
|
||||
/// A fixed point.
|
||||
Point { p: Vec3 },
|
||||
/// An origin datum of an exact placement (its O point, an axis or a plane), found again on
|
||||
/// each evaluation, so it follows the component the way a named reference does.
|
||||
Datum { datum: DatumRef },
|
||||
/// The design origin.
|
||||
Origin,
|
||||
/// A body vertex: where the edges named `edges` meet (the end they share), else the one
|
||||
@@ -52,7 +55,7 @@ pub enum GeoRef {
|
||||
Axis { name: crate::FeatureName },
|
||||
/// A construction point feature, by name.
|
||||
ConstructPoint { name: crate::FeatureName },
|
||||
/// A sketch point (by sketch feature id and point id).
|
||||
/// A sketch point (by sketch feature id and point id), or a drawn wire node as `wire:index`.
|
||||
SketchPoint { sketch: u64, point: String },
|
||||
/// A sketch curve (by sketch feature id and curve id).
|
||||
SketchCurve { sketch: u64, curve: String },
|
||||
@@ -112,6 +115,129 @@ impl ConstructGeom {
|
||||
}
|
||||
}
|
||||
|
||||
/// One of the seven named items of a placement's Origin folder: the O point, the X, Y and Z
|
||||
/// axes, and the XY, XZ and YZ planes. Case-insensitive to parse; the `Plane::named` aliases
|
||||
/// (TOP/FRONT/RIGHT) stay root-only.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum DatumItem {
|
||||
O,
|
||||
X,
|
||||
Y,
|
||||
Z,
|
||||
XY,
|
||||
XZ,
|
||||
YZ,
|
||||
}
|
||||
|
||||
impl DatumItem {
|
||||
/// The item's name as a key spells it.
|
||||
pub fn name(self) -> &'static str {
|
||||
match self {
|
||||
DatumItem::O => "O",
|
||||
DatumItem::X => "X",
|
||||
DatumItem::Y => "Y",
|
||||
DatumItem::Z => "Z",
|
||||
DatumItem::XY => "XY",
|
||||
DatumItem::XZ => "XZ",
|
||||
DatumItem::YZ => "YZ",
|
||||
}
|
||||
}
|
||||
|
||||
/// Case-insensitive; the Plane::named aliases (TOP/FRONT/RIGHT) stay root-only.
|
||||
pub fn parse(name: &str) -> Option<Self> {
|
||||
Some(match name.to_ascii_uppercase().as_str() {
|
||||
"O" => DatumItem::O,
|
||||
"X" => DatumItem::X,
|
||||
"Y" => DatumItem::Y,
|
||||
"Z" => DatumItem::Z,
|
||||
"XY" => DatumItem::XY,
|
||||
"XZ" => DatumItem::XZ,
|
||||
"YZ" => DatumItem::YZ,
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
|
||||
/// The item in its component's own frame: O the point, X/Y/Z the axes, XY/XZ/YZ the planes.
|
||||
pub fn geom(self) -> ConstructGeom {
|
||||
match self {
|
||||
DatumItem::O => ConstructGeom::Point(Vec3::ZERO),
|
||||
DatumItem::X => ConstructGeom::Axis { origin: Vec3::ZERO, dir: Vec3::X },
|
||||
DatumItem::Y => ConstructGeom::Axis { origin: Vec3::ZERO, dir: Vec3::Y },
|
||||
DatumItem::Z => ConstructGeom::Axis { origin: Vec3::ZERO, dir: Vec3::Z },
|
||||
DatumItem::XY => ConstructGeom::Plane(Plane::XY),
|
||||
DatumItem::XZ => ConstructGeom::Plane(Plane::XZ),
|
||||
DatumItem::YZ => ConstructGeom::Plane(Plane::YZ),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An origin datum of an exact placement. The empty path is never a `DatumRef`: the root keeps
|
||||
/// `PlaneRef::Origin` and `GeoRef::Origin` as they are.
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct DatumRef {
|
||||
/// The occurrence ids of the placement, root first.
|
||||
pub path: Vec<u64>,
|
||||
pub item: DatumItem,
|
||||
}
|
||||
|
||||
impl DatumRef {
|
||||
/// The datum's Browser key: `o:2/3/origin/XY`.
|
||||
pub fn key(&self) -> String {
|
||||
format!("o:{}/origin/{}", self.path.iter().map(|id| id.to_string()).collect::<Vec<_>>().join("/"), self.item.name())
|
||||
}
|
||||
|
||||
/// Strict: canonical non-zero decimal ids, depth at most 64, length at most 2048. Rejects
|
||||
/// `c0/origin`, `o:01/origin/X` and `o:0/origin/X`.
|
||||
pub fn parse_key(key: &str) -> Option<Self> {
|
||||
if key.len() > 2048 {
|
||||
return None;
|
||||
}
|
||||
let rest = key.strip_prefix("o:")?;
|
||||
let (ids, item) = rest.rsplit_once("/origin/")?;
|
||||
if ids.is_empty() || ids.split('/').count() > 64 {
|
||||
return None;
|
||||
}
|
||||
let path = ids.split('/').map(|id| id.parse::<u64>().ok().filter(|n| *n != 0 && n.to_string() == id)).collect::<Option<Vec<_>>>()?;
|
||||
Some(DatumRef { path, item: DatumItem::parse(item)? })
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for DatumRef {
|
||||
/// Saved as its Browser key: `o:2/3/origin/XY`.
|
||||
fn serialize<S: serde::Serializer>(&self, s: S) -> std::result::Result<S::Ok, S::Error> {
|
||||
s.serialize_str(&self.key())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for DatumRef {
|
||||
/// Reads a saved reference back from its Browser key: anything that is not a bounded
|
||||
/// datum key is a deserialize error, so an older release never mis-reads a newer design.
|
||||
fn deserialize<D: serde::Deserializer<'de>>(d: D) -> std::result::Result<Self, D::Error> {
|
||||
let key = String::deserialize(d)?;
|
||||
DatumRef::parse_key(&key).ok_or_else(|| serde::de::Error::custom(format!("not a datum key: `{key}`")))
|
||||
}
|
||||
}
|
||||
|
||||
/// An origin datum of an exact placement, resolved at evaluation time: the item in its own
|
||||
/// component's frame, placed by the placement's world frame. It follows the component on every
|
||||
/// evaluation, the way `PlaneRef::Face` re-finds its face.
|
||||
pub fn resolve_datum(doc: &Document, d: &DatumRef) -> Result<ConstructGeom> {
|
||||
Ok(d.item.geom().placed(&doc.placement_frame(&d.path)?))
|
||||
}
|
||||
|
||||
/// [`resolve_datum`] as the component `component` sees it: placed by the placements, then
|
||||
/// mapped back through that component's frame, since a feature evaluated in its own frame
|
||||
/// places what it reads into the world again through that frame (the world pass). The root
|
||||
/// (0) reads the world as it is.
|
||||
pub fn resolve_datum_in(doc: &Document, d: &DatumRef, component: u64) -> Result<ConstructGeom> {
|
||||
if component == 0 {
|
||||
return resolve_datum(doc, d);
|
||||
}
|
||||
let inverse =
|
||||
crate::mat_inverse(&doc.component_transform(component)).ok_or_else(|| DocError::Invalid("the component's placement is singular".into()))?;
|
||||
Ok(resolve_datum(doc, d)?.placed(&inverse))
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Construct {
|
||||
pub feature: u64,
|
||||
@@ -133,6 +259,10 @@ pub(crate) struct Ctx<'a> {
|
||||
/// geometry resolves its sides through the document again, so the count has to continue
|
||||
/// across that hop; restarting it lets a plane that refers to itself recurse forever.
|
||||
pub depth: usize,
|
||||
/// The component the reading feature lives in: a datum it reads is found through the
|
||||
/// placements and mapped back into this frame ([`resolve_datum_in`]). The root (0) is
|
||||
/// the world.
|
||||
pub component: u64,
|
||||
}
|
||||
|
||||
fn bad(m: impl Into<String>) -> DocError {
|
||||
@@ -308,11 +438,6 @@ fn as_circle(pts: &[Vec3]) -> Option<(Vec3, Vec3, f64)> {
|
||||
.then_some((centre, unit, r))
|
||||
}
|
||||
|
||||
fn sketch_world(ctx: &Ctx, sketch: u64, q: Vec2) -> Result<Vec3> {
|
||||
let ss = ctx.st.sketch(sketch).ok_or_else(|| DocError::Unknown(format!("sketch {sketch}")))?;
|
||||
Ok(ss.plane.to_world(q))
|
||||
}
|
||||
|
||||
fn sketch_curve_points(ctx: &Ctx, sketch: u64, curve: &str) -> Result<Vec<Vec3>> {
|
||||
let ss = ctx.st.sketch(sketch).ok_or_else(|| DocError::Unknown(format!("sketch {sketch}")))?;
|
||||
if let Some(wire) = ss.sketch.wires.iter().find(|wire| wire.id == curve) {
|
||||
@@ -358,17 +483,30 @@ pub(crate) fn point(ctx: &Ctx, g: &GeoRef) -> Result<Vec3> {
|
||||
_ => Err(bad(format!("`{name}` is not a point"))),
|
||||
},
|
||||
GeoRef::SketchPoint { sketch, point } => {
|
||||
let ss = ctx.st.sketch(*sketch).ok_or_else(|| DocError::Unknown(format!("sketch {sketch}")))?;
|
||||
let q =
|
||||
ss.sketch.point_index(point).and_then(|i| ss.sketch.point(i)).ok_or_else(|| DocError::Unknown(format!("sketch point `{point}`")))?;
|
||||
sketch_world(ctx, *sketch, q)
|
||||
sketch_point_position(ctx.st, *sketch, point).ok_or_else(|| DocError::Unknown(format!("sketch point `{point}`")))
|
||||
}
|
||||
// A round edge or face: its centre.
|
||||
GeoRef::Edge { .. } | GeoRef::Face { .. } | GeoRef::SketchCurve { .. } => centre(ctx, g),
|
||||
GeoRef::Datum { datum } => match resolve_datum_in(ctx.doc, datum, ctx.component)? {
|
||||
ConstructGeom::Point(p) => Ok(p),
|
||||
_ => Err(bad("the datum is not a point (pick the O of a component)")),
|
||||
},
|
||||
_ => Err(bad("pick a point, vertex or sketch point")),
|
||||
}
|
||||
}
|
||||
|
||||
/// Resolve a planar point or a drawn 3D wire's `wire:index` node in the evaluated state's frame.
|
||||
/// Wire coordinates have already been placed; applying the sketch plane again would move them twice.
|
||||
pub fn sketch_point_position(st: &ModelState, sketch: u64, point: &str) -> Option<Vec3> {
|
||||
let ss = st.sketch(sketch)?;
|
||||
if let Some(p) = ss.sketch.point_index(point).and_then(|i| ss.sketch.point(i)) {
|
||||
return Some(ss.plane.to_world(p));
|
||||
}
|
||||
let (wire, index) = point.rsplit_once(':')?;
|
||||
let index = index.parse::<usize>().ok()?;
|
||||
ss.sketch.wires.get(ss.sketch.wire_index(wire)?)?.fit.get(index).copied()
|
||||
}
|
||||
|
||||
/// An edge or face of the model as a line: along a straight edge, through the centre of a
|
||||
/// circular edge along its normal, or the axis of a cylinder, cone or torus face.
|
||||
fn model_line(st: &ModelState, g: &GeoRef) -> Result<(Vec3, Vec3)> {
|
||||
@@ -403,6 +541,23 @@ pub fn model_axis(st: &ModelState, g: &GeoRef) -> Result<(Vec3, Vec3)> {
|
||||
Ok((o, canonical_dir(d)))
|
||||
}
|
||||
|
||||
/// [`model_axis`] for references that may name a component's origin datum: the datum is placed
|
||||
/// through the document's placements ([`resolve_datum_in`], as the component `component` sees
|
||||
/// it), the rest as [`model_axis`] finds it in the model state. `None` for a datum asks for an
|
||||
/// evaluation.
|
||||
pub fn model_axis_in(doc: Option<&Document>, st: &ModelState, g: &GeoRef, component: u64) -> Result<(Vec3, Vec3)> {
|
||||
match g {
|
||||
GeoRef::Datum { datum } => {
|
||||
let doc = doc.ok_or_else(|| bad("this axis is built from a component's origin: evaluate first"))?;
|
||||
match resolve_datum_in(doc, datum, component)? {
|
||||
ConstructGeom::Axis { origin, dir } => Ok((origin, dir)),
|
||||
_ => Err(bad("the datum is not an axis (pick the X, Y or Z of a component)")),
|
||||
}
|
||||
}
|
||||
_ => model_axis(st, g),
|
||||
}
|
||||
}
|
||||
|
||||
/// `d` or `-d`, whichever has its largest component (the first of equal ones) positive: how
|
||||
/// [`model_axis`] orients an axis, for a preview of one to point the same way.
|
||||
pub fn canonical_dir(d: Vec3) -> Vec3 {
|
||||
@@ -417,6 +572,10 @@ pub fn canonical_dir(d: Vec3) -> Vec3 {
|
||||
/// A reference as a line (origin, unit direction).
|
||||
pub(crate) fn line(ctx: &Ctx, g: &GeoRef) -> Result<(Vec3, Vec3)> {
|
||||
match g {
|
||||
GeoRef::Datum { datum } => match resolve_datum_in(ctx.doc, datum, ctx.component)? {
|
||||
ConstructGeom::Axis { origin, dir } => Ok((origin, dir)),
|
||||
_ => Err(bad("the datum is not an axis (pick the X, Y or Z of a component)")),
|
||||
},
|
||||
GeoRef::Edge { .. } | GeoRef::Face { .. } => model_line(ctx.st, g),
|
||||
GeoRef::SketchCurve { sketch, curve } => {
|
||||
let pts = sketch_curve_points(ctx, *sketch, curve)?;
|
||||
@@ -442,7 +601,7 @@ pub(crate) fn line(ctx: &Ctx, g: &GeoRef) -> Result<(Vec3, Vec3)> {
|
||||
/// A reference as a plane.
|
||||
pub(crate) fn plane(ctx: &Ctx, g: &GeoRef) -> Result<Plane> {
|
||||
match g {
|
||||
GeoRef::Plane { plane } => ctx.doc.resolve_plane_in(ctx.vals, plane, ctx.depth + 1, Some(ctx.st)),
|
||||
GeoRef::Plane { plane } => ctx.doc.resolve_plane_in(ctx.vals, plane, ctx.depth + 1, ctx.component, Some(ctx.st)),
|
||||
GeoRef::Face { at, name } => {
|
||||
let (b, fi, q) = face_of(ctx.st, *at, name)?;
|
||||
match kernel::face_surface(&b.body, fi) {
|
||||
@@ -453,6 +612,10 @@ pub(crate) fn plane(ctx: &Ctx, g: &GeoRef) -> Result<Plane> {
|
||||
_ => Err(bad("the face is not planar")),
|
||||
}
|
||||
}
|
||||
GeoRef::Datum { datum } => match resolve_datum_in(ctx.doc, datum, ctx.component)? {
|
||||
ConstructGeom::Plane(p) => Ok(p),
|
||||
_ => Err(bad("the datum is not a plane (pick the XY, XZ or YZ of a component)")),
|
||||
},
|
||||
_ => Err(bad("pick a plane or planar face")),
|
||||
}
|
||||
}
|
||||
@@ -846,11 +1009,11 @@ pub(crate) fn resolve_geo_plane(ctx: &Ctx, p: &PlaneRef) -> Result<Plane> {
|
||||
Plane::from_normal(p, tan).ok_or_else(degenerate)
|
||||
}
|
||||
PlaneRef::ThroughPoint { base, point: at } => {
|
||||
let b = ctx.doc.resolve_plane_in(ctx.vals, base, ctx.depth + 1, Some(ctx.st))?;
|
||||
let b = ctx.doc.resolve_plane_in(ctx.vals, base, ctx.depth + 1, ctx.component, Some(ctx.st))?;
|
||||
let n = b.normal().normalized().ok_or_else(degenerate)?;
|
||||
Ok(Plane { origin: b.origin + n * (point(ctx, at)? - b.origin).dot(n), ..b })
|
||||
}
|
||||
_ => ctx.doc.resolve_plane_in(ctx.vals, p, ctx.depth + 1, Some(ctx.st)),
|
||||
_ => ctx.doc.resolve_plane_in(ctx.vals, p, ctx.depth + 1, ctx.component, Some(ctx.st)),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+94
-19
@@ -45,6 +45,9 @@ pub enum PlaneRef {
|
||||
Origin { name: String },
|
||||
/// An explicit plane (e.g. picked from a planar face).
|
||||
Custom { plane: Plane },
|
||||
/// An origin datum of an exact placement (its XY, XZ or YZ), found again on each evaluation
|
||||
/// so it follows the component the way a named plane does.
|
||||
Datum { datum: crate::construct::DatumRef },
|
||||
/// An explicit plane whose origin is given as length expressions
|
||||
/// (`{origin: ["half", 0, 0], normal: [1, 0, 0]}`), so it follows parameter changes.
|
||||
Placed {
|
||||
@@ -540,31 +543,68 @@ impl EmbossFace {
|
||||
|
||||
/// Resolve one saved component path without expanding other occurrences.
|
||||
pub fn component_frame(doc: &Document, owner: u64, path: &[u64]) -> Result<crate::Mat> {
|
||||
if path.len() > 64 || doc.occurrences.len() > 100_000 {
|
||||
return Err(DocError::Invalid("selected cylinder path exceeds work limits".into()));
|
||||
let frame = doc.placement_frame(path)?;
|
||||
match path.split_last() {
|
||||
None => Ok(doc.component_transform(owner)),
|
||||
Some((last, _)) => {
|
||||
let component = doc.occurrences.iter().find(|o| o.id == *last).map(|o| o.component);
|
||||
if component == Some(owner) {
|
||||
Ok(frame)
|
||||
} else {
|
||||
Err(DocError::Invalid("selected cylinder path belongs to another component".into()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Document {
|
||||
/// The world frame of one exact placement, without expanding every occurrence: the frame
|
||||
/// every origin datum of the placement resolves in ([`crate::construct::resolve_datum`]).
|
||||
/// The empty path is the root design frame. The shared walk of an exact placement (the
|
||||
/// Emboss selection's `component_frame` delegates to it): depth at most 64, non-zero
|
||||
/// canonical ids, no id repeated in a path, at most 100 000 occurrences.
|
||||
pub fn placement_frame(&self, path: &[u64]) -> Result<crate::Mat> {
|
||||
if path.len() > 64 || self.occurrences.len() > 100_000 {
|
||||
return Err(DocError::Invalid("the placement path exceeds work limits".into()));
|
||||
}
|
||||
let mut frame = crate::IDENTITY;
|
||||
let mut component = 0;
|
||||
let mut seen = std::collections::BTreeSet::new();
|
||||
for id in path {
|
||||
if *id == 0 || !seen.insert(*id) {
|
||||
return Err(DocError::Invalid("invalid selected cylinder path".into()));
|
||||
return Err(DocError::Invalid("invalid placement path".into()));
|
||||
}
|
||||
let occurrence = doc
|
||||
let occurrence = self
|
||||
.occurrences
|
||||
.iter()
|
||||
.find(|o| o.id == *id && o.parent == component)
|
||||
.ok_or_else(|| DocError::Invalid("selected cylinder placement no longer exists".into()))?;
|
||||
.ok_or_else(|| DocError::Invalid("the placement no longer exists".into()))?;
|
||||
frame = crate::mat_mul(&frame, &occurrence.transform);
|
||||
component = occurrence.component;
|
||||
}
|
||||
if path.is_empty() {
|
||||
frame = doc.component_transform(owner);
|
||||
} else if component != owner {
|
||||
return Err(DocError::Invalid("selected cylinder path belongs to another component".into()));
|
||||
}
|
||||
Ok(frame)
|
||||
}
|
||||
|
||||
/// The complete occurrence path of one occurrence, root first (the ids
|
||||
/// [`Self::placement_frame`] walks): the occurrence itself, then its ancestors, each stepped
|
||||
/// through its parent component's first occurrence, as `occurrence_world` reads a parent.
|
||||
/// `None` when the occurrence is missing or its chain is broken, cyclic or deeper than 64.
|
||||
pub fn occurrence_path(&self, occurrence: u64) -> Option<Vec<u64>> {
|
||||
let mut path = Vec::new();
|
||||
let mut cur = occurrence;
|
||||
while let Some(o) = self.occurrences.iter().find(|o| o.id == cur) {
|
||||
if path.len() >= 64 {
|
||||
return None;
|
||||
}
|
||||
path.insert(0, o.id);
|
||||
if o.parent == 0 {
|
||||
return Some(path);
|
||||
}
|
||||
cur = self.occurrence_of(o.parent)?.id;
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// One edge of an edge flange feature: a point on the sheet's edge and, where given, this
|
||||
@@ -993,6 +1033,10 @@ pub enum FeatureKind {
|
||||
length: Option<Expr>,
|
||||
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
|
||||
modeled: bool,
|
||||
/// Continuous flank faces for this feature. Missing in older designs: keep
|
||||
/// their half-turn faces and groove-before-chamfer order for saved references.
|
||||
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
|
||||
continuous_flanks: bool,
|
||||
/// A point near the end of the face the thread starts at; `None`: the face's only free
|
||||
/// end (no material past it), or the end the pick at `face` lies near.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
@@ -1190,6 +1234,25 @@ pub enum FeatureKind {
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
targets: Vec<BodyName>,
|
||||
},
|
||||
/// Plates closing open ends of frame members (#4003), one body per end, each the outside of
|
||||
/// the member's profile, optionally set in from its edge.
|
||||
FrameEndCap {
|
||||
ends: Vec<crate::end_cap::End>,
|
||||
#[walk(length = "Thickness")]
|
||||
thickness: Expr,
|
||||
/// The inset from the outline's edge as a length, or `ratio` of the thickness; neither:
|
||||
/// flush with the outside of the profile.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[walk(length = "Inset")]
|
||||
offset: Option<Expr>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[walk(unitless = "Inset Ratio")]
|
||||
ratio: Option<Expr>,
|
||||
#[walk(length = "Corner Chamfer")]
|
||||
chamfer: Expr,
|
||||
#[serde(default)]
|
||||
direction: crate::end_cap::Direction,
|
||||
},
|
||||
/// Structural members (#4003): one body per straight line of a frame sketch (2D sketch lines
|
||||
/// and 3D sketch lines), its cross-section the profile, square to the line from end to end.
|
||||
FrameMember {
|
||||
@@ -2733,6 +2796,7 @@ impl FeatureKind {
|
||||
FeatureKind::SurfaceOffset { .. } => "OffsetSurfaceFeature",
|
||||
FeatureKind::BoundingSolid { .. } => "BoundingSolidFeature",
|
||||
FeatureKind::Pipe { .. } => "PipeFeature",
|
||||
FeatureKind::FrameEndCap { .. } => "EndCapFeature",
|
||||
FeatureKind::FrameMember { .. } => "FrameMemberFeature",
|
||||
FeatureKind::Emboss { .. } => "EmbossFeature",
|
||||
FeatureKind::Boss { .. } => "BossFeature",
|
||||
@@ -2815,6 +2879,7 @@ impl FeatureKind {
|
||||
FeatureKind::DeleteFace { .. } => "delete_face",
|
||||
FeatureKind::BoundingSolid { .. } => "bounding_solid",
|
||||
FeatureKind::Pipe { .. } => "pipe",
|
||||
FeatureKind::FrameEndCap { .. } => "frame_end_cap",
|
||||
FeatureKind::FrameMember { .. } => "frame_member",
|
||||
FeatureKind::Emboss { .. } => "emboss",
|
||||
FeatureKind::Rib { .. } => "rib",
|
||||
@@ -2899,6 +2964,7 @@ impl FeatureKind {
|
||||
"OffsetSurfaceFeature" => "surface_offset",
|
||||
"BoundingSolidFeature" => "bounding_solid",
|
||||
"PipeFeature" => "pipe",
|
||||
"EndCapFeature" => "frame_end_cap",
|
||||
"FrameMemberFeature" => "frame_member",
|
||||
"EmbossFeature" => "emboss",
|
||||
"BossFeature" => "boss",
|
||||
@@ -2982,6 +3048,7 @@ impl FeatureKind {
|
||||
FeatureKind::SurfaceOffset { .. } => "OffsetSurface",
|
||||
FeatureKind::BoundingSolid { .. } => "BoundingSolid",
|
||||
FeatureKind::Pipe { .. } => "Pipe",
|
||||
FeatureKind::FrameEndCap { .. } => "EndCap",
|
||||
FeatureKind::FrameMember { .. } => "Member",
|
||||
FeatureKind::Emboss { .. } => "Emboss",
|
||||
FeatureKind::Boss { .. } => "Boss",
|
||||
@@ -4512,18 +4579,22 @@ impl Document {
|
||||
expr::eval_with(e, &|n| vals.get(n).copied().ok_or_else(|| DocError::Expr(format!("unknown parameter `{n}`"))))?.to_kind(kind)
|
||||
}
|
||||
|
||||
/// Resolve a plane reference.
|
||||
/// Resolve a plane reference (in the world: the root's frame).
|
||||
pub fn resolve_plane(&self, vals: &std::collections::BTreeMap<String, expr::Value>, p: &PlaneRef, depth: usize) -> Result<Plane> {
|
||||
self.resolve_plane_in(vals, p, depth, None)
|
||||
self.resolve_plane_in(vals, p, depth, 0, None)
|
||||
}
|
||||
|
||||
/// Resolve a plane; planes built from model geometry (edges, faces, construction axes and
|
||||
/// points) need the model state `st`, and construction planes are read from it when given.
|
||||
/// `component` is the frame the plane is read for: a component origin datum resolves as
|
||||
/// that component sees it ([`crate::construct::resolve_datum_in`]), since a feature places
|
||||
/// what it read into the world again through its own frame. The root (0) is the world.
|
||||
pub fn resolve_plane_in(
|
||||
&self,
|
||||
vals: &std::collections::BTreeMap<String, expr::Value>,
|
||||
p: &PlaneRef,
|
||||
depth: usize,
|
||||
component: u64,
|
||||
st: Option<&crate::ModelState>,
|
||||
) -> Result<Plane> {
|
||||
if depth > 32 {
|
||||
@@ -4543,17 +4614,21 @@ impl Document {
|
||||
}
|
||||
Plane::new(o, *x_dir, *y_dir).ok_or_else(|| DocError::Invalid("degenerate plane".into()))
|
||||
}
|
||||
PlaneRef::Datum { datum } => match crate::construct::resolve_datum_in(self, datum, component)? {
|
||||
crate::construct::ConstructGeom::Plane(p) => Ok(p),
|
||||
_ => Err(DocError::Invalid("the datum is not a plane (pick the XY, XZ or YZ of a component)".into())),
|
||||
},
|
||||
PlaneRef::Offset { base, distance } => {
|
||||
let b = self.resolve_plane_in(vals, base, depth + 1, st)?;
|
||||
let b = self.resolve_plane_in(vals, base, depth + 1, component, st)?;
|
||||
Ok(b.offset(Self::eval_in(vals, distance, Kind::Length)?))
|
||||
}
|
||||
PlaneRef::AtAngle { base, axis_origin, axis_dir, angle, line, direction_only, pivot } => {
|
||||
let b = self.resolve_plane_in(vals, base, depth + 1, st)?;
|
||||
let b = self.resolve_plane_in(vals, base, depth + 1, component, st)?;
|
||||
let a = Self::eval_in(vals, angle, Kind::Angle)?;
|
||||
let (axis_origin, axis_dir) = match line {
|
||||
Some(g) => {
|
||||
let st = st.ok_or_else(|| DocError::Invalid("this plane is built from the model: evaluate first".into()))?;
|
||||
crate::construct::model_axis(st, g)?
|
||||
crate::construct::model_axis_in(Some(self), st, g, component)?
|
||||
}
|
||||
None => (*axis_origin, *axis_dir),
|
||||
};
|
||||
@@ -4566,7 +4641,7 @@ impl Document {
|
||||
let pivot = match pivot {
|
||||
Some(g) => {
|
||||
let st = st.ok_or_else(|| DocError::Invalid("this plane is built from the model: evaluate first".into()))?;
|
||||
crate::construct::point(&crate::construct::Ctx { doc: self, vals, st, depth }, g)?
|
||||
crate::construct::point(&crate::construct::Ctx { doc: self, vals, st, depth, component }, g)?
|
||||
}
|
||||
None => b.origin,
|
||||
};
|
||||
@@ -4581,7 +4656,7 @@ impl Document {
|
||||
let o = axis_origin + rot(b.origin - axis_origin);
|
||||
Plane::new(o, rot(b.x), rot(b.y)).ok_or_else(|| DocError::Invalid("degenerate plane".into()))
|
||||
}
|
||||
PlaneRef::Flipped { base, about_y } => Ok(self.resolve_plane_in(vals, base, depth + 1, st)?.flipped(*about_y)),
|
||||
PlaneRef::Flipped { base, about_y } => Ok(self.resolve_plane_in(vals, base, depth + 1, component, st)?.flipped(*about_y)),
|
||||
PlaneRef::Construction { feature } => {
|
||||
// Evaluated already: as it came out.
|
||||
if let Some(c) = st.and_then(|st| st.construct.iter().find(|c| c.feature == feature.0))
|
||||
@@ -4590,7 +4665,7 @@ impl Document {
|
||||
return Ok(*pl);
|
||||
}
|
||||
match self.feature(feature.0).map(|f| &f.kind) {
|
||||
Some(FeatureKind::ConstructionPlane { plane }) => self.resolve_plane_in(vals, plane, depth + 1, st),
|
||||
Some(FeatureKind::ConstructionPlane { plane }) => self.resolve_plane_in(vals, plane, depth + 1, component, st),
|
||||
// A name that could not be resolved when an older design opened keeps id 0,
|
||||
// which no feature has (#1134): the reference dangles, as it always did.
|
||||
_ => {
|
||||
@@ -4608,7 +4683,7 @@ impl Document {
|
||||
| PlaneRef::Perpendicular { .. }
|
||||
| PlaneRef::ThroughPoint { .. } => {
|
||||
let st = st.ok_or_else(|| DocError::Invalid("this plane is built from the model: evaluate first".into()))?;
|
||||
crate::construct::resolve_geo_plane(&crate::construct::Ctx { doc: self, vals, st, depth }, p)
|
||||
crate::construct::resolve_geo_plane(&crate::construct::Ctx { doc: self, vals, st, depth, component }, p)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,582 @@
|
||||
//! End caps (#4003): a plate closing the open end of a frame member, its outline the member
|
||||
//! profile's outer outline set in from the edge, built from existing extrude and boolean
|
||||
//! operations.
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use crate::expr::{Kind, Value};
|
||||
use crate::{DocError, Document, Feature, FeatureKind, ModelBody, ModelState, PlaneRef, Result};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use solidcore_record::{Loop2, Plane, Region2, Seg2, Vec2};
|
||||
use solidcraft_geom::prelude::*;
|
||||
use solidcraft_kernel::{self as kernel, BoolOp};
|
||||
|
||||
/// Most end faces one end cap feature closes.
|
||||
pub const MAX_FACES: usize = 256;
|
||||
|
||||
/// The member a capped face belongs to: its feature and line, which outlive body renames.
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, solidcraft_derive::Walk)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Member {
|
||||
pub feature: crate::FeatureId,
|
||||
pub line: String,
|
||||
}
|
||||
|
||||
/// One capped end: the member's planar end face and the member it belongs to.
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, solidcraft_derive::Walk)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct End {
|
||||
pub plane: PlaneRef,
|
||||
pub member: Member,
|
||||
}
|
||||
|
||||
/// Which way the cap goes from the end face.
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize, solidcraft_derive::Walk)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum Direction {
|
||||
/// Past the end: the frame gets longer by the thickness.
|
||||
#[default]
|
||||
Outward,
|
||||
/// Into the member, which is cut back by the thickness: the frame keeps its length.
|
||||
Inward,
|
||||
}
|
||||
|
||||
fn invalid(s: impl Into<String>) -> DocError {
|
||||
DocError::Invalid(s.into())
|
||||
}
|
||||
|
||||
/// The member that `plane`'s face belongs to; an error when it is no frame member's face.
|
||||
pub fn member(doc: &Document, st: &ModelState, plane: &PlaneRef) -> Result<Member> {
|
||||
let PlaneRef::Face { anchor: Some(anchor), .. } = plane else { return Err(invalid("an end cap needs a planar face picked on a frame member")) };
|
||||
let source = doc.feature(anchor.target.origin_feature).ok_or_else(|| invalid("the capped member's feature no longer exists"))?;
|
||||
let FeatureKind::FrameMember { names, .. } = &source.kind else { return Err(invalid("the face is not on a frame member")) };
|
||||
let ids = crate::frame::member_line_ids(st, &source.kind)?;
|
||||
let line = if source.body_names.is_empty() {
|
||||
ids.iter().find(|line| names.get(*line).is_some_and(|name| *name == anchor.target.body))
|
||||
} else {
|
||||
source.body_names.iter().position(|name| *name == anchor.target.body).and_then(|i| ids.get(i))
|
||||
}
|
||||
.ok_or_else(|| invalid("the face is no longer on the member it was picked on"))?;
|
||||
Ok(Member { feature: source.id.into(), line: line.clone() })
|
||||
}
|
||||
|
||||
fn length(v: f64, what: &str, min: f64) -> Result<f64> {
|
||||
if !v.is_finite() || v > 1e6 || v < min {
|
||||
return Err(invalid(format!("the end cap's {what} must be a length from {min} to 1e6 mm")));
|
||||
}
|
||||
Ok(v)
|
||||
}
|
||||
|
||||
/// Most edges in an outline an end cap follows.
|
||||
const MAX_EDGES: usize = 4096;
|
||||
|
||||
/// Where a segment of the outline goes when it moves in: a line through a point along a unit
|
||||
/// direction, or a circle.
|
||||
#[derive(Clone, Copy)]
|
||||
enum Carrier {
|
||||
Line(Vec2, Vec2),
|
||||
Circle(Vec2, f64),
|
||||
}
|
||||
|
||||
/// The points where two carriers cross.
|
||||
fn crossings(c1: Carrier, c2: Carrier) -> Vec<Vec2> {
|
||||
match (c1, c2) {
|
||||
(Carrier::Line(p1, t1), Carrier::Line(p2, t2)) => {
|
||||
let den = t1.cross(t2);
|
||||
if den.abs() < 1e-9 { Vec::new() } else { vec![p1 + t1 * ((p2 - p1).cross(t2) / den)] }
|
||||
}
|
||||
(Carrier::Line(p, t), Carrier::Circle(c, r)) | (Carrier::Circle(c, r), Carrier::Line(p, t)) => {
|
||||
let foot = p + t * (c - p).dot(t);
|
||||
let h2 = r * r - (c - foot).dot(c - foot);
|
||||
if h2 < -1e-9 * r.max(1.0) {
|
||||
return Vec::new();
|
||||
}
|
||||
let h = h2.max(0.0).sqrt();
|
||||
vec![foot - t * h, foot + t * h]
|
||||
}
|
||||
(Carrier::Circle(c1, r1), Carrier::Circle(c2, r2)) => {
|
||||
let dd = c1.dist(c2);
|
||||
if dd < 1e-12 {
|
||||
return Vec::new();
|
||||
}
|
||||
let u = (c2 - c1) / dd;
|
||||
let along = (r1 * r1 - r2 * r2 + dd * dd) / (2.0 * dd);
|
||||
let h2 = r1 * r1 - along * along;
|
||||
if h2 < -1e-9 * r1.max(1.0) {
|
||||
return Vec::new();
|
||||
}
|
||||
let h = h2.max(0.0).sqrt();
|
||||
let foot = c1 + u * along;
|
||||
vec![foot - u.perp() * h, foot + u.perp() * h]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// How far `p` is from segment `s` (a line or an arc).
|
||||
fn distance(s: &Seg2, p: Vec2) -> f64 {
|
||||
match *s {
|
||||
Seg2::Line { a, b } => {
|
||||
let ab = b - a;
|
||||
let l2 = ab.dot(ab);
|
||||
let u = if l2 > 0.0 { ((p - a).dot(ab) / l2).clamp(0.0, 1.0) } else { 0.0 };
|
||||
p.dist(a + ab * u)
|
||||
}
|
||||
Seg2::Arc { center, radius, start, sweep } => {
|
||||
let tau = std::f64::consts::TAU;
|
||||
let rel = (p - center).angle() - start;
|
||||
let u = if sweep >= 0.0 { rel.rem_euclid(tau) } else { (-rel).rem_euclid(tau) };
|
||||
if u <= sweep.abs() { (p.dist(center) - radius).abs() } else { p.dist(s.start()).min(p.dist(s.end())) }
|
||||
}
|
||||
_ => p.dist(s.start()).min(p.dist(s.end())),
|
||||
}
|
||||
}
|
||||
|
||||
/// Points along `s`: a few on a line, more on an arc.
|
||||
fn samples(s: &Seg2) -> Vec<Vec2> {
|
||||
let k = match *s {
|
||||
Seg2::Arc { sweep, .. } => ((sweep.abs() / (std::f64::consts::PI / 32.0)).ceil() as usize).clamp(2, 128),
|
||||
_ => 8,
|
||||
};
|
||||
(0..=k).map(|i| s.point_at(i as f64 / k as f64)).collect()
|
||||
}
|
||||
|
||||
/// Whether two straight pieces cross (touching at their ends does not count).
|
||||
fn pieces_cross(a: Vec2, b: Vec2, c: Vec2, d: Vec2) -> bool {
|
||||
let (o1, o2) = ((b - a).cross(c - a), (b - a).cross(d - a));
|
||||
let (o3, o4) = ((d - c).cross(a - c), (d - c).cross(b - c));
|
||||
let eps = 1e-12 * (1.0 + a.dist(b) + c.dist(d)).powi(2);
|
||||
o1 * o2 < -eps && o3 * o4 < -eps
|
||||
}
|
||||
|
||||
/// Whether `lp`'s edges cross one another.
|
||||
fn crosses_itself(lp: &Loop2) -> bool {
|
||||
let pts: Vec<Vec2> = lp
|
||||
.segs
|
||||
.iter()
|
||||
.flat_map(|s| {
|
||||
let mut v = samples(s);
|
||||
v.pop();
|
||||
v
|
||||
})
|
||||
.collect();
|
||||
let n = pts.len();
|
||||
for i in 0..n {
|
||||
for j in i + 2..n {
|
||||
if i == 0 && j + 1 == n {
|
||||
continue;
|
||||
}
|
||||
let (Some(&a), Some(&b), Some(&c), Some(&d)) = (pts.get(i), pts.get((i + 1) % n), pts.get(j), pts.get((j + 1) % n)) else {
|
||||
continue;
|
||||
};
|
||||
if pieces_cross(a, b, c, d) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
/// `outline`, a counter-clockwise loop of lines and arcs, moved in by `d` all round: lines move
|
||||
/// along their inward normal, arcs that bulge out lose `d` of radius and arcs that curve in (the
|
||||
/// root of an angle or a beam) gain it. An arc that shrinks away leaves its neighbours meeting
|
||||
/// at a corner. Any shape works: round and rectangular tubes as well as angles, channels and
|
||||
/// beams. An inset more than half a wall somewhere (an angle's leg, a beam's web) is refused.
|
||||
pub(crate) fn inset(outline: &Loop2, d: f64) -> Result<Loop2> {
|
||||
let no_plate = || {
|
||||
invalid(format!(
|
||||
"an inset of {} mm leaves no plate inside the profile's outline (it is more than half a wall somewhere)",
|
||||
crate::frame::short(d)
|
||||
))
|
||||
};
|
||||
if !d.is_finite() || d < 0.0 {
|
||||
return Err(invalid("the end cap's inset must be a length of 0 or more"));
|
||||
}
|
||||
let segs = &outline.segs;
|
||||
let n = segs.len();
|
||||
if n == 0 || outline.signed_area() <= 0.0 {
|
||||
return Err(invalid("the profile's outline has no area"));
|
||||
}
|
||||
if n > MAX_EDGES {
|
||||
return Err(invalid(format!("end caps follow outlines of at most {MAX_EDGES} edges")));
|
||||
}
|
||||
// A full circle (arcs on one circle): its radius shrinks.
|
||||
if let Some(Seg2::Arc { center, radius, .. }) = segs.first().copied()
|
||||
&& segs
|
||||
.iter()
|
||||
.all(|s| matches!(*s, Seg2::Arc { center: c, radius: r, sweep, .. } if c.dist(center) < 1e-9 && (r - radius).abs() < 1e-9 && sweep > 0.0))
|
||||
{
|
||||
return if radius - d > 1e-6 { Ok(Loop2::circle(center, radius - d)) } else { Err(no_plate()) };
|
||||
}
|
||||
let mut carriers = Vec::with_capacity(n);
|
||||
for s in segs {
|
||||
carriers.push(match *s {
|
||||
Seg2::Line { a, b } => {
|
||||
let t = (b - a).normalized().ok_or_else(|| invalid("the profile's outline has an edge of no length"))?;
|
||||
Some(Carrier::Line(a + t.perp() * d, t))
|
||||
}
|
||||
// Counter-clockwise arcs bulge out and shrink; clockwise ones curve in and grow.
|
||||
Seg2::Arc { center, radius, sweep, .. } if sweep.abs() > 1e-12 && radius > 0.0 => {
|
||||
let r = radius - d * sweep.signum();
|
||||
(r > 1e-6).then_some(Carrier::Circle(center, r))
|
||||
}
|
||||
Seg2::Arc { .. } => return Err(invalid("the profile's outline has an arc of no length")),
|
||||
_ => return Err(invalid("end caps follow outlines of lines and arcs (a spline or conic outline is not supported)")),
|
||||
});
|
||||
}
|
||||
let kept: Vec<usize> = (0..n).filter(|i| carriers.get(*i).is_some_and(Option::is_some)).collect();
|
||||
let m = kept.len();
|
||||
if m < 2 {
|
||||
return Err(no_plate());
|
||||
}
|
||||
// Where kept segment `k` starts: after a smooth join, the old point moved in; otherwise (a
|
||||
// corner, or arcs shrunk away between) where it meets the previous kept segment, nearest the
|
||||
// corner it replaces.
|
||||
let mut starts = Vec::with_capacity(m);
|
||||
for (j, &k) in kept.iter().enumerate() {
|
||||
let p = kept.get((j + m - 1) % m).copied().ok_or_else(no_plate)?;
|
||||
let (Some(prev), Some(this)) = (segs.get(p), segs.get(k)) else { return Err(no_plate()) };
|
||||
let (tin, tout) = (prev.end_tangent(), this.start_tangent());
|
||||
if (p + 1) % n == k && tin.cross(tout).abs() < 1e-7 && tin.dot(tout) > 0.0 {
|
||||
starts.push(this.start() + tout.perp() * d);
|
||||
continue;
|
||||
}
|
||||
let (Some(Some(c1)), Some(Some(c2))) = (carriers.get(p).copied(), carriers.get(k).copied()) else { return Err(no_plate()) };
|
||||
let near = prev.end().lerp(this.start(), 0.5);
|
||||
let best = crossings(c1, c2).into_iter().min_by(|a, b| a.dist(near).total_cmp(&b.dist(near))).ok_or_else(no_plate)?;
|
||||
starts.push(best);
|
||||
}
|
||||
let mut out = Vec::with_capacity(m);
|
||||
for (j, &k) in kept.iter().enumerate() {
|
||||
let (Some(&a), Some(&b)) = (starts.get(j), starts.get((j + 1) % m)) else { return Err(no_plate()) };
|
||||
match (segs.get(k).copied(), carriers.get(k).copied()) {
|
||||
(Some(Seg2::Line { a: oa, b: ob }), _) => {
|
||||
if (b - a).dot(ob - oa) <= 1e-6 * oa.dist(ob) || a.dist(b) < 1e-6 {
|
||||
return Err(no_plate());
|
||||
}
|
||||
out.push(Seg2::Line { a, b });
|
||||
}
|
||||
(Some(Seg2::Arc { sweep, .. }), Some(Some(Carrier::Circle(center, r)))) => {
|
||||
let tau = std::f64::consts::TAU;
|
||||
let (s, e) = ((a - center).angle(), (b - center).angle());
|
||||
let sw = if sweep > 0.0 { (e - s).rem_euclid(tau) } else { -(s - e).rem_euclid(tau) };
|
||||
// An arc turned inside out shows as one sweeping most of the way round.
|
||||
if sw.abs() < 1e-9 || sw.abs() > sweep.abs() + std::f64::consts::FRAC_PI_2 {
|
||||
return Err(no_plate());
|
||||
}
|
||||
out.push(Seg2::Arc { center, radius: r, start: s, sweep: sw });
|
||||
}
|
||||
_ => return Err(no_plate()),
|
||||
}
|
||||
}
|
||||
let lp = Loop2 { segs: out };
|
||||
// Every point of the plate's edge is at least `d` from the profile's: closer means the inset
|
||||
// reached across a wall thinner than twice the inset.
|
||||
let tol = 1e-6 * (1.0 + d);
|
||||
let far_enough = lp.segs.iter().flat_map(samples).all(|q| segs.iter().map(|s| distance(s, q)).fold(f64::INFINITY, f64::min) >= d - tol);
|
||||
if !(lp.signed_area() > 1e-6) || !far_enough || crosses_itself(&lp) {
|
||||
return Err(no_plate());
|
||||
}
|
||||
Ok(lp)
|
||||
}
|
||||
|
||||
/// `outline` (as [`inset`] makes it) with every outside corner cut by a chamfer `c` long along
|
||||
/// each edge, measured from where the edges meet. A rounded corner is cut away whole, so `c`
|
||||
/// must be at least as long as its rounding. Inside corners (the root of an angle or a beam)
|
||||
/// stay as they are.
|
||||
pub(crate) fn chamfered(outline: &Loop2, c: f64) -> Result<Loop2> {
|
||||
if !c.is_finite() || c < 0.0 {
|
||||
return Err(invalid("the end cap's chamfer must be a length of 0 or more"));
|
||||
}
|
||||
if c == 0.0 {
|
||||
return Ok(outline.clone());
|
||||
}
|
||||
let segs = &outline.segs;
|
||||
let n = segs.len();
|
||||
let round = || invalid("a round end cap has no corners to chamfer (set the chamfer to 0)");
|
||||
// The lines in order from the first; an outline with none is round.
|
||||
let first = segs.iter().position(|s| matches!(s, Seg2::Line { .. })).ok_or_else(round)?;
|
||||
let lines: Vec<usize> = (0..n).map(|i| (first + i) % n).filter(|i| matches!(segs.get(*i), Some(Seg2::Line { .. }))).collect();
|
||||
let k = lines.len();
|
||||
if k < 2 {
|
||||
return Err(round());
|
||||
}
|
||||
let line = |i: usize| -> Result<(Vec2, Vec2, Vec2)> {
|
||||
match lines.get(i % k).and_then(|j| segs.get(*j)).copied() {
|
||||
Some(Seg2::Line { a, b }) => Ok((a, b, (b - a).normalized().ok_or_else(|| invalid("the end cap's outline has an edge of no length"))?)),
|
||||
_ => Err(invalid("the end cap's outline lost an edge")),
|
||||
}
|
||||
};
|
||||
// The segments between line `i` and the next line.
|
||||
let between = |i: usize| -> Vec<Seg2> {
|
||||
let (Some(&a), Some(&b)) = (lines.get(i % k), lines.get((i + 1) % k)) else { return Vec::new() };
|
||||
let count = (b + n - a - 1) % n;
|
||||
(1..=count).filter_map(|o| segs.get((a + o) % n).copied()).collect()
|
||||
};
|
||||
// Each line's corner at its end, where chamfered: an outside corner, sharp or rounded by arcs
|
||||
// that bulge out.
|
||||
let mut corners = Vec::with_capacity(k);
|
||||
for i in 0..k {
|
||||
let (a1, b1, t1) = line(i)?;
|
||||
let (a2, _, t2) = line(i + 1)?;
|
||||
let den = t1.cross(t2);
|
||||
let outside = den > 1e-9 && between(i).iter().all(|s| matches!(*s, Seg2::Arc { sweep, .. } if sweep > 0.0));
|
||||
if !outside {
|
||||
corners.push(None);
|
||||
continue;
|
||||
}
|
||||
let v = a1 + t1 * ((a2 - a1).cross(t2) / den);
|
||||
let setback = v.dist(b1).max(v.dist(a2));
|
||||
if c + 1e-9 < setback {
|
||||
return Err(invalid(format!(
|
||||
"the chamfer must be at least the corner rounding it cuts away ({} mm), or 0",
|
||||
crate::frame::short(setback)
|
||||
)));
|
||||
}
|
||||
corners.push(Some((v - t1 * c, v + t2 * c)));
|
||||
}
|
||||
if corners.iter().all(Option::is_none) {
|
||||
return Err(invalid("the end cap has no outside corners to chamfer (set the chamfer to 0)"));
|
||||
}
|
||||
let too_large = || invalid("the chamfer is too large for the end cap's edges");
|
||||
let mut out = Vec::with_capacity(2 * n);
|
||||
for i in 0..k {
|
||||
let (a, b, t) = line(i)?;
|
||||
let start = match corners.get((i + k - 1) % k) {
|
||||
Some(Some((_, s))) => *s,
|
||||
_ => a,
|
||||
};
|
||||
let end = match corners.get(i) {
|
||||
Some(Some((e, _))) => *e,
|
||||
_ => b,
|
||||
};
|
||||
if (end - start).dot(t) <= 1e-6 {
|
||||
return Err(too_large());
|
||||
}
|
||||
out.push(Seg2::Line { a: start, b: end });
|
||||
match corners.get(i) {
|
||||
Some(Some((e, s))) => out.push(Seg2::Line { a: *e, b: *s }),
|
||||
_ => out.extend(between(i)),
|
||||
}
|
||||
}
|
||||
let lp = Loop2 { segs: out };
|
||||
if !(lp.signed_area() > 1e-6) || crosses_itself(&lp) {
|
||||
return Err(too_large());
|
||||
}
|
||||
Ok(lp)
|
||||
}
|
||||
|
||||
/// A free body name for the cap on `member`: `<member> End Cap`, then `… (2)`, `… (3)`…
|
||||
fn cap_name(st: &mut ModelState, f: &Feature, k: usize, member: &str) -> String {
|
||||
if f.body_names.get(k).is_some_and(|n| !n.is_empty()) {
|
||||
return crate::eval::new_name(st, f, k);
|
||||
}
|
||||
let base = format!("{member} End Cap");
|
||||
// Not a name the design keeps for a suppressed feature or a rename (#4302, #4957): a cap
|
||||
// made while another is suppressed must not take that one's name. Nor one another end of
|
||||
// this cap has stored, which is built after this one when an end is added before it.
|
||||
let tries = st.bodies.len() + st.reserved_body_names.len() + f.body_names.len() + 2;
|
||||
(1..=tries)
|
||||
.map(|i| if i == 1 { base.clone() } else { format!("{base} ({i})") })
|
||||
.find(|n| st.body(n).is_none() && !st.reserved_body_names.contains(n) && !f.body_names.contains(n))
|
||||
.unwrap_or(base)
|
||||
}
|
||||
|
||||
/// A capped end, worked out before any body changes.
|
||||
struct Planned {
|
||||
body: String,
|
||||
plane: Plane,
|
||||
region: Region2,
|
||||
/// The cap's extent along the plane's normal, and the slab cut from an inward cap's member.
|
||||
cap: (f64, f64),
|
||||
cut: Option<(Region2, f64, f64)>,
|
||||
/// The cap's frame to the member body's own: the cap is authored in this feature's frame, the
|
||||
/// member is stored in its component's (moved by its body offset), and the cut is made there.
|
||||
to_member: crate::Mat,
|
||||
}
|
||||
|
||||
pub(crate) fn evaluate(doc: &Document, vals: &BTreeMap<String, Value>, f: &Feature, st: &mut ModelState) -> Result<()> {
|
||||
let FeatureKind::FrameEndCap { ends, thickness, offset, ratio, chamfer, direction } = &f.kind else {
|
||||
return Err(invalid("not an end cap"));
|
||||
};
|
||||
if ends.is_empty() {
|
||||
return Err(invalid("pick at least one open end face of a frame member"));
|
||||
}
|
||||
if ends.len() > MAX_FACES {
|
||||
return Err(invalid(format!("at most {MAX_FACES} end faces in one end cap feature")));
|
||||
}
|
||||
let t = length(crate::eval::val(vals, thickness, Kind::Length)?, "thickness", 0.01)?;
|
||||
let d = match (offset, ratio) {
|
||||
(Some(e), None) => length(crate::eval::val(vals, e, Kind::Length)?, "inset", 0.0)?,
|
||||
(None, Some(e)) => {
|
||||
let r = crate::eval::val(vals, e, Kind::Unitless)?;
|
||||
if !r.is_finite() || !(0.0..=1000.0).contains(&r) {
|
||||
return Err(invalid("the end cap's inset ratio must be from 0 to 1000 times the thickness"));
|
||||
}
|
||||
r * t
|
||||
}
|
||||
// Neither: flush with the outside of the profile.
|
||||
(None, None) => 0.0,
|
||||
_ => return Err(invalid("give the end cap's inset as either a length or a ratio of the thickness, not both")),
|
||||
};
|
||||
let c = length(crate::eval::val(vals, chamfer, Kind::Length)?, "chamfer", 0.0)?;
|
||||
let mut planned = Vec::with_capacity(ends.len());
|
||||
for end in ends {
|
||||
let PlaneRef::Face { anchor: Some(anchor), .. } = &end.plane else {
|
||||
return Err(invalid("an end cap needs a planar face picked on a frame member"));
|
||||
};
|
||||
if member(doc, st, &end.plane)? != end.member {
|
||||
return Err(invalid("the capped face is no longer on the member it was picked on"));
|
||||
}
|
||||
let face = doc.resolve_face_anchor(anchor, f.component, st).map_err(|e| invalid(format!("the capped end face: {e}")))?;
|
||||
let body = st.body(&anchor.target.body).ok_or_else(|| invalid("the capped member's body no longer exists"))?;
|
||||
let source = doc.feature(end.member.feature.0).ok_or_else(|| invalid("the capped member's feature no longer exists"))?;
|
||||
let (section, len, region) = crate::eval::frame_member::member_section(doc, vals, source, st, &end.member.line)?;
|
||||
let to_author = anchor.source_to_author(doc, f.component, body)?;
|
||||
let section = Plane::new(
|
||||
crate::apply_point(&to_author, section.origin),
|
||||
crate::apply_vector(&to_author, section.x),
|
||||
crate::apply_vector(&to_author, section.y),
|
||||
)
|
||||
.ok_or_else(|| invalid("the member's placement is degenerate"))?;
|
||||
let along = section.normal();
|
||||
let facing = face.normal().dot(along);
|
||||
if facing.abs() < 1.0 - 1e-7 {
|
||||
return Err(invalid("the picked face is not an end of the member (it is not square to the member's line)"));
|
||||
}
|
||||
let plane = Plane::new(section.origin + along * (face.origin - section.origin).dot(along), section.x, section.y)
|
||||
.ok_or_else(|| invalid("the end face's plane is degenerate"))?;
|
||||
// The same end, however it was picked (another point on its face, another anchor): the
|
||||
// same body with an earlier cap on this exact end plane.
|
||||
let same_end = |p: &Planned| {
|
||||
p.body == anchor.target.body && p.plane.origin.dist(plane.origin) < 1e-6 && p.plane.normal().dot(plane.normal()).abs() > 1.0 - 1e-9
|
||||
};
|
||||
if planned.iter().any(same_end) {
|
||||
return Err(invalid("an end face is picked twice"));
|
||||
}
|
||||
let outline = chamfered(&inset(&cap_outline(®ion.outer), d)?, c)?;
|
||||
let cap_region = Region2 { outer: outline, holes: Vec::new() };
|
||||
// Along the plane's normal: the member lies behind an end facing that way.
|
||||
let s = facing.signum();
|
||||
let (cap, cut) = match direction {
|
||||
Direction::Outward => (if s > 0.0 { (0.0, t) } else { (-t, 0.0) }, None),
|
||||
Direction::Inward => {
|
||||
if t >= len - 1e-3 {
|
||||
return Err(invalid(format!("an inward end cap {} mm thick needs a longer member", crate::frame::short(t))));
|
||||
}
|
||||
// A slab wider than the profile and past the end, so no face of it lies on the
|
||||
// member's.
|
||||
let bb = region.outer.polyline(1e-3).bounds();
|
||||
let m = 1.0 + 0.01 * (bb.max - bb.min).len();
|
||||
let (lo, hi) = (bb.min - Vec2::new(m, m), bb.max + Vec2::new(m, m));
|
||||
let slab = Region2 { outer: Loop2::polygon(&[lo, Vec2::new(hi.x, lo.y), hi, Vec2::new(lo.x, hi.y)]), holes: Vec::new() };
|
||||
let (a, b) = if s > 0.0 { (-t, m) } else { (-m, t) };
|
||||
(if s > 0.0 { (-t, 0.0) } else { (0.0, t) }, Some((slab, a, b)))
|
||||
}
|
||||
};
|
||||
let to_member = crate::mat_inverse(&to_author).ok_or_else(|| invalid("the member's placement is degenerate"))?;
|
||||
planned.push(Planned { body: anchor.target.body.clone(), plane, region: cap_region, cap, cut, to_member });
|
||||
}
|
||||
for (k, p) in planned.into_iter().enumerate() {
|
||||
if let Some((slab, a, b)) = &p.cut {
|
||||
let i = st.bodies.iter().position(|b| b.name == p.body).ok_or_else(|| invalid("the capped member's body no longer exists"))?;
|
||||
let mb = st.bodies.get(i).cloned().ok_or_else(|| invalid("the capped member's body no longer exists"))?;
|
||||
let at = Plane::new(
|
||||
crate::apply_point(&p.to_member, p.plane.origin),
|
||||
crate::apply_vector(&p.to_member, p.plane.x),
|
||||
crate::apply_vector(&p.to_member, p.plane.y),
|
||||
)
|
||||
.ok_or_else(|| invalid("the member's placement is degenerate"))?;
|
||||
let tool = one(kernel::extrude(&at, std::slice::from_ref(slab), *a, *b)?)?;
|
||||
let tool = crate::lineage::numbered_tool(tool);
|
||||
let cut = kernel::boolean(&mb.body, &tool.body, BoolOp::Cut)?
|
||||
.ok_or_else(|| invalid("cutting the member back for an inward end cap left nothing"))?;
|
||||
let cut = crate::lineage::Traced::step(cut, &[&mb.traced(), &tool]);
|
||||
if let Some(slot) = st.bodies.get_mut(i) {
|
||||
*slot = ModelBody::traced_new(mb.name, cut, mb.feature);
|
||||
}
|
||||
}
|
||||
let body = one(kernel::extrude(&p.plane, std::slice::from_ref(&p.region), p.cap.0, p.cap.1)?)?;
|
||||
let name = cap_name(st, f, k, &p.body);
|
||||
st.bodies.push(ModelBody::traced_new(name, crate::lineage::numbered_tool(body), f.id));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// The outline an end cap is cut from: the outside of the profile. A closed section (a tube, a
|
||||
/// pipe, a bar) keeps its own outline. An open section that turns inward somewhere (an angle, a
|
||||
/// channel, a beam, an extrusion with slots) keeps the edges on its bounding rectangle and the
|
||||
/// rounds and chamfers turning between them, and bridges each inward stretch along the
|
||||
/// rectangle, so the plate closes the whole end with the profile's own outside corners.
|
||||
pub(crate) fn cap_outline(outer: &Loop2) -> Loop2 {
|
||||
let ring = outer.polyline(1e-3);
|
||||
let convex = ring.corners().all(|(p, c, n)| (*c - *p).cross(*n - *c) >= -1e-9);
|
||||
if convex {
|
||||
return outer.clone();
|
||||
}
|
||||
let bb = ring.bounds();
|
||||
let rect = Loop2::polygon(&[bb.min, Vec2::new(bb.max.x, bb.min.y), bb.max, Vec2::new(bb.min.x, bb.max.y)]);
|
||||
let tol = 1e-6 * (1.0 + bb.max.dist(bb.min));
|
||||
// How far a point is off each side of the rectangle (0 bottom, 1 right, 2 top, 3 left,
|
||||
// counter-clockwise); a line lies on a side when both its ends do.
|
||||
let off = |q: Vec2| [(q.y - bb.min.y).abs(), (q.x - bb.max.x).abs(), (q.y - bb.max.y).abs(), (q.x - bb.min.x).abs()];
|
||||
let on_side = |s: &Seg2| match *s {
|
||||
Seg2::Line { a, b } => (0..4).find(|i| off(a).get(*i).is_some_and(|e| *e < tol) && off(b).get(*i).is_some_and(|e| *e < tol)),
|
||||
_ => None,
|
||||
};
|
||||
let segs = &outer.segs;
|
||||
let n = segs.len();
|
||||
let sides: Vec<Option<usize>> = segs.iter().map(on_side).collect();
|
||||
let Some(first) = sides.iter().position(Option::is_some) else { return rect };
|
||||
let corner = |i: usize| [Vec2::new(bb.max.x, bb.min.y), bb.max, Vec2::new(bb.min.x, bb.max.y), bb.min].get(i % 4).copied();
|
||||
let mut out: Vec<Seg2> = Vec::with_capacity(n + 4);
|
||||
let mut i = first;
|
||||
for _ in 0..n {
|
||||
let (Some(&seg), Some(&Some(si))) = (segs.get(i), sides.get(i)) else { return rect };
|
||||
out.push(seg);
|
||||
// The stretch up to the next edge on the rectangle.
|
||||
let mut j = (i + 1) % n;
|
||||
let mut run = Vec::new();
|
||||
while sides.get(j).is_some_and(Option::is_none) {
|
||||
run.push(j);
|
||||
j = (j + 1) % n;
|
||||
}
|
||||
let (Some(&next), Some(&Some(sj))) = (segs.get(j), sides.get(j)) else { return rect };
|
||||
// Kept when it only turns outward from one side to the next: a round or a chamfer.
|
||||
let mut chain = vec![seg];
|
||||
chain.extend(run.iter().filter_map(|k| segs.get(*k).copied()));
|
||||
chain.push(next);
|
||||
let turns_out = chain.windows(2).all(|w| matches!(w, [a, b] if a.end_tangent().cross(b.start_tangent()) >= -1e-9))
|
||||
&& chain.iter().all(|s| !matches!(*s, Seg2::Arc { sweep, .. } if sweep < 0.0));
|
||||
if !run.is_empty() && turns_out && sj == (si + 1) % 4 {
|
||||
out.extend(run.iter().filter_map(|k| segs.get(*k).copied()));
|
||||
} else if !run.is_empty() || seg.end().dist(next.start()) > tol {
|
||||
// Along the rectangle from this side round to the next one's.
|
||||
let mut p = seg.end();
|
||||
let steps = (sj + 4 - si) % 4;
|
||||
let steps = if steps == 0 && (next.start() - p).dot(corner(si).unwrap_or(p) - p) < 0.0 { 4 } else { steps };
|
||||
for k in 0..steps {
|
||||
let Some(c) = corner(si + k) else { return rect };
|
||||
if p.dist(c) > tol {
|
||||
out.push(Seg2::Line { a: p, b: c });
|
||||
}
|
||||
p = c;
|
||||
}
|
||||
if p.dist(next.start()) > tol {
|
||||
out.push(Seg2::Line { a: p, b: next.start() });
|
||||
}
|
||||
}
|
||||
if j == first {
|
||||
break;
|
||||
}
|
||||
i = j;
|
||||
}
|
||||
let lp = Loop2 { segs: out };
|
||||
if lp.signed_area() > 0.0 && lp.is_closed(tol) && !crosses_itself(&lp) { lp } else { rect }
|
||||
}
|
||||
|
||||
fn one(mut bodies: Vec<solidcraft_kernel::Body>) -> Result<solidcraft_kernel::Body> {
|
||||
let body = bodies.pop().ok_or_else(|| invalid("the end cap is not one solid"))?;
|
||||
if !bodies.is_empty() {
|
||||
return Err(invalid("the end cap is not one solid"));
|
||||
}
|
||||
Ok(body)
|
||||
}
|
||||
+932
-405
File diff suppressed because it is too large
Load Diff
@@ -132,8 +132,8 @@ fn joint_face_measurements_are_shared_across_motion_samples_and_snap_kinds() {
|
||||
id: 100,
|
||||
name: "Pivot".into(),
|
||||
kind: JointKind::Revolute,
|
||||
a: JointOrigin { occurrence: 0, snap: Snap::Frame { origin: pick, z: Vec3::Z, x: Some(Vec3::X) } },
|
||||
b: JointOrigin { occurrence, snap: Snap::FaceCenter { pick, face: None, x: Some(XRef::Dir(Vec3::X)) } },
|
||||
a: JointOrigin::new(0, Snap::Frame { origin: pick, z: Vec3::Z, x: Some(Vec3::X) }),
|
||||
b: JointOrigin::new(occurrence, Snap::FaceCenter { pick, face: None, x: Some(XRef::Dir(Vec3::X)) }),
|
||||
values: vec![0.0],
|
||||
limits: Vec::new(),
|
||||
flip: true,
|
||||
@@ -181,7 +181,7 @@ fn joint_face_measurements_never_follow_a_replaced_body_or_stale_offset() {
|
||||
let mut doc = Document::new("replaced joint geometry");
|
||||
let mut state = ModelState::default();
|
||||
state.bodies.push(ModelBody::new("Pin".into(), kernel::cylinder(Vec3::ZERO, Vec3::Z, 2.0, 10.0).unwrap(), 0));
|
||||
let origin = JointOrigin { occurrence: 0, snap: Snap::FaceCenter { pick: Vec3::new(0.0, 0.0, 10.0), face: None, x: None } };
|
||||
let origin = JointOrigin::new(0, Snap::FaceCenter { pick: Vec3::new(0.0, 0.0, 10.0), face: None, x: None });
|
||||
let work = counted(|| {
|
||||
joints::resolve_origin(&doc, &state, &origin).unwrap();
|
||||
});
|
||||
@@ -210,7 +210,7 @@ fn an_edge_origin_measures_its_faces_once() {
|
||||
let mut state = ModelState::default();
|
||||
state.bodies.push(ModelBody::new("Block".into(), kernel::box_solid(Vec3::ZERO, Vec3::new(10.0, 10.0, 10.0)).unwrap(), 0));
|
||||
let pick = Vec3::new(5.0, 0.0, 10.0);
|
||||
let origin = JointOrigin { occurrence: 0, snap: Snap::Edge { pick, edge: None, face: None, corner: None, axis: None } };
|
||||
let origin = JointOrigin::new(0, Snap::Edge { pick, edge: None, face: None, corner: None, axis: None });
|
||||
let work = counted(|| {
|
||||
for _ in 0..8 {
|
||||
let frame = joints::resolve_origin(&doc, &state.clone(), &origin).unwrap();
|
||||
@@ -1412,6 +1412,7 @@ fn marking(p: Vec3) -> FeatureKind {
|
||||
chamfer_angle: None,
|
||||
chamfer_depth: None,
|
||||
steep_flank: Default::default(),
|
||||
continuous_flanks: false,
|
||||
old_auto_size: false,
|
||||
}
|
||||
}
|
||||
@@ -1999,3 +2000,21 @@ fn a_hole_classifies_the_faces_it_reads_not_every_face_of_the_design() {
|
||||
let side = super::hole_direction_at(&st, Vec3::new(252.0, 0.0, 5.0), &[]).unwrap();
|
||||
assert!((side - Vec3::new(-1.0, 0.0, 0.0)).len() < 1e-6, "into the side wall: {side:?}");
|
||||
}
|
||||
|
||||
/// A hole's look at the material over its entry face (#10695) is best effort: when the kernel
|
||||
/// cannot build the run-on's column (here a column of no width), the hole keeps its full run-on
|
||||
/// and cuts nothing out of its tools, as before the check, instead of failing.
|
||||
#[test]
|
||||
fn a_hole_whose_run_on_column_cannot_be_built_keeps_its_run_on() {
|
||||
let mut state = ModelState::default();
|
||||
state.bodies.push(ModelBody::new("Over".into(), kernel::box_solid(Vec3::new(-5.0, -5.0, 0.5), Vec3::new(5.0, 5.0, 2.0)).unwrap(), 0));
|
||||
for reach in [0.0, f64::NAN] {
|
||||
let (top, near) = super::hole_run_on(&state, &Plane::XY, reach, 1.0);
|
||||
assert_eq!(top, 1.0, "reach {reach}");
|
||||
assert!(near.is_empty(), "reach {reach}");
|
||||
}
|
||||
// With a column, the body 0.5 over the face halves the run-on to its gap.
|
||||
let (top, near) = super::hole_run_on(&state, &Plane::XY, 3.0, 1.0);
|
||||
assert!((top - 0.25).abs() < 1e-6, "top {top}");
|
||||
assert!(near.is_empty());
|
||||
}
|
||||
|
||||
@@ -25,23 +25,10 @@ const STRAIGHT_TOL: f64 = 1e-3;
|
||||
/// Evaluate a `FrameMember` feature: one new body per line, each named
|
||||
/// ([`member_names`], or by position for a copy whose `body_names` were set).
|
||||
pub(super) fn evaluate(doc: &Document, vals: &BTreeMap<String, Value>, f: &Feature, st: &mut ModelState) -> Result<()> {
|
||||
let FeatureKind::FrameMember { path_sketch, lines, profile, anchor, angle, mirror, body_name, names } = &f.kind else {
|
||||
let FeatureKind::FrameMember { body_name, names, .. } = &f.kind else {
|
||||
return Err(DocError::Invalid("not a frame member feature".into()));
|
||||
};
|
||||
let ps = st.sketch(path_sketch.0).ok_or_else(|| DocError::Unknown(format!("sketch {path_sketch} (it must come earlier in the timeline)")))?;
|
||||
// The frame sketch in this feature's component frame: its plane, and its 3D lines.
|
||||
let mapped =
|
||||
if ps.sketch.wires.is_empty() { Cow::Owned(sketch_in_feature_frame(doc, ps, f.component)?) } else { path_in_frame(doc, ps, f.component)? };
|
||||
let segments = member_lines(mapped.as_ref(), lines)?;
|
||||
let (mut regions, description) = profile_regions(vals, st, profile)?;
|
||||
if *mirror {
|
||||
regions = regions.iter().map(frame::mirrored).collect();
|
||||
}
|
||||
let at = frame::anchor_point(®ions, *anchor);
|
||||
let turn = match angle {
|
||||
Some(e) => val(vals, e, Kind::Angle)?,
|
||||
None => 0.0,
|
||||
};
|
||||
let Layout { segments, regions, description, at, turn } = layout(doc, vals, f, st)?;
|
||||
let mut made = Vec::with_capacity(segments.len());
|
||||
for (id, a, b) in &segments {
|
||||
let (x, y) = frame::member_axes(*b - *a, turn).ok_or_else(|| DocError::Invalid(format!("line `{id}` has no length")))?;
|
||||
@@ -70,6 +57,54 @@ pub(super) fn evaluate(doc: &Document, vals: &BTreeMap<String, Value>, f: &Featu
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// A member feature's lines (in its component frame), profile regions, default name, the
|
||||
/// profile point that sits on the lines and the profile's turn about them.
|
||||
struct Layout {
|
||||
segments: Vec<(String, Vec3, Vec3)>,
|
||||
regions: Vec<Region2>,
|
||||
description: String,
|
||||
at: Vec2,
|
||||
turn: f64,
|
||||
}
|
||||
|
||||
fn layout(doc: &Document, vals: &BTreeMap<String, Value>, f: &Feature, st: &ModelState) -> Result<Layout> {
|
||||
let FeatureKind::FrameMember { path_sketch, lines, profile, anchor, angle, mirror, .. } = &f.kind else {
|
||||
return Err(DocError::Invalid("not a frame member feature".into()));
|
||||
};
|
||||
let ps = st.sketch(path_sketch.0).ok_or_else(|| DocError::Unknown(format!("sketch {path_sketch} (it must come earlier in the timeline)")))?;
|
||||
// The frame sketch in this feature's component frame: its plane, and its 3D lines.
|
||||
let mapped =
|
||||
if ps.sketch.wires.is_empty() { Cow::Owned(sketch_in_feature_frame(doc, ps, f.component)?) } else { path_in_frame(doc, ps, f.component)? };
|
||||
let segments = member_lines(mapped.as_ref(), lines)?;
|
||||
let (mut regions, description) = profile_regions(vals, st, profile)?;
|
||||
if *mirror {
|
||||
regions = regions.iter().map(frame::mirrored).collect();
|
||||
}
|
||||
let at = frame::anchor_point(®ions, *anchor);
|
||||
let turn = match angle {
|
||||
Some(e) => val(vals, e, Kind::Angle)?,
|
||||
None => 0.0,
|
||||
};
|
||||
Ok(Layout { segments, regions, description, at, turn })
|
||||
}
|
||||
|
||||
/// The member of feature `f` on line `line`, as its body was made: the plane square to the line
|
||||
/// at its start (x × y along the line), its length, and its profile in that plane.
|
||||
pub(crate) fn member_section(
|
||||
doc: &Document,
|
||||
vals: &BTreeMap<String, Value>,
|
||||
f: &Feature,
|
||||
st: &ModelState,
|
||||
line: &str,
|
||||
) -> Result<(Plane, f64, Region2)> {
|
||||
let Layout { segments, regions, at, turn, .. } = layout(doc, vals, f, st)?;
|
||||
let (_, a, b) = segments.iter().find(|(id, _, _)| id == line).ok_or_else(|| DocError::Unknown(format!("line `{line}` of the member feature")))?;
|
||||
let (x, y) = frame::member_axes(*b - *a, turn).ok_or_else(|| DocError::Invalid(format!("line `{line}` has no length")))?;
|
||||
let plane = Plane::new(*a - x * at.x - y * at.y, x, y).ok_or_else(|| DocError::Invalid(format!("line `{line}`: no plane square to it")))?;
|
||||
let region = regions.into_iter().next().ok_or_else(|| DocError::Invalid("the member profile has no area".into()))?;
|
||||
Ok((plane, a.dist(*b), region))
|
||||
}
|
||||
|
||||
/// The body name of the member on each of `lines`: its own name from `pinned` (by line id) when no
|
||||
/// other body has it, else the first free one of `base`, `base (2)`, `base (3)`… that no line has
|
||||
/// pinned. A member therefore keeps its name when other lines are added, deleted or reordered.
|
||||
|
||||
@@ -79,7 +79,7 @@ pub(super) fn eval(doc: &Document, vals: &BTreeMap<String, Value>, f: &Feature,
|
||||
apply_op(doc, st, f, tools, Operation::Join, &[])
|
||||
}
|
||||
FeatureKind::ReplaceFace { faces, target, body } => {
|
||||
let tp = doc.resolve_plane_in(vals, target, 0, Some(st))?;
|
||||
let tp = doc.resolve_plane_in(vals, target, 0, f.component, Some(st))?;
|
||||
let tn = tp.normal();
|
||||
let i = body_at(st, body, &crate::plain(faces))?;
|
||||
let Some(mb) = st.bodies.get(i).cloned() else { return Err(DocError::Invalid("body".into())) };
|
||||
@@ -106,7 +106,7 @@ pub(super) fn eval(doc: &Document, vals: &BTreeMap<String, Value>, f: &Feature,
|
||||
// A plane on either side is worked out now, so the bodies follow it when it moves.
|
||||
let (mut from, mut from_normal) = (from.0, from_normal.and_then(|n| n.normalized()));
|
||||
if let Some(p) = from_plane {
|
||||
let pl = doc.resolve_plane_in(vals, p, 0, Some(&*st))?;
|
||||
let pl = doc.resolve_plane_in(vals, p, 0, f.component, Some(&*st))?;
|
||||
(from, from_normal) = (pl.origin, Some(pl.normal()));
|
||||
}
|
||||
// So is a frame (#6257): its origin and z, found again from the geometry.
|
||||
@@ -116,7 +116,7 @@ pub(super) fn eval(doc: &Document, vals: &BTreeMap<String, Value>, f: &Feature,
|
||||
}
|
||||
let target = match to_frame {
|
||||
Some(_) => None,
|
||||
None => to_plane.as_ref().map(|p| doc.resolve_plane_in(vals, p, 0, Some(&*st))).transpose()?,
|
||||
None => to_plane.as_ref().map(|p| doc.resolve_plane_in(vals, p, 0, f.component, Some(&*st))).transpose()?,
|
||||
};
|
||||
let (to, to_normal) = match (to_frame, &target) {
|
||||
(Some(fr), _) => fr.resolve(doc, st).map(|(o, z)| (o, Some(z)))?,
|
||||
|
||||
@@ -0,0 +1,264 @@
|
||||
//! SMLib's check of a feature's bodies beside the features after it.
|
||||
//!
|
||||
//! Under [`kernel::Validation::EachFeature`] a feature ends with SMLib's full check of the bodies
|
||||
//! it keeps, and the next feature used to wait for it: a third to a half of an evaluation went to
|
||||
//! those checks, on one core. [`Checks`] detaches each check from the bodies it reads
|
||||
//! ([`kernel::detach_kept`]) and runs it on a thread of its own while the evaluation goes on. What the features after it produce stands only once it passes: their
|
||||
//! cache entries are held until then, and a refusal takes the evaluation back to the refused
|
||||
//! feature, which then fails with the check's error and warnings, as it did when the check ran
|
||||
//! in line. The results are the same either way; only the time differs.
|
||||
|
||||
use std::collections::{HashMap, VecDeque};
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use solidcraft_kernel as kernel;
|
||||
|
||||
use super::{CachedEval, EvalCache, FeatureResult, KeptSlot, ModelBody, ModelState};
|
||||
|
||||
/// The evaluation's loop state just before a feature was evaluated: what a refusal of its check
|
||||
/// puts back before evaluating it again.
|
||||
pub(super) struct Saved {
|
||||
pub state: Arc<ModelState>,
|
||||
pub reserved: std::collections::BTreeSet<String>,
|
||||
pub out_len: usize,
|
||||
pub reuse: bool,
|
||||
pub prev_fp: u64,
|
||||
pub recomputed: usize,
|
||||
pub restored: usize,
|
||||
pub poses: HashMap<u64, u64>,
|
||||
pub moved: Vec<(u64, Vec<ModelBody>)>,
|
||||
pub failed: HashMap<u64, (String, String)>,
|
||||
pub rolled_results: HashMap<u64, (u64, FeatureResult)>,
|
||||
}
|
||||
|
||||
/// How a feature whose check refused its bodies ends: as the check in line ended it.
|
||||
#[derive(Clone)]
|
||||
pub(super) struct Failure {
|
||||
pub error: kernel::KernelError,
|
||||
pub warning: Option<String>,
|
||||
pub import_report: Option<Arc<kernel::ImportReport>>,
|
||||
pub repair: Option<Arc<kernel::RepairReport>>,
|
||||
pub ms: f64,
|
||||
}
|
||||
|
||||
/// A check that refused feature `index`'s bodies.
|
||||
pub(super) struct Refused {
|
||||
pub index: usize,
|
||||
pub saved: Saved,
|
||||
pub failure: Failure,
|
||||
}
|
||||
|
||||
struct Running {
|
||||
index: usize,
|
||||
saved: Saved,
|
||||
failure: Failure,
|
||||
done: std::thread::JoinHandle<kernel::Result<()>>,
|
||||
}
|
||||
|
||||
pub(super) struct Checks {
|
||||
on: bool,
|
||||
/// Most checks running at once: the cores beside the evaluation's own.
|
||||
most: usize,
|
||||
running: VecDeque<Running>,
|
||||
/// Cache entries of features evaluated after a check that is still running, in order.
|
||||
held: Vec<(usize, u64, CachedEval)>,
|
||||
/// Features whose check refused their bodies, to fail again as it did.
|
||||
refused: HashMap<usize, Failure>,
|
||||
}
|
||||
|
||||
impl Checks {
|
||||
pub fn new(validation: kernel::Validation) -> Checks {
|
||||
let cores = std::thread::available_parallelism().map_or(1, usize::from);
|
||||
Checks {
|
||||
on: validation == kernel::Validation::EachFeature && cores > 1,
|
||||
most: cores.saturating_sub(1).max(1),
|
||||
running: VecDeque::new(),
|
||||
held: Vec::new(),
|
||||
refused: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// The check of the bodies `after` adds to `before`, detached from them so it can run beside
|
||||
/// the features after it ([`kernel::detach_kept`]); `None` when it runs in line.
|
||||
pub fn detach(&self, before: &ModelState, after: &ModelState) -> Option<Vec<(String, kernel::KeptCheck)>> {
|
||||
self.on.then(|| {
|
||||
after
|
||||
.bodies
|
||||
.iter()
|
||||
.filter(|b| !before.bodies.iter().any(|old| old.body.same_shape(&b.body)))
|
||||
.map(|b| (b.name.clone(), kernel::detach_kept(&b.body)))
|
||||
.collect()
|
||||
})
|
||||
}
|
||||
|
||||
/// The failure feature `index` ends with, when its check refused it before.
|
||||
pub fn refused(&mut self, index: usize) -> Option<Failure> {
|
||||
self.refused.remove(&index)
|
||||
}
|
||||
|
||||
/// Runs `check`, feature `index`'s check, on a thread of its own. `Err`: no thread could
|
||||
/// start, and this is the check's own result, made here.
|
||||
pub fn start(
|
||||
&mut self,
|
||||
index: usize,
|
||||
saved: Saved,
|
||||
failure: Failure,
|
||||
check: impl FnOnce() -> kernel::Result<()> + Send + 'static,
|
||||
) -> kernel::Result<()> {
|
||||
// Taken by whichever runs it: the thread, or this one when the thread cannot start.
|
||||
let shared = Arc::new(Mutex::new(Some(check)));
|
||||
let taken = shared.clone();
|
||||
let started = kernel::kernel_thread("feature-check").spawn(move || match taken.lock().ok().and_then(|mut c| c.take()) {
|
||||
Some(check) => check(),
|
||||
None => Ok(()),
|
||||
});
|
||||
match started {
|
||||
Ok(done) => {
|
||||
self.running.push_back(Running { index, saved, failure, done });
|
||||
Ok(())
|
||||
}
|
||||
Err(_) => match shared.lock().ok().and_then(|mut c| c.take()) {
|
||||
Some(check) => check(),
|
||||
None => Ok(()),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Stores the cache entry of feature `index` once no check before it, or of it, is running.
|
||||
pub fn store(&mut self, index: usize, key: u64, entry: CachedEval, cache: &Mutex<EvalCache>, kept: &KeptSlot) {
|
||||
if self.running.front().is_some_and(|r| r.index <= index) {
|
||||
self.held.push((index, key, entry));
|
||||
} else {
|
||||
put(key, entry, cache, kept);
|
||||
}
|
||||
}
|
||||
|
||||
/// Takes the checks that ended (all of them with `wait`, or while too many run), in order:
|
||||
/// the first that refused, with what it puts back. Cache entries are stored as the checks
|
||||
/// before them pass.
|
||||
pub fn settle(&mut self, wait: bool, cache: &Mutex<EvalCache>, kept: &KeptSlot) -> Option<Refused> {
|
||||
while let Some(front) = self.running.front() {
|
||||
if !(wait || self.running.len() > self.most || front.done.is_finished()) {
|
||||
break;
|
||||
}
|
||||
let Some(r) = self.running.pop_front() else { break };
|
||||
let passed = match r.done.join() {
|
||||
Ok(check) => check,
|
||||
Err(_) => Err(kernel::KernelError::Internal(format!("{}: the check's thread stopped", r.index))),
|
||||
};
|
||||
if let Err(error) = passed {
|
||||
// What came after it was evaluated on bodies the check refuses: none of it stands.
|
||||
// The checks still running are left to end on their own.
|
||||
self.running.clear();
|
||||
self.held.retain(|(i, _, _)| *i < r.index);
|
||||
return Some(Refused { index: r.index, saved: r.saved, failure: Failure { error, ..r.failure } });
|
||||
}
|
||||
let upto = self.running.front().map_or(usize::MAX, |next| next.index);
|
||||
for (i, key, entry) in std::mem::take(&mut self.held) {
|
||||
if i < upto {
|
||||
put(key, entry, cache, kept);
|
||||
} else {
|
||||
self.held.push((i, key, entry));
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/// Feature `index`'s check refused its bodies: it ends with `failure` when evaluated again.
|
||||
pub fn refuse(&mut self, index: usize, failure: Failure) {
|
||||
self.refused.insert(index, failure);
|
||||
}
|
||||
}
|
||||
|
||||
fn put(key: u64, entry: CachedEval, cache: &Mutex<EvalCache>, kept: &KeptSlot) {
|
||||
if let Some(k) = &kept.0 {
|
||||
k.put(key, &entry);
|
||||
}
|
||||
if let Ok(mut m) = cache.lock() {
|
||||
m.put(key, entry);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use kernel::KernelError;
|
||||
|
||||
fn saved() -> Saved {
|
||||
Saved {
|
||||
state: Arc::new(ModelState::default()),
|
||||
reserved: Default::default(),
|
||||
out_len: 0,
|
||||
reuse: false,
|
||||
prev_fp: 0,
|
||||
recomputed: 0,
|
||||
restored: 0,
|
||||
poses: HashMap::new(),
|
||||
moved: Vec::new(),
|
||||
failed: HashMap::new(),
|
||||
rolled_results: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn failure() -> Failure {
|
||||
Failure { error: KernelError::Failed(String::new()), warning: Some("kept".into()), import_report: None, repair: None, ms: 1.0 }
|
||||
}
|
||||
|
||||
fn entry() -> CachedEval {
|
||||
CachedEval { error: None, warning: None, import_report: None, repair: None, ms: 0.0, state: Arc::new(ModelState::default()), bytes: 1 }
|
||||
}
|
||||
|
||||
fn checks() -> Checks {
|
||||
Checks { on: true, most: 4, running: VecDeque::new(), held: Vec::new(), refused: HashMap::new() }
|
||||
}
|
||||
|
||||
/// A check that ends after the evaluation went on, with `r`.
|
||||
fn later(r: kernel::Result<()>) -> impl FnOnce() -> kernel::Result<()> + Send + 'static {
|
||||
move || {
|
||||
std::thread::sleep(std::time::Duration::from_millis(30));
|
||||
r
|
||||
}
|
||||
}
|
||||
|
||||
/// Feature 1's check refuses its bodies while feature 0's passes: feature 0's result is
|
||||
/// stored, the results of features 1 and 2 (evaluated on the refused bodies) are not, and
|
||||
/// feature 1 ends with the check's error and the warnings it had.
|
||||
#[test]
|
||||
fn a_refused_check_takes_back_what_came_after_it() {
|
||||
let (cache, kept) = (Mutex::new(EvalCache::default()), KeptSlot(None));
|
||||
let mut c = checks();
|
||||
assert!(c.start(0, saved(), failure(), later(Ok(()))).is_ok());
|
||||
c.store(0, 10, entry(), &cache, &kept);
|
||||
assert!(c.start(1, saved(), failure(), later(Err(KernelError::Failed("refused".into())))).is_ok());
|
||||
c.store(1, 11, entry(), &cache, &kept);
|
||||
c.store(2, 12, entry(), &cache, &kept);
|
||||
assert!(cache.lock().unwrap().is_empty(), "held while the checks run");
|
||||
let refused = c.settle(true, &cache, &kept).expect("the second check refuses");
|
||||
assert_eq!(refused.index, 1);
|
||||
assert_eq!(refused.failure.error, KernelError::Failed("refused".into()));
|
||||
assert_eq!(refused.failure.warning.as_deref(), Some("kept"));
|
||||
{
|
||||
let m = cache.lock().unwrap();
|
||||
assert!(m.map.contains_key(&10) && !m.map.contains_key(&11) && !m.map.contains_key(&12));
|
||||
}
|
||||
c.refuse(1, refused.failure);
|
||||
assert!(c.refused(1).is_some() && c.refused(1).is_none());
|
||||
assert!(c.settle(true, &cache, &kept).is_none());
|
||||
}
|
||||
|
||||
/// With no check running a result is stored at once; once the checks pass, so is every
|
||||
/// result that waited for them.
|
||||
#[test]
|
||||
fn passed_checks_store_what_waited() {
|
||||
let (cache, kept) = (Mutex::new(EvalCache::default()), KeptSlot(None));
|
||||
let mut c = checks();
|
||||
c.store(0, 10, entry(), &cache, &kept);
|
||||
assert_eq!(cache.lock().unwrap().len(), 1);
|
||||
assert!(c.start(1, saved(), failure(), later(Ok(()))).is_ok());
|
||||
c.store(1, 11, entry(), &cache, &kept);
|
||||
c.store(2, 12, entry(), &cache, &kept);
|
||||
assert!(c.settle(true, &cache, &kept).is_none());
|
||||
assert_eq!(cache.lock().unwrap().len(), 3);
|
||||
}
|
||||
}
|
||||
@@ -109,7 +109,9 @@ pub(super) fn eval(doc: &Document, vals: &BTreeMap<String, Value>, f: &Feature,
|
||||
keeps,
|
||||
)?
|
||||
}
|
||||
(None, None) => kernel::trim_keep(&mb.body, &kernel::SplitTool::Plane(doc.resolve_plane_in(vals, plane, 0, Some(st))?), keeps)?,
|
||||
(None, None) => {
|
||||
kernel::trim_keep(&mb.body, &kernel::SplitTool::Plane(doc.resolve_plane_in(vals, plane, 0, f.component, Some(st))?), keeps)?
|
||||
}
|
||||
};
|
||||
let made = Traced::step(trimmed, &[&mb.traced()]);
|
||||
if let Some(slot) = st.bodies.get_mut(i) {
|
||||
@@ -132,7 +134,7 @@ pub(super) fn eval(doc: &Document, vals: &BTreeMap<String, Value>, f: &Feature,
|
||||
}
|
||||
Some(crate::ExtendTo::Bounds) => kernel::extend_surface(&mb.body, &crate::plain(edges), &at(kernel::ExtendLimit::Bounds))?,
|
||||
Some(crate::ExtendTo::Plane(plane)) => {
|
||||
let tool = kernel::SplitTool::Plane(doc.resolve_plane_in(vals, plane, 0, Some(st))?);
|
||||
let tool = kernel::SplitTool::Plane(doc.resolve_plane_in(vals, plane, 0, f.component, Some(st))?);
|
||||
kernel::extend_surface(&mb.body, &crate::plain(edges), &at(kernel::ExtendLimit::UpTo(&tool)))?
|
||||
}
|
||||
Some(crate::ExtendTo::Face(t)) => {
|
||||
@@ -312,6 +314,8 @@ pub(super) fn eval(doc: &Document, vals: &BTreeMap<String, Value>, f: &Feature,
|
||||
f.component,
|
||||
)?;
|
||||
let (o, d) = revolve_axis(
|
||||
Some(doc),
|
||||
f.component,
|
||||
vals,
|
||||
&ss,
|
||||
axis,
|
||||
|
||||
@@ -765,6 +765,7 @@ pub(super) fn eval(doc: &Document, vals: &BTreeMap<String, Value>, f: &Feature,
|
||||
designation,
|
||||
length,
|
||||
modeled,
|
||||
continuous_flanks,
|
||||
from,
|
||||
up_to,
|
||||
form,
|
||||
@@ -786,7 +787,7 @@ pub(super) fn eval(doc: &Document, vals: &BTreeMap<String, Value>, f: &Feature,
|
||||
let extent = match (length, up_to) {
|
||||
(Some(e), _) => Extent::Length(val(vals, e, Kind::Length)?),
|
||||
(None, Some(crate::ThreadLimit::Face(q))) => Extent::UpToPoint(q.0),
|
||||
(None, Some(crate::ThreadLimit::Plane(pl))) => Extent::UpTo(doc.resolve_plane_in(vals, pl, 0, Some(st))?),
|
||||
(None, Some(crate::ThreadLimit::Plane(pl))) => Extent::UpTo(doc.resolve_plane_in(vals, pl, 0, f.component, Some(st))?),
|
||||
(None, None) => Extent::Full,
|
||||
};
|
||||
// A form left at its default is the one the designation names (`Tr20x4`).
|
||||
@@ -827,7 +828,7 @@ pub(super) fn eval(doc: &Document, vals: &BTreeMap<String, Value>, f: &Feature,
|
||||
None => note,
|
||||
});
|
||||
}
|
||||
if let Some(note) = cut(st, on, (*tip, angle, depth))? {
|
||||
if let Some(note) = cut_with_flanks(st, on, (*tip, angle, depth), *continuous_flanks)? {
|
||||
*warning = Some(match warning.take() {
|
||||
Some(w) => format!("{w}; {note}"),
|
||||
None => note,
|
||||
@@ -846,11 +847,18 @@ pub(super) fn runout(vals: &BTreeMap<String, Value>, e: &Option<crate::ThreadRun
|
||||
})
|
||||
}
|
||||
|
||||
/// Cut a modelled thread resolved on its face into its body: the grooves (SMLib's exact screw
|
||||
/// sweeps, a taper's crests by its envelope) by one B-rep boolean, then the chamfered tip
|
||||
/// (`tip`, with its angle and depth when given). What the user should be told about the result, if
|
||||
/// anything, is returned.
|
||||
/// Cut a modelled thread with its historical half-turn faces and groove-before-chamfer
|
||||
/// order. Existing hole features use this layout; Thread features keep their saved choice.
|
||||
pub(super) fn cut(st: &mut ModelState, on: ThreadOn, (tip, angle, depth): (ThreadTip, Option<f64>, Option<f64>)) -> Result<Option<String>> {
|
||||
cut_with_flanks(st, on, (tip, angle, depth), false)
|
||||
}
|
||||
|
||||
fn cut_with_flanks(
|
||||
st: &mut ModelState,
|
||||
on: ThreadOn,
|
||||
(tip, angle, depth): (ThreadTip, Option<f64>, Option<f64>),
|
||||
continuous_flanks: bool,
|
||||
) -> Result<Option<String>> {
|
||||
let ThreadOn { info: t, cyl, ends, steep, ease, from: from_side, narrow, shoulder_unchecked } = on;
|
||||
let i = st.bodies.iter().position(|b| b.name == t.body).ok_or_else(|| DocError::Invalid("threaded body".into()))?;
|
||||
let Some(mb) = st.bodies.get(i).cloned() else { return Err(DocError::Invalid("body".into())) };
|
||||
@@ -888,11 +896,28 @@ pub(super) fn cut(st: &mut ModelState, on: ThreadOn, (tip, angle, depth): (Threa
|
||||
}
|
||||
false => None,
|
||||
};
|
||||
// Preserve historical construction order when rebuilding an older feature.
|
||||
let chamfer = |mut input: Traced| -> Result<Traced> {
|
||||
if tip != ThreadTip::None {
|
||||
for cone in tip_cones(&t, radius, ends, (tip, from_side), angle, depth, taper)? {
|
||||
let faces = cone.face_count();
|
||||
let cut =
|
||||
kernel::boolean(&input.body, &cone, BoolOp::Cut)?.ok_or_else(|| DocError::Invalid("the chamfer removed everything".into()))?;
|
||||
let unnamed = crate::lineage::Lineage::unnamed_faces(faces);
|
||||
let lineage = input.lineage.and_then(|l| crate::lineage::Lineage::step(&cut, &[&l, &unnamed]));
|
||||
input = Traced { body: cut, lineage };
|
||||
}
|
||||
}
|
||||
Ok(input)
|
||||
};
|
||||
if continuous_flanks {
|
||||
input = chamfer(input)?;
|
||||
}
|
||||
let cut_grooves = |ends: [End; 2]| -> Result<(Option<Body>, usize)> {
|
||||
let mut grooves = Vec::new();
|
||||
for g in thread_grooves(&t, groove_radius, (cyl.start, cyl.end), ends, steep, ease, taper)? {
|
||||
let section = Region2 { outer: solidcore_record::Loop2::polygon(&g.section), holes: Vec::new() };
|
||||
grooves.push(kernel::sweep_helix_radial(&g.plane, §ion, g.base, g.axis, g.pitch, g.turns, &g.law)?);
|
||||
grooves.push(kernel::sweep_helix_radial(&g.plane, §ion, g.base, g.axis, g.pitch, g.turns, &g.law, continuous_flanks)?);
|
||||
}
|
||||
if let Some(taper) = taper
|
||||
&& let Some(envelope) = taper_envelope(&t, radius, ends, taper)?
|
||||
@@ -932,16 +957,8 @@ pub(super) fn cut(st: &mut ModelState, on: ThreadOn, (tip, angle, depth): (Threa
|
||||
// The groove's faces have no role to name them by.
|
||||
let groove = crate::lineage::Lineage::unnamed_faces(groove_faces);
|
||||
let lineage = input.lineage.and_then(|l| crate::lineage::Lineage::step(&nb, &[&l, &groove]));
|
||||
let mut nb = Traced { body: nb, lineage };
|
||||
if tip != ThreadTip::None {
|
||||
for cone in tip_cones(&t, radius, ends, (tip, from_side), angle, depth, taper)? {
|
||||
let faces = cone.face_count();
|
||||
let cut = kernel::boolean(&nb.body, &cone, BoolOp::Cut)?.ok_or_else(|| DocError::Invalid("the chamfer removed everything".into()))?;
|
||||
let unnamed = crate::lineage::Lineage::unnamed_faces(faces);
|
||||
let lineage = nb.lineage.and_then(|l| crate::lineage::Lineage::step(&cut, &[&l, &unnamed]));
|
||||
nb = Traced { body: cut, lineage };
|
||||
}
|
||||
}
|
||||
let nb = Traced { body: nb, lineage };
|
||||
let nb = if continuous_flanks { nb } else { chamfer(nb)? };
|
||||
if let Some(slot) = st.bodies.get_mut(i) {
|
||||
*slot = ModelBody::traced_new(mb.name, nb, mb.feature);
|
||||
}
|
||||
@@ -951,7 +968,7 @@ pub(super) fn cut(st: &mut ModelState, on: ThreadOn, (tip, angle, depth): (Threa
|
||||
/// The chamfered tip of an external thread (ISO 4753, chamfered end CH) at the free ends `tip`
|
||||
/// names (`Start`: the end of the axis `from`, which must be free; `Both`: each free end):
|
||||
/// the material outside a cone `angle` to the axis (default 45°) that reaches the diameter
|
||||
/// d_f = d - 2 `depth` at the face's end, as a ring to cut after the groove, so the last teeth
|
||||
/// d_f = d - 2 `depth` at the face's end, as a ring to cut from the stock, so the last teeth
|
||||
/// taper into it. ISO 4753 bounds d_f by the external thread's minor diameter; the default is
|
||||
/// that bound, d3 = d - 1.226869 P (ISO 724, the rounded root of the design profile). It lies
|
||||
/// below the modelled basic root d1, so the cone crosses the root cylinder and leaves a whole
|
||||
|
||||
@@ -214,7 +214,7 @@ impl Document {
|
||||
}
|
||||
let mut resolved = plane.clone();
|
||||
let note = replace(self, &mut resolved, author, state, 0)?;
|
||||
Ok((self.resolve_plane_in(vals, &resolved, 0, Some(framed))?, note))
|
||||
Ok((self.resolve_plane_in(vals, &resolved, 0, author, Some(framed))?, note))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,10 @@ pub(super) fn fixtures() -> Vec<(&'static str, Value)> {
|
||||
|h: Value| json!({"type": "hole", "position": o, "direction": [0, 0, 1], "diameter": "hole.diameter", "depth": "hole.depth", "hole": h});
|
||||
vec![
|
||||
("newer_file_feature", json!({"type": "newer_file_feature", "raw": {"type": "gyroid_lattice", "cell": 2}})),
|
||||
(
|
||||
"frame_end_cap",
|
||||
json!({"type":"frame_end_cap","ends":[{"plane":plane("cap1"),"member":{"feature":7,"line":"l1"}}],"thickness":"cap.thickness","ratio":"cap.ratio","chamfer":"cap.chamfer","direction":"inward"}),
|
||||
),
|
||||
(
|
||||
"body_transfer",
|
||||
json!({"type": "body_transfer", "bodies": ["B"], "from": 0, "to": 1, "transform": [[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]]}),
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
newer_file_feature
|
||||
frame_end_cap
|
||||
inputs:
|
||||
Angle = cap1.angle (Angle)
|
||||
Offset = cap1.offset (Length)
|
||||
Thickness = cap.thickness (Length)
|
||||
Inset Ratio = cap.ratio (Unitless)
|
||||
Corner Chamfer = cap.chamfer (Length)
|
||||
expressions: cap1.angle, cap1.offset, cap.thickness, cap.ratio, cap.chamfer
|
||||
body_transfer
|
||||
sketch
|
||||
inputs:
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
newer_file_feature
|
||||
frame_end_cap
|
||||
moves: ends[0].plane.axis_dir[0], ends[0].plane.axis_dir[1], ends[0].plane.axis_origin[0], ends[0].plane.axis_origin[1], ends[0].plane.axis_origin[2]
|
||||
body_transfer
|
||||
sketch
|
||||
moves: plane.axis_dir[0], plane.axis_dir[1], plane.axis_origin[0], plane.axis_origin[1], plane.axis_origin[2]
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
newer_file_feature
|
||||
frame_end_cap
|
||||
remap_refs: ends[0].member.feature, ends[0].plane.base.base.feature
|
||||
body_transfer
|
||||
remap_bodies: bodies[0]
|
||||
sketch
|
||||
|
||||
+28
-13
@@ -864,8 +864,9 @@ fn all_unique(ids: impl Iterator<Item = u64>) -> bool {
|
||||
ids.into_iter().all(|id| seen.insert(id))
|
||||
}
|
||||
|
||||
/// The caps interactive editing enforces, applied to the raw JSON so an oversized sketch is
|
||||
/// never deserialised. Every sketch in the timeline is solved when the design opens, and the
|
||||
/// The sketch ceilings ([`solidcraft_sketch::CEILING_POINTS`] and the others, the highest the
|
||||
/// limit interactive editing enforces may be raised to), applied to the raw JSON so an oversized
|
||||
/// sketch is never deserialised. Every sketch in the timeline is solved when the design opens, and the
|
||||
/// solver sizes its dense matrices by the sketch, so a file with hundreds of thousands of
|
||||
/// points would ask the allocator for terabytes and abort before anything could report it.
|
||||
fn validate_sketch_sizes(value: &Value) -> Result<()> {
|
||||
@@ -877,10 +878,11 @@ fn validate_sketch_sizes(value: &Value) -> Result<()> {
|
||||
}
|
||||
let Some(sketch) = feature.get("sketch") else { continue };
|
||||
let len = |key: &str| sketch.get(key).and_then(Value::as_array).map_or(0, Vec::len);
|
||||
if len("points") > solidcraft_sketch::MAX_POINTS
|
||||
|| len("curves") > solidcraft_sketch::MAX_CURVES
|
||||
|| len("constraints") > solidcraft_sketch::MAX_CONSTRAINTS
|
||||
|| len("patterns") > solidcraft_sketch::MAX_CONSTRAINTS
|
||||
// The ceilings, not the limits in force: a design made where the limit was raised opens (#10874).
|
||||
if len("points") > solidcraft_sketch::CEILING_POINTS
|
||||
|| len("curves") > solidcraft_sketch::CEILING_CURVES
|
||||
|| len("constraints") > solidcraft_sketch::CEILING_CONSTRAINTS
|
||||
|| len("patterns") > solidcraft_sketch::CEILING_CONSTRAINTS
|
||||
{
|
||||
return Err(invalid());
|
||||
}
|
||||
@@ -891,7 +893,7 @@ fn validate_sketch_sizes(value: &Value) -> Result<()> {
|
||||
for pattern in patterns {
|
||||
let Some(entities) = pattern.get("entities").and_then(Value::as_array) else { return Err(invalid()) };
|
||||
let Some(instances) = pattern.get("instances").and_then(Value::as_array) else { return Err(invalid()) };
|
||||
if entities.len() > solidcraft_sketch::MAX_CURVES + solidcraft_sketch::MAX_POINTS || instances.len() >= 500 {
|
||||
if entities.len() > solidcraft_sketch::CEILING_CURVES + solidcraft_sketch::CEILING_POINTS || instances.len() >= 500 {
|
||||
return Err(invalid());
|
||||
}
|
||||
for instance in instances {
|
||||
@@ -899,9 +901,9 @@ fn validate_sketch_sizes(value: &Value) -> Result<()> {
|
||||
points = points.saturating_add(size("points"));
|
||||
curves = curves.saturating_add(size("curves"));
|
||||
constraints = constraints.saturating_add(size("constraints"));
|
||||
if points > solidcraft_sketch::MAX_POINTS
|
||||
|| curves > solidcraft_sketch::MAX_CURVES
|
||||
|| constraints > solidcraft_sketch::MAX_CONSTRAINTS
|
||||
if points > solidcraft_sketch::CEILING_POINTS
|
||||
|| curves > solidcraft_sketch::CEILING_CURVES
|
||||
|| constraints > solidcraft_sketch::CEILING_CONSTRAINTS
|
||||
{
|
||||
return Err(invalid());
|
||||
}
|
||||
@@ -2457,7 +2459,7 @@ mod tests {
|
||||
/// file too, before the arrays are deserialised.
|
||||
#[test]
|
||||
fn oversized_sketches_are_refused_before_typed_decoding() {
|
||||
use solidcraft_sketch::{MAX_CONSTRAINTS, MAX_CURVES, MAX_POINTS, Sketch};
|
||||
use solidcraft_sketch::{CEILING_CONSTRAINTS, CEILING_CURVES, CEILING_POINTS, MAX_POINTS, Sketch};
|
||||
|
||||
// A sketch right at the point cap, chained by coincident constraints.
|
||||
let mut sketch = Sketch::new();
|
||||
@@ -2472,8 +2474,8 @@ mod tests {
|
||||
let at_cap: Value = serde_json::from_str(&doc.to_json()).unwrap();
|
||||
assert!(read(&at_cap.to_string()).is_ok(), "a sketch at the caps must still load");
|
||||
|
||||
// One past each cap, grown at the JSON level: no typed array is ever built.
|
||||
for (key, cap) in [("points", MAX_POINTS), ("constraints", MAX_CONSTRAINTS), ("curves", MAX_CURVES)] {
|
||||
// One past each ceiling, grown at the JSON level: no typed array is ever built.
|
||||
for (key, cap) in [("points", CEILING_POINTS), ("constraints", CEILING_CONSTRAINTS), ("curves", CEILING_CURVES)] {
|
||||
let mut value = at_cap.clone();
|
||||
let slot = &mut value["features"][0]["sketch"][key];
|
||||
let first = slot.as_array().and_then(|a| a.first()).cloned().unwrap_or(Value::Null);
|
||||
@@ -2483,6 +2485,19 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
/// #10874: a design whose sketch is past the default limit (made where Preferences › Sketch ›
|
||||
/// Largest sketch was raised) passes the size check when it opens, whatever the limit here.
|
||||
#[test]
|
||||
fn a_sketch_past_the_default_limit_opens() {
|
||||
use solidcraft_sketch::{MAX_CURVES, MAX_POINTS};
|
||||
let points: Vec<Value> = (0..MAX_POINTS + 1).map(|i| serde_json::json!({"id": format!("p{}", i + 1), "pos": [i as f64, 0.0]})).collect();
|
||||
let curves: Vec<Value> =
|
||||
(0..MAX_CURVES + 1).map(|i| serde_json::json!({"id": format!("l{}", i + 1), "kind": {"type": "line", "a": i, "b": i + 1}})).collect();
|
||||
let mut v: Value = serde_json::from_str(&Document::new("dense drawing").to_json()).unwrap();
|
||||
v["features"] = serde_json::json!([{"type": "sketch", "sketch": {"points": points, "curves": curves}}]);
|
||||
assert!(validate_sketch_sizes(&v).is_ok(), "{} points and {} curves", MAX_POINTS + 1, MAX_CURVES + 1);
|
||||
}
|
||||
|
||||
fn two_components_one_occurrence() -> Document {
|
||||
let mut d = Document::new("ids");
|
||||
let a = d.add_component(None, 0).unwrap();
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
//! Construction sketch-point references also accept `wire:index`, identifying a drawn 3D
|
||||
//! wire's fit/control node by its stable curve id and zero-based index. References follow
|
||||
//! node movement and component placement instead of storing a frozen world coordinate.
|
||||
@@ -0,0 +1,5 @@
|
||||
//! Datum references save an origin datum of an exact placement as `o:<ids>/origin/<item>`
|
||||
//! (`PlaneRef::Datum` and `GeoRef::Datum`), resolved again on every evaluation so they follow
|
||||
//! the component. Older designs have no datum references: nothing new, they round-trip as they
|
||||
//! are. The last release warns about the newer format number, opens what it can read and keeps
|
||||
//! the rest.
|
||||
@@ -0,0 +1,4 @@
|
||||
//! Designs save frame_end_cap features: the capped end faces as persistent face anchors with
|
||||
//! their members' feature and line, the thickness, the inset as a length or a ratio of the
|
||||
//! thickness, the corner chamfer and the direction. Older designs have no end caps and need no
|
||||
//! migration. The last release refuses this newer format rather than dropping the cap bodies.
|
||||
@@ -0,0 +1,8 @@
|
||||
//! A joint origin can name the occurrences it is `inside` (`"inside": [ids]`, under its
|
||||
//! `occurrence`): set when it is picked on a part in a sub-assembly placed more than once, on
|
||||
//! another copy than the first. The origin is then on that copy, and the part's own geometry is
|
||||
//! found through those occurrences (#11426). Older designs need no transformation: their origins
|
||||
//! have nothing inside and are written as before. The last release opens a design that has such
|
||||
//! an origin with a warning and keeps the field it can't read; there the origin's part is looked
|
||||
//! for in the copy's own bodies, so its joint reports an error instead of landing on the first
|
||||
//! copy.
|
||||
@@ -0,0 +1,5 @@
|
||||
//! Joint origins can snap to origin planes/axes and construction geometry.
|
||||
//!
|
||||
//! Adds `Snap::Plane` and `Snap::Axis` to joint snap variants. Older releases
|
||||
//! do not know these snap types and ask for an update when opening a design
|
||||
//! that uses them. Older designs without plane or axis joints open unchanged.
|
||||
@@ -0,0 +1,9 @@
|
||||
//! A face name that holds the name of another face writes it in parentheses: a blend face names
|
||||
//! the edge it rounds (`F5:blend(F2:side:l2|F2:top)`) and an inner face names the face it offsets
|
||||
//! (`F3:inner(F2:top)`), where before the name followed a colon (`F5:blend:F2:side:l2|F2:top`).
|
||||
//! A curve id may hold a character outside ASCII (`F2:side:曲`), and the name that holds it
|
||||
//! (`F5:blend(F2:side:曲|F2:top)`) is read a character at a time, so the character is read whole
|
||||
//! and the name is not cut in half.
|
||||
//! Older designs need no transformation: their names are in the older form and are read as the
|
||||
//! faces they name, so a design opens as it did; the last release refuses a design saved with this
|
||||
//! (the newer format number).
|
||||
@@ -0,0 +1,5 @@
|
||||
//! A saved GPU path setup can keep an indirect-light clamp (#9815): `clamp_indirect` in its job
|
||||
//! options, a linear radiance from 0.000001 to 1000000 that caps each contribution from the
|
||||
//! first bounce on. It is omitted when off. An older design has none, and its setups render
|
||||
//! as before. The last release refuses a design saved with it and asks for an update, instead
|
||||
//! of failing to read the setup or rendering it without the clamp.
|
||||
@@ -0,0 +1,3 @@
|
||||
//! Saves each thread feature's continuous-flank layout choice. Older threads omit
|
||||
//! the field and keep their historical faces and chamfer order, preserving references.
|
||||
//! The previous release refuses designs with this newer format rather than losing it.
|
||||
@@ -0,0 +1,7 @@
|
||||
//! A cut with two sides names the two caps of its tool by the end they close: the low one
|
||||
//! `bottom`, the high one `top`. A design saved before this named them by their height
|
||||
//! instead, which gives both one name when the two sides of the cut lie on the same side of
|
||||
//! the sketch plane: the two faces the cut leaves cannot be told apart then, and a sketch on
|
||||
//! either of them cannot keep its attachment. A design that refers to such a face by the name
|
||||
//! it had is told that the face has to be picked again, as it is for any face that was
|
||||
//! renamed. The last release refuses a design that has it (it asks for an update).
|
||||
@@ -366,7 +366,7 @@ fn at_most(what: &str, r: f64, room: f64, why: &str) -> Result<()> {
|
||||
}
|
||||
|
||||
/// A number for a name: up to four decimals, without trailing zeros.
|
||||
fn short(x: f64) -> String {
|
||||
pub(crate) fn short(x: f64) -> String {
|
||||
let t = format!("{x:.4}");
|
||||
let t = if t.contains('.') { t.trim_end_matches('0').trim_end_matches('.') } else { &t };
|
||||
if t == "-0" { "0".into() } else { t.to_string() }
|
||||
|
||||
@@ -411,3 +411,106 @@ fn a_line_a_hair_off_vertical_is_vertical() {
|
||||
let (_, y) = member_axes(Vec3::new(1e-3, 0.0, 1.0), 0.0).unwrap();
|
||||
assert!(y.z > 0.0 && y.x < 0.0, "{y:?}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn end_cap_outlines_inset_and_chamfer_exactly() {
|
||||
use crate::end_cap::{chamfered, inset};
|
||||
// A 40 square with corners of radius 6, in by 3: a 34 square with corners of radius 3.
|
||||
let tube = Profile::RectTube { width: 40.0, height: 40.0, wall: 3.0, outer_radius: Some(6.0) }.region().unwrap();
|
||||
let lp = inset(&tube.outer, 3.0).unwrap();
|
||||
close(lp.signed_area(), 34.0 * 34.0 - (4.0 - std::f64::consts::PI) * 9.0, "rounded inset");
|
||||
// In by 8, past the rounding: a sharp 24 square.
|
||||
close(inset(&tube.outer, 8.0).unwrap().signed_area(), 24.0 * 24.0, "sharp inset");
|
||||
// Chamfers at least the rounding cut it away; shorter ones are refused.
|
||||
close(chamfered(&lp, 3.0).unwrap().signed_area(), 34.0 * 34.0 - 4.0 * 4.5, "chamfer");
|
||||
assert!(chamfered(&lp, 2.0).is_err());
|
||||
assert!(chamfered(&lp, 17.0).is_err());
|
||||
let round = Profile::RoundTube { diameter: 40.0, wall: 3.0 }.region().unwrap();
|
||||
close(inset(&round.outer, 2.0).unwrap().signed_area(), std::f64::consts::PI * 324.0, "round inset");
|
||||
assert!(inset(&round.outer, 20.0).is_err());
|
||||
assert!(chamfered(&inset(&round.outer, 2.0).unwrap(), 1.0).is_err());
|
||||
// A 40 x 40 x 4 angle in by 1: an L 38 long each way and 2 thick, 38 * 2 + 36 * 2.
|
||||
let angle = Profile::Angle { width: 40.0, height: 40.0, thickness: 4.0, root_radius: Some(0.0), toe_radius: Some(0.0) }.region().unwrap();
|
||||
let l = inset(&angle.outer, 1.0).unwrap();
|
||||
close(l.signed_area(), 148.0, "angle inset");
|
||||
// Five outside corners lose 0.5 * 0.5 / 2 each; the inside corner stays. A chamfer of 1 eats
|
||||
// the 2 mm toes whole.
|
||||
close(chamfered(&l, 0.5).unwrap().signed_area(), 148.0 - 5.0 * 0.125, "angle chamfer");
|
||||
assert!(chamfered(&l, 1.0).is_err());
|
||||
// Half the leg thickness or more leaves no plate.
|
||||
assert!(inset(&angle.outer, 2.0).is_err());
|
||||
assert!(inset(&angle.outer, 2.5).is_err());
|
||||
// A root rounding of 3 grows to 4 and keeps its fillet: 16 - 4 pi more than the sharp L.
|
||||
let rooted = Profile::Angle { width: 40.0, height: 40.0, thickness: 4.0, root_radius: Some(3.0), toe_radius: Some(0.0) }.region().unwrap();
|
||||
close(inset(&rooted.outer, 1.0).unwrap().signed_area(), 148.0 + 16.0 - 4.0 * std::f64::consts::PI, "rooted angle inset");
|
||||
// A 100 x 50 I-beam (web 4.5, flanges 7) in by 1: flanges 48 x 5, a web 2.5 x 88.
|
||||
let beam = Profile::IBeam { height: 100.0, width: 50.0, web: 4.5, flange: 7.0, root_radius: Some(0.0) }.region().unwrap();
|
||||
close(inset(&beam.outer, 1.0).unwrap().signed_area(), 2.0 * 48.0 * 5.0 + 2.5 * 88.0, "beam inset");
|
||||
assert!(inset(&beam.outer, 2.3).is_err());
|
||||
let channel =
|
||||
Profile::Channel { height: 100.0, width: 50.0, web: 6.0, flange: 8.0, root_radius: Some(5.0), toe_radius: Some(2.0) }.region().unwrap();
|
||||
let c = inset(&channel.outer, 1.5).unwrap();
|
||||
assert!(chamfered(&c, 3.0).is_err(), "3 + 3 is more than the 5 mm flange tip");
|
||||
let cut = chamfered(&c, 2.0).unwrap();
|
||||
assert!(cut.signed_area() < c.signed_area() && cut.signed_area() > c.signed_area() - 30.0);
|
||||
for d in [f64::NAN, f64::INFINITY, -1.0, 1e300] {
|
||||
let _ = inset(&tube.outer, d).and_then(|l| chamfered(&l, d));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn end_caps_close_open_sections_with_the_outside_of_the_profile() {
|
||||
use crate::end_cap::cap_outline;
|
||||
// Closed sections keep their own outline: the rounded tube, the round tube.
|
||||
let tube = Profile::RectTube { width: 40.0, height: 30.0, wall: 3.0, outer_radius: Some(6.0) }.region().unwrap();
|
||||
close(cap_outline(&tube.outer).signed_area(), tube.outer.signed_area(), "rect tube");
|
||||
let round = Profile::RoundTube { diameter: 40.0, wall: 3.0 }.region().unwrap();
|
||||
close(cap_outline(&round.outer).signed_area(), round.outer.signed_area(), "round tube");
|
||||
// Open sections (an L, a C, an I) get the rectangle round them.
|
||||
let open = [
|
||||
(Profile::Angle { width: 40.0, height: 30.0, thickness: 4.0, root_radius: Some(3.0), toe_radius: Some(1.0) }, 40.0 * 30.0),
|
||||
(Profile::Channel { height: 100.0, width: 50.0, web: 6.0, flange: 8.0, root_radius: Some(5.0), toe_radius: Some(2.0) }, 100.0 * 50.0),
|
||||
(Profile::IBeam { height: 100.0, width: 50.0, web: 4.5, flange: 7.0, root_radius: Some(4.5) }, 100.0 * 50.0),
|
||||
];
|
||||
for (p, area) in open {
|
||||
close(cap_outline(&p.region().unwrap().outer).signed_area(), area, "open section");
|
||||
}
|
||||
// The outside of the profile, rounds and chamfers included: a 40 x 40 extrusion with r 3
|
||||
// corners but a 2 x 2 chamfer at the bottom left, and a 6 wide, 5 deep slot in each side,
|
||||
// gets the rounded, chamfered square with the slots closed: 1600 - 3 r² (1 - π/4) - 2.
|
||||
use solidcore_record::{Loop2, Seg2, Vec2};
|
||||
use std::f64::consts::{FRAC_PI_2, PI};
|
||||
let (h, r, w, dp) = (20.0, 3.0, 3.0, 5.0);
|
||||
let v = Vec2::new;
|
||||
let line = |a: Vec2, b: Vec2| Seg2::Line { a, b };
|
||||
let round = |center: Vec2, start: f64| Seg2::Arc { center, radius: r, start, sweep: FRAC_PI_2 };
|
||||
let segs = vec![
|
||||
line(v(-h + 2.0, -h), v(-w, -h)),
|
||||
line(v(-w, -h), v(-w, -h + dp)),
|
||||
line(v(-w, -h + dp), v(w, -h + dp)),
|
||||
line(v(w, -h + dp), v(w, -h)),
|
||||
line(v(w, -h), v(h - r, -h)),
|
||||
round(v(h - r, -h + r), -FRAC_PI_2),
|
||||
line(v(h, -h + r), v(h, -w)),
|
||||
line(v(h, -w), v(h - dp, -w)),
|
||||
line(v(h - dp, -w), v(h - dp, w)),
|
||||
line(v(h - dp, w), v(h, w)),
|
||||
line(v(h, w), v(h, h - r)),
|
||||
round(v(h - r, h - r), 0.0),
|
||||
line(v(h - r, h), v(w, h)),
|
||||
line(v(w, h), v(w, h - dp)),
|
||||
line(v(w, h - dp), v(-w, h - dp)),
|
||||
line(v(-w, h - dp), v(-w, h)),
|
||||
line(v(-w, h), v(-h + r, h)),
|
||||
round(v(-h + r, h - r), FRAC_PI_2),
|
||||
line(v(-h, h - r), v(-h, w)),
|
||||
line(v(-h, w), v(-h + dp, w)),
|
||||
line(v(-h + dp, w), v(-h + dp, -w)),
|
||||
line(v(-h + dp, -w), v(-h, -w)),
|
||||
line(v(-h, -w), v(-h, -h + 2.0)),
|
||||
line(v(-h, -h + 2.0), v(-h + 2.0, -h)),
|
||||
];
|
||||
let cap = cap_outline(&Loop2 { segs });
|
||||
close(cap.signed_area(), 1600.0 - 3.0 * r * r * (1.0 - PI / 4.0) - 2.0, "slotted extrusion");
|
||||
assert_eq!(cap.segs.iter().filter(|s| matches!(s, Seg2::Arc { .. })).count(), 3, "its three rounds are kept");
|
||||
}
|
||||
|
||||
@@ -191,7 +191,7 @@ impl<'a> OperandNames<'a> {
|
||||
}
|
||||
}),
|
||||
Operand::Inner(_) => {
|
||||
given(&self.names).map(|n| Named { name: format!("F{fid}:inner:{}", n.name), verified: n.verified, ..Named::default() })
|
||||
given(&self.names).map(|n| Named { name: format!("F{fid}:inner({})", n.name), verified: n.verified, ..Named::default() })
|
||||
}
|
||||
Operand::Made(roles) => {
|
||||
let (first, rest) = roles.get(face)?.split_first()?;
|
||||
@@ -235,11 +235,11 @@ fn from_origins(face: &FaceProv, operands: &[OperandNames], fid: u64) -> Option<
|
||||
FaceOrigin::Face { operand, face } => operands.get(operand)?.face(face, fid)?,
|
||||
FaceOrigin::Edge { operand, edge } => {
|
||||
let (edge, verified) = operands.get(operand)?.edge(edge)?;
|
||||
Named { name: format!("F{fid}:blend:{edge}"), verified, ..Named::default() }
|
||||
Named { name: format!("F{fid}:blend({edge})"), verified, ..Named::default() }
|
||||
}
|
||||
FaceOrigin::Offset { operand, face } => {
|
||||
let source = operands.get(operand)?.face(face, fid)?;
|
||||
Named { name: format!("F{fid}:inner:{}", source.name), verified: source.verified, ..Named::default() }
|
||||
Named { name: format!("F{fid}:inner({})", source.name), verified: source.verified, ..Named::default() }
|
||||
}
|
||||
// A profile or cap of a body made from nothing: only a built body's own roles name
|
||||
// these, and those come in as `Made` operands.
|
||||
@@ -534,7 +534,7 @@ fn without_index(origin: FaceOrigin) -> FaceOrigin {
|
||||
}
|
||||
}
|
||||
|
||||
/// How a stored face name matches a current face.
|
||||
/// How the stored face name matches a current face.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub(crate) enum Match {
|
||||
/// Only its root stem is the same: some piece of the same face (the caller picks by point).
|
||||
@@ -549,11 +549,24 @@ pub(crate) enum Match {
|
||||
|
||||
/// How the stored name `name` matches face `index` (`None`: not at all).
|
||||
pub(crate) fn matches(names: &Names, index: usize, name: &str) -> Option<Match> {
|
||||
let current = names.faces.get(index)?;
|
||||
matches_read(names, index, name, crate::persistent_name::FaceName::parse(name).ok())
|
||||
}
|
||||
|
||||
/// [`matches`], with the wanted name already read: a name of many faces is compared with each of
|
||||
/// them, and reading it once keeps that cheap.
|
||||
pub(crate) fn matches_read(names: &Names, index: usize, name: &str, wanted: Option<crate::persistent_name::FaceName>) -> Option<Match> {
|
||||
let face = names.faces.get(index)?;
|
||||
let info = names.info.get(index);
|
||||
if current == name {
|
||||
if face == name || wanted.as_ref().is_some_and(|w| crate::persistent_name::same_face_read(face, w)) {
|
||||
return Some(Match::Exact);
|
||||
}
|
||||
// A name in the older form reads as the name it was, and is compared in today's form: the
|
||||
// checks below compare names as they are written now. The face's own name is written in
|
||||
// today's form too, unless it too was written in the older one.
|
||||
let canonical = wanted.as_ref().filter(|_| crate::persistent_name::in_old_form(name)).map(|w| w.to_string());
|
||||
let name = canonical.as_deref().unwrap_or(name);
|
||||
let today = crate::persistent_name::written_now(face);
|
||||
let current: &str = &today;
|
||||
// Another name of this very face; of a piece of it, when the face was split since.
|
||||
if info.is_some_and(|i| i.synonyms.iter().any(|a| a == name)) {
|
||||
return Some(if crate::naming::strip_piece(current) == current { Match::Exact } else { Match::Piece });
|
||||
@@ -585,10 +598,9 @@ pub(crate) fn matches(names: &Names, index: usize, name: &str) -> Option<Match>
|
||||
}
|
||||
// A piece of a blend face: a blend is named after the edge it replaced, so the qualifier that
|
||||
// tells its pieces apart sits *inside* that name, on one of the edge's sides
|
||||
// (`F4:blend:F2:side:c1#[F2:side:l3]|F2:side:l3`), and the face whole again since is the blend
|
||||
// (`F4:blend(F2:side:c1#[F2:side:l3]|F2:side:l3)`), and the face whole again since is the blend
|
||||
// of the sides without their qualifiers (#4325).
|
||||
if name.contains(":blend:")
|
||||
&& let Some((stem, around)) = blend_piece(name)
|
||||
if let Some((stem, around)) = blend_piece(name)
|
||||
&& (current == stem || crate::naming::parent_piece(current) == Some(stem.as_str()))
|
||||
&& info.is_some_and(|i| around.iter().all(|f| i.bounds.contains(*f) || i.bounds.iter().any(|bound| rounds_the_edge(bound, &stem, f))))
|
||||
{
|
||||
@@ -612,9 +624,7 @@ fn blend_piece(name: &str) -> Option<(String, Vec<&str>)> {
|
||||
if around.is_empty() {
|
||||
return None;
|
||||
}
|
||||
let mark = name.find(":blend:")?;
|
||||
let stem = format!("{}:blend:{}|{}", name.get(..mark)?, crate::naming::strip_piece(a), crate::naming::strip_piece(b));
|
||||
Some((stem, around))
|
||||
Some((crate::naming::blend_stem(name)?, around))
|
||||
}
|
||||
|
||||
/// Whether the face named `bound` (one of the faces around face `here`) is a blend that rounds the
|
||||
|
||||
@@ -111,6 +111,22 @@ fn a_piece_with_many_faces_around_it_keeps_a_name_that_can_be_used() {
|
||||
assert_ne!(names.faces[0], names.faces[1], "the pieces are still told apart");
|
||||
}
|
||||
|
||||
/// A name saved in the older form (`F5:blend:F2:+x|F2:+z`) names the same face as today's
|
||||
/// `F5:blend(F2:+x|F2:+z)`, so a stored name still finds the face, its piece and its stem.
|
||||
#[test]
|
||||
fn a_name_in_the_older_form_still_finds_the_face_it_names() {
|
||||
let names = qualify(named(&["F5:blend(F2:+x|F2:+z)#[F6:-y]", "F2:+x", "F2:+z"]), &[]);
|
||||
// The face is a piece of the blend face the stored name names.
|
||||
assert_eq!(matches(&names, 0, "F5:blend:F2:+x|F2:+z"), Some(Match::Piece), "the older form names the same face");
|
||||
assert_eq!(matches(&names, 0, "F5:blend(F2:+x|F2:+z)"), Some(Match::Piece), "the current form as well");
|
||||
// Another face of the design is not that face.
|
||||
assert_eq!(matches(&names, 1, "F5:blend:F2:+x|F2:+z"), None);
|
||||
// The inner face of an older design is found as well.
|
||||
let names = qualify(named(&["F3:inner(F2:top)#[F4:-y]", "F2:top"]), &[]);
|
||||
assert_eq!(matches(&names, 0, "F3:inner:F2:top"), Some(Match::Piece), "the older form names the same face");
|
||||
assert_eq!(matches(&names, 1, "F3:inner:F2:top"), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_merged_face_takes_the_shared_stem_or_the_first_name_and_answers_to_the_others() {
|
||||
let m = merged(named(&["top#[a]", "top#[b]"])).unwrap();
|
||||
@@ -227,6 +243,20 @@ fn a_piece_of_a_blend_face_finds_it_once_it_is_one_face_again() {
|
||||
assert_eq!(matches(&copied, 0, "F3:blend:side#[start@F9.1]|start@F9.2"), None, "another copy");
|
||||
}
|
||||
|
||||
/// A piece of a blend face is found by the name the blend is written in today as well: the
|
||||
/// qualifier that tells the piece apart sits inside the blend's name, on one of the edge's sides,
|
||||
/// and the face whole again since is the blend of the sides without their qualifiers.
|
||||
#[test]
|
||||
fn a_piece_of_a_blend_face_is_found_by_the_name_the_blend_is_written_in_today() {
|
||||
let faces = named(&["F3:blend(side|start)", "side", "start"]);
|
||||
let names = qualify(faces, &[(0, 1), (0, 2)]);
|
||||
assert_eq!(names.faces[0], "F3:blend(side|start)");
|
||||
assert_eq!(matches(&names, 0, "F3:blend(side#[start]|start)"), Some(Match::Piece));
|
||||
assert_eq!(matches(&names, 0, "F3:blend(side#[side]|start)"), Some(Match::Piece));
|
||||
// A face the blend no longer touches, inside its name: not its piece.
|
||||
assert_eq!(matches(&names, 0, "F3:blend(side#[top]|start)"), None);
|
||||
}
|
||||
|
||||
/// Two pieces of one face that a blend tells apart from the same face both answer to the stored
|
||||
/// name: one through the face itself, one through the blend that replaced its edge. The lookup
|
||||
/// chooses neither (#4325).
|
||||
|
||||
+496
-51
@@ -18,12 +18,13 @@ use solidcraft_geom::prelude::*;
|
||||
use std::collections::{BTreeMap, BTreeSet, VecDeque};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use solidcore_record::Vec3;
|
||||
use solidcore_record::{Plane, Vec3};
|
||||
use solidcraft_geom::Aabb3;
|
||||
|
||||
use solidcraft_sketch::linalg;
|
||||
|
||||
use crate::{DocError, Document, IDENTITY, Mat, ModelState, Result, apply_point, apply_vector, mat_inverse, mat_mul};
|
||||
use crate::construct::{ConstructGeom, DatumRef};
|
||||
use crate::{DocError, Document, IDENTITY, Mat, ModelState, PlaneRef, Result, apply_point, apply_vector, mat_inverse, mat_mul};
|
||||
|
||||
#[path = "joints_handles.rs"]
|
||||
mod handles;
|
||||
@@ -32,6 +33,49 @@ pub use handles::{MotionAxis, motion_axes};
|
||||
/// Joints the solver (and the URDF export) reads at most.
|
||||
pub const MAX_JOINTS: usize = 10_000;
|
||||
|
||||
/// A reference to an axis for a joint origin (component coordinates): an origin axis (X, Y, Z),
|
||||
/// a named construction axis, a placement's origin datum, or an axis from model geometry.
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum AxisRef {
|
||||
Target(AxisTarget),
|
||||
/// Name shorthand: "X", "Y", "Z" for the side's own origin axes, or a construction axis
|
||||
/// feature name.
|
||||
Name(String),
|
||||
}
|
||||
|
||||
/// A structured reference to an axis.
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(tag = "type", rename_all = "snake_case")]
|
||||
pub enum AxisTarget {
|
||||
/// An origin axis: "X", "Y", or "Z" (the side's own component's).
|
||||
Origin { axis: String },
|
||||
/// A construction axis feature, by name, bound to the component that owns it.
|
||||
Construction { name: String },
|
||||
/// An origin datum of an exact placement (`o:2/3/origin/X`), re-resolved at every solve.
|
||||
Datum { datum: DatumRef },
|
||||
/// An axis from model or sketch geometry.
|
||||
Geo { geo: crate::construct::GeoRef },
|
||||
}
|
||||
|
||||
impl AxisRef {
|
||||
pub fn origin(axis: impl Into<String>) -> Self {
|
||||
AxisRef::Target(AxisTarget::Origin { axis: axis.into() })
|
||||
}
|
||||
|
||||
pub fn construction(name: impl Into<String>) -> Self {
|
||||
AxisRef::Target(AxisTarget::Construction { name: name.into() })
|
||||
}
|
||||
|
||||
pub fn datum(datum: DatumRef) -> Self {
|
||||
AxisRef::Target(AxisTarget::Datum { datum })
|
||||
}
|
||||
|
||||
pub fn geo(geo: crate::construct::GeoRef) -> Self {
|
||||
AxisRef::Target(AxisTarget::Geo { geo })
|
||||
}
|
||||
}
|
||||
|
||||
/// Where a joint origin sits on a component's geometry (component coordinates).
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(tag = "type", rename_all = "snake_case")]
|
||||
@@ -95,6 +139,26 @@ pub enum Snap {
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
x: Option<Vec3>,
|
||||
},
|
||||
/// A plane (the root's origin planes, a construction plane feature, or a placement's origin
|
||||
/// datum): z along its normal, x along the plane's x axis (or `x` if given). Origin at `pick`
|
||||
/// projected onto the plane, or the plane's own origin when `pick` is omitted.
|
||||
Plane {
|
||||
plane: Box<PlaneRef>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pick: Option<Vec3>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
x: Option<XRef>,
|
||||
},
|
||||
/// An axis (the side's own origin axis "X"|"Y"|"Z", a construction axis, a placement's origin
|
||||
/// datum, or model edge/axis): z along the axis, x square to z (or `x` if given). Origin at
|
||||
/// `pick` projected onto the axis line, or the axis origin when `pick` is None.
|
||||
Axis {
|
||||
axis: Box<AxisRef>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pick: Option<Vec3>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
x: Option<XRef>,
|
||||
},
|
||||
}
|
||||
|
||||
/// The z of an edge origin that isn't its face's normal (component coordinates); its x follows
|
||||
@@ -150,6 +214,9 @@ impl Snap {
|
||||
if let Snap::Edge { edge, face, corner, .. } = self {
|
||||
out.extend(edge.iter().chain(face.iter()).chain(corner.iter()));
|
||||
}
|
||||
if let Snap::Plane { x: Some(XRef::Face { face, .. }), .. } | Snap::Axis { x: Some(XRef::Face { face, .. }), .. } = self {
|
||||
out.push(face);
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
@@ -171,32 +238,60 @@ impl Snap {
|
||||
}
|
||||
}
|
||||
Snap::Edge { edge, face, corner, .. } => out.extend(edge.iter_mut().chain(face.iter_mut()).chain(corner.iter_mut())),
|
||||
Snap::Plane { x: Some(XRef::Face { face, .. }), .. } | Snap::Axis { x: Some(XRef::Face { face, .. }), .. } => {
|
||||
out.push(face);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
/// The direction a face or circle snap keeps as its frame's x (`XRef::Dir`), in the
|
||||
/// component's coordinates; `None` for a face reference or none.
|
||||
/// The direction a face, circle, plane or axis snap keeps as its frame's x (`XRef::Dir`),
|
||||
/// in the component's coordinates; `None` for a face reference or none.
|
||||
pub fn frame_x(&self) -> Option<Vec3> {
|
||||
match self {
|
||||
Snap::FaceCenter { x: Some(XRef::Dir(d)), .. } | Snap::CircleCenter { x: Some(XRef::Dir(d)), .. } => Some(*d),
|
||||
Snap::FaceCenter { x: Some(XRef::Dir(d)), .. }
|
||||
| Snap::CircleCenter { x: Some(XRef::Dir(d)), .. }
|
||||
| Snap::Plane { x: Some(XRef::Dir(d)), .. }
|
||||
| Snap::Axis { x: Some(XRef::Dir(d)), .. } => Some(*d),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// A face or circle snap given no x reference keeps `x` (the frame's x as it is now): each
|
||||
/// solve lays it onto the face, or square to the hole's axis, as the geometry is then, so a
|
||||
/// part on a face that tilts keeps its turn about z. Without it (designs made before) x
|
||||
/// follows from z alone, and turns through a right angle where z crosses 0.9 along the
|
||||
/// component's X. A snap with a reference keeps it.
|
||||
/// A face, circle, plane or axis snap given no x reference keeps `x` (the frame's x as it is
|
||||
/// now): each solve lays it onto the face, or square to the axis, as the geometry is then, so
|
||||
/// a part on a face that tilts keeps its turn about z. A snap with a reference keeps it.
|
||||
pub fn with_frame_x(mut self, x: Vec3) -> Snap {
|
||||
if let Snap::FaceCenter { x: slot @ None, .. } | Snap::CircleCenter { x: slot @ None, .. } = &mut self {
|
||||
if let Snap::FaceCenter { x: slot @ None, .. }
|
||||
| Snap::CircleCenter { x: slot @ None, .. }
|
||||
| Snap::Plane { x: slot @ None, .. }
|
||||
| Snap::Axis { x: slot @ None, .. } = &mut self
|
||||
{
|
||||
*slot = Some(XRef::Dir(x));
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
/// A datum plane or axis side given no `pick` keeps the origin it resolved to when the joint
|
||||
/// was made (the side's own coordinates, as `pick`): the datum is re-resolved at every solve,
|
||||
/// and the stored point is laid onto it again, so the side follows the datum's orientation
|
||||
/// and rides it across its normal - and none of that reads the side's own placement back.
|
||||
/// Without the pin, a side on one placement of a component naming another placement's datum
|
||||
/// would map the datum through its own current frame each solve (`in_occurrence`), and the
|
||||
/// solve would move that placement again: the joint drifts by the datum's offset every time
|
||||
/// the assembly is solved.
|
||||
pub fn with_datum_pick(mut self, origin: Vec3) -> Snap {
|
||||
let pinned = match &self {
|
||||
Snap::Plane { plane, pick, .. } => matches!(plane.as_ref(), PlaneRef::Datum { .. }) && pick.is_none(),
|
||||
Snap::Axis { axis, pick, .. } => matches!(axis.as_ref(), AxisRef::Target(AxisTarget::Datum { .. })) && pick.is_none(),
|
||||
_ => false,
|
||||
};
|
||||
if pinned && let Snap::Plane { pick: slot @ None, .. } | Snap::Axis { pick: slot @ None, .. } = &mut self {
|
||||
*slot = Some(origin);
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
/// Whether every point and direction in the snap is finite.
|
||||
pub fn is_finite(&self) -> bool {
|
||||
let x_ok = |x: &Option<XRef>| match x {
|
||||
@@ -209,6 +304,7 @@ impl Snap {
|
||||
Snap::FaceCenter { pick, x, .. } | Snap::CircleCenter { pick, x, .. } => pick.is_finite() && x_ok(x),
|
||||
Snap::Point { point, z, x } => point.is_finite() && z.is_none_or(|z| z.is_finite()) && x.is_none_or(|x| x.is_finite()),
|
||||
Snap::Edge { pick, axis, .. } => pick.is_finite() && axis.is_none_or(|a| a.dir().is_finite()),
|
||||
Snap::Plane { pick, x, .. } | Snap::Axis { pick, x, .. } => pick.is_none_or(|p| p.is_finite()) && x_ok(x),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -216,10 +312,35 @@ impl Snap {
|
||||
/// A joint origin: a snap on an occurrence's component (occurrence 0 = the root design).
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct JointOrigin {
|
||||
/// What the origin is on: the occurrence a joint at it holds or moves.
|
||||
pub occurrence: u64,
|
||||
/// The occurrences below `occurrence`, one per level, down to the part whose geometry `snap`
|
||||
/// names (its [`JointOrigin::part`]). Set when that part sits in a sub-assembly placed more
|
||||
/// than once and the origin was picked on another copy than the first: the part's own
|
||||
/// occurrence is shared by every copy, so the origin is on the copy instead (#11426).
|
||||
/// Empty: the snap is on `occurrence`'s own component.
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub inside: Vec<u64>,
|
||||
pub snap: Snap,
|
||||
}
|
||||
|
||||
impl JointOrigin {
|
||||
/// An origin on `occurrence`'s own component.
|
||||
pub fn new(occurrence: u64, snap: Snap) -> Self {
|
||||
JointOrigin { occurrence, inside: Vec::new(), snap }
|
||||
}
|
||||
|
||||
/// The occurrence whose component the snap's geometry and face names belong to.
|
||||
pub fn part(&self) -> u64 {
|
||||
self.inside.last().copied().unwrap_or(self.occurrence)
|
||||
}
|
||||
|
||||
/// Every occurrence the origin needs: it is lost when any of them goes.
|
||||
pub fn occurrences(&self) -> impl Iterator<Item = u64> + '_ {
|
||||
std::iter::once(self.occurrence).chain(self.inside.iter().copied())
|
||||
}
|
||||
}
|
||||
|
||||
/// A named joint origin (Joint Origin command), referenced by joints by name.
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct NamedOrigin {
|
||||
@@ -800,7 +921,7 @@ fn named_pick(doc: &Document, st: &ModelState, component: u64, pick: Vec3, face:
|
||||
/// planar face nearest `pick` (component coordinates; a body moved in from another component
|
||||
/// placed by its offset, as a named face is).
|
||||
fn nearest_plane(doc: &Document, st: &ModelState, o: &JointOrigin, pick: Vec3) -> Result<(Vec3, Vec3)> {
|
||||
let comp = component_of(doc, o.occurrence)?;
|
||||
let comp = component_of(doc, o.part())?;
|
||||
let mut best: Option<(f64, &crate::ModelBody, solidcraft_kernel::FaceInfo, Vec3)> = None;
|
||||
for b in component_bodies(doc, st, comp) {
|
||||
let offset = doc.model_body_offset(b);
|
||||
@@ -825,8 +946,77 @@ fn nearest_plane(doc: &Document, st: &ModelState, o: &JointOrigin, pick: Vec3) -
|
||||
})
|
||||
}
|
||||
|
||||
/// Resolve a joint origin to a frame in its component's coordinates.
|
||||
/// The world seen from an occurrence's component: the inverse of the occurrence's own world
|
||||
/// frame (identity for the root).
|
||||
fn in_occurrence(doc: &Document, occ: u64) -> Result<Mat> {
|
||||
if occ == 0 {
|
||||
return Ok(IDENTITY);
|
||||
}
|
||||
mat_inverse(&occurrence_world(doc, occ)).ok_or_else(|| DocError::Invalid("joint origin: the occurrence's placement is singular".into()))
|
||||
}
|
||||
|
||||
/// Resolve an axis reference to a line (origin, unit direction) in the side's component
|
||||
/// coordinates. `occurrence` is the joint origin's occurrence: a construction axis resolves only
|
||||
/// in the component that owns it (no cross-component fallback), and a placement's datum resolves
|
||||
/// in the world ([`crate::construct::resolve_datum`]) and is mapped into the side's frame.
|
||||
pub fn resolve_axis_ref(doc: &Document, st: &ModelState, occurrence: u64, axis: &AxisRef) -> Result<(Vec3, Vec3)> {
|
||||
let comp = component_of(doc, occurrence)?;
|
||||
match axis {
|
||||
AxisRef::Target(AxisTarget::Origin { axis }) => {
|
||||
let d = match axis.to_ascii_uppercase().as_str() {
|
||||
"X" => Vec3::X,
|
||||
"Y" => Vec3::Y,
|
||||
"Z" => Vec3::Z,
|
||||
_ => return Err(DocError::Unknown(format!("axis `{axis}`"))),
|
||||
};
|
||||
Ok((Vec3::ZERO, d))
|
||||
}
|
||||
AxisRef::Name(axis) if axis.eq_ignore_ascii_case("X") => Ok((Vec3::ZERO, Vec3::X)),
|
||||
AxisRef::Name(axis) if axis.eq_ignore_ascii_case("Y") => Ok((Vec3::ZERO, Vec3::Y)),
|
||||
AxisRef::Name(axis) if axis.eq_ignore_ascii_case("Z") => Ok((Vec3::ZERO, Vec3::Z)),
|
||||
AxisRef::Target(AxisTarget::Construction { name }) | AxisRef::Name(name) => {
|
||||
let mut match_comp = None;
|
||||
for c in &st.construct {
|
||||
if c.name == *name {
|
||||
if let ConstructGeom::Axis { origin, dir } = &c.geom {
|
||||
let feat_comp = doc.feature(c.feature).map(|f| f.component).unwrap_or(0);
|
||||
if feat_comp == comp {
|
||||
match_comp = Some((*origin, *dir));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
return Err(DocError::Invalid(format!("construction `{name}` is not an axis")));
|
||||
}
|
||||
}
|
||||
}
|
||||
match_comp.ok_or_else(|| DocError::Unknown(format!("construction axis `{name}`")))
|
||||
}
|
||||
AxisRef::Target(AxisTarget::Datum { datum }) => {
|
||||
// Through the core: the datum in the world (its exact placement), then into the
|
||||
// side's frame. `resolve_datum_in`'s component mapping is not used here: it goes
|
||||
// through a component's FIRST placement, while a joint side is an exact occurrence,
|
||||
// which may be a later placement of its component.
|
||||
let inv = in_occurrence(doc, occurrence)?;
|
||||
match crate::construct::resolve_datum(doc, datum)? {
|
||||
ConstructGeom::Axis { origin, dir } => Ok((apply_point(&inv, origin), apply_vector(&inv, dir))),
|
||||
_ => Err(DocError::Invalid("the datum is not an axis (pick the X, Y or Z of a component)".into())),
|
||||
}
|
||||
}
|
||||
AxisRef::Target(AxisTarget::Geo { geo }) => {
|
||||
let (vals, _) = doc.param_values();
|
||||
let ctx = crate::construct::Ctx { doc, vals: &vals, st, depth: 0, component: comp };
|
||||
crate::construct::line(&ctx, geo)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Resolve a joint origin to a frame in its component's coordinates (its `occurrence`'s: an
|
||||
/// origin with occurrences `inside` is resolved on its part and carried up through them).
|
||||
pub fn resolve_origin(doc: &Document, st: &ModelState, o: &JointOrigin) -> Result<Mat> {
|
||||
if !o.inside.is_empty() {
|
||||
let on_part = resolve_origin(doc, st, &JointOrigin::new(o.part(), o.snap.clone()))?;
|
||||
return Ok(mat_mul(&inside_transform(doc, o)?, &on_part));
|
||||
}
|
||||
let bad = || DocError::Invalid("joint origin: degenerate frame".into());
|
||||
match &o.snap {
|
||||
Snap::Frame { origin, z, x } => frame(*origin, *z, *x).ok_or_else(bad),
|
||||
@@ -850,15 +1040,74 @@ pub fn resolve_origin(doc: &Document, st: &ModelState, o: &JointOrigin) -> Resul
|
||||
let r = round_of(doc, st, o)?;
|
||||
frame(r.centre, r.z, face::x_axis(doc, st, component_of(doc, o.occurrence)?, x.as_ref(), r.centre)?).ok_or_else(bad)
|
||||
}
|
||||
Snap::Plane { plane, pick, x } => {
|
||||
let comp = component_of(doc, o.occurrence)?;
|
||||
let (vals, _) = doc.param_values();
|
||||
// A construction plane is kept evaluated in its owning component's frame and stays
|
||||
// bound to it: a plane of another component is refused, and the side reads its own
|
||||
// component's as it is. Every other kind resolves in the world (the root's origin
|
||||
// planes, a placement's datum) and is mapped into the side's frame — through the
|
||||
// side's exact occurrence, not `resolve_datum_in`'s first-placement mapping.
|
||||
let pl = match plane.as_ref() {
|
||||
PlaneRef::Construction { feature } => {
|
||||
if doc.feature(feature.0).map(|f| f.component) != Some(comp) {
|
||||
return Err(DocError::Unknown(format!("construction plane is not on this component (occurrence {})", o.occurrence)));
|
||||
}
|
||||
doc.resolve_plane_in(&vals, plane, 0, comp, Some(st))?
|
||||
}
|
||||
_ => {
|
||||
let inv = in_occurrence(doc, o.occurrence)?;
|
||||
let world = doc.resolve_plane_in(&vals, plane, 0, 0, Some(st))?;
|
||||
Plane::new(apply_point(&inv, world.origin), apply_vector(&inv, world.x), apply_vector(&inv, world.y)).ok_or_else(bad)?
|
||||
}
|
||||
};
|
||||
let n = pl.normal().normalized().ok_or_else(bad)?;
|
||||
let origin = match pick {
|
||||
Some(p) => *p - n * (*p - pl.origin).dot(n),
|
||||
None => pl.origin,
|
||||
};
|
||||
let x_axis = match x {
|
||||
Some(_) => face::x_axis(doc, st, comp, x.as_ref(), origin)?,
|
||||
None => Some(pl.x),
|
||||
};
|
||||
frame(origin, n, x_axis).ok_or_else(bad)
|
||||
}
|
||||
Snap::Axis { axis, pick, x } => {
|
||||
let comp = component_of(doc, o.occurrence)?;
|
||||
let (line_origin, line_dir) = resolve_axis_ref(doc, st, o.occurrence, axis)?;
|
||||
let z = line_dir.normalized().ok_or_else(bad)?;
|
||||
let origin = match pick {
|
||||
Some(p) => line_origin + z * (*p - line_origin).dot(z),
|
||||
None => line_origin,
|
||||
};
|
||||
let x_axis = face::x_axis(doc, st, comp, x.as_ref(), origin)?;
|
||||
frame(origin, z, x_axis).ok_or_else(bad)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The transform from an origin's part to its `occurrence`, through the occurrences `inside`
|
||||
/// (each placed in the one before). An error when they no longer lead from one to the next.
|
||||
fn inside_transform(doc: &Document, o: &JointOrigin) -> Result<Mat> {
|
||||
let lost = || DocError::Invalid("joint origin: its part is no longer in that sub-assembly".into());
|
||||
if o.inside.len() > crate::MAX_PLACEMENT_DEPTH {
|
||||
return Err(lost());
|
||||
}
|
||||
let (mut m, mut component) = (IDENTITY, component_of(doc, o.occurrence)?);
|
||||
for id in &o.inside {
|
||||
let x = doc.occurrences.iter().find(|x| x.id == *id && x.parent == component).ok_or_else(lost)?;
|
||||
m = mat_mul(&m, &x.transform);
|
||||
component = x.component;
|
||||
}
|
||||
Ok(m)
|
||||
}
|
||||
|
||||
/// A circle-centre snap's cylinder and the end it takes (component coordinates): through its
|
||||
/// named face when it names a cylinder, else the cylindrical face at its pick and the end nearer
|
||||
/// it, as older builds found them. Any other snap is refused.
|
||||
fn round_of(doc: &Document, st: &ModelState, o: &JointOrigin) -> Result<face::Round> {
|
||||
let Snap::CircleCenter { pick, face, end, .. } = &o.snap else { return Err(DocError::Invalid("pick a round face".into())) };
|
||||
let comp = component_of(doc, o.occurrence)?;
|
||||
let comp = component_of(doc, o.part())?;
|
||||
if let Some(n) = face.as_deref()
|
||||
&& let Some(r) = face::named_round(doc, st, comp, *pick, n, end.as_deref())?
|
||||
{
|
||||
@@ -891,6 +1140,24 @@ fn circle_at(doc: &Document, st: &ModelState, o: &JointOrigin) -> Result<solidcr
|
||||
round_of(doc, st, o).map(|r| r.cylinder)
|
||||
}
|
||||
|
||||
/// Where a joint origin picked on the placement `path` (occurrence ids from the root) goes: the
|
||||
/// deepest occurrence of the path that [`occurrence_world`] places there (every occurrence above
|
||||
/// it is its component's first), and the occurrences below it, which the origin is `inside`. A
|
||||
/// path through first occurrences only gives its last occurrence and nothing inside, as an
|
||||
/// origin was before; an empty path, the root.
|
||||
pub fn origin_anchor(doc: &Document, path: &[u64]) -> (u64, Vec<u64>) {
|
||||
let first = |id: &u64| {
|
||||
let component = doc.occurrences.iter().find(|o| o.id == *id).map(|o| o.component);
|
||||
component.and_then(|c| doc.occurrence_of(c)).is_some_and(|f| f.id == *id)
|
||||
};
|
||||
let last = path.len().saturating_sub(1);
|
||||
let k = path.iter().take(last).position(|id| !first(id)).unwrap_or(last);
|
||||
match path.get(k) {
|
||||
Some(anchor) => (*anchor, path.get(k + 1..).unwrap_or_default().to_vec()),
|
||||
None => (0, Vec::new()),
|
||||
}
|
||||
}
|
||||
|
||||
/// World transform of an occurrence (through its parents).
|
||||
pub fn occurrence_world(doc: &Document, occ: u64) -> Mat {
|
||||
let mut m = IDENTITY;
|
||||
@@ -1022,13 +1289,16 @@ pub fn joint_values(asm: &Assembly) -> BTreeMap<u64, Vec<f64>> {
|
||||
}
|
||||
|
||||
/// The turn and offset from A's joint frame to B's: mated (B's z against A's, as faces meet)
|
||||
/// unless flipped.
|
||||
/// unless flipped. Two datum references (a plane or an axis on each side) both point along the
|
||||
/// geometry's own normal rather than out of a body, so they mate aligned - each part keeps its
|
||||
/// side of the datum - and `flip` asks for the mated relation.
|
||||
fn flip_of(j: &Joint) -> Mat {
|
||||
// An angle relation's `angle` is its tilt (`tail`); a perpendicular one has none.
|
||||
let turn = if matches!(j.kind, JointKind::Angle | JointKind::Perpendicular) { 0.0 } else { j.angle };
|
||||
let mut m = rot_z(turn);
|
||||
m[3][2] = j.offset;
|
||||
if !j.flip { mat_mul(&m, &[[1.0, 0.0, 0.0, 0.0], [0.0, -1.0, 0.0, 0.0], [0.0, 0.0, -1.0, 0.0], [0.0, 0.0, 0.0, 1.0]]) } else { m }
|
||||
let datums = matches!(j.a.snap, Snap::Plane { .. } | Snap::Axis { .. }) && matches!(j.b.snap, Snap::Plane { .. } | Snap::Axis { .. });
|
||||
if datums == j.flip { mat_mul(&m, &[[1.0, 0.0, 0.0, 0.0], [0.0, -1.0, 0.0, 0.0], [0.0, 0.0, -1.0, 0.0], [0.0, 0.0, 0.0, 1.0]]) } else { m }
|
||||
}
|
||||
|
||||
/// Component-space frames stay fixed throughout one solve. Cache their inverses without
|
||||
@@ -2003,7 +2273,14 @@ struct Built<'a> {
|
||||
/// Lay out the joint graph: the spanning tree out from the fixed occurrences (the root, grounded
|
||||
/// ones; with neither involved, the first joint's A side) and the joints left over, which close
|
||||
/// loops. Joints whose origins can't be resolved go to `sol.errors`; `sol.fixed` is set.
|
||||
fn build<'a>(doc: &'a Document, st: &ModelState, vals: &Values, sol: &mut Solution) -> Built<'a> {
|
||||
///
|
||||
/// Candidates are taken in FIFO order from a `VecDeque`: a parent popped earlier at depth `D-1`
|
||||
/// enqueues its children first, so its edge reaches an occurrence before any parent popped later
|
||||
/// at the same level. When two joints at equal BFS depth reach the same occurrence, the one from
|
||||
/// the **earlier-queued parent** wins the tie (the original behaviour, predating `BinaryHeap`).
|
||||
/// Two runs of the same design place identically; a design's tree can still differ from
|
||||
/// `BinaryHeap`'s, which broke ties by joint creation index instead.
|
||||
fn build<'a>(doc: &'a Document, st: &'a ModelState, vals: &Values, sol: &mut Solution) -> Built<'a> {
|
||||
let asm = &doc.assembly;
|
||||
let joints: Vec<&Joint> = asm.joints.iter().filter(|j| !j.suppressed).take(MAX_JOINTS).collect();
|
||||
// Joint frames in component coordinates (errors leave the joint out). An origin several joints
|
||||
@@ -2012,8 +2289,17 @@ fn build<'a>(doc: &'a Document, st: &ModelState, vals: &Values, sol: &mut Soluti
|
||||
let mut found: BTreeMap<(u64, String), std::result::Result<Mat, String>> = BTreeMap::new();
|
||||
let mut resolve = |o: &JointOrigin| -> Result<Mat> {
|
||||
let Ok(comp) = component_of(doc, o.occurrence) else { return resolve_origin(doc, st, o) };
|
||||
// A plane or axis side resolves in the world and is mapped into the side's exact
|
||||
// occurrence's frame (`in_occurrence`), so its frame depends on the occurrence, not just
|
||||
// on the component: two placements of one component whose sides name the same datum must
|
||||
// not share the cached entry, or the second reads the first's frame. Such sides key by
|
||||
// their occurrence; every other snap stays component-local and shares as before.
|
||||
let keyed = match &o.snap {
|
||||
Snap::Plane { .. } | Snap::Axis { .. } => o.occurrence,
|
||||
_ => comp,
|
||||
};
|
||||
found
|
||||
.entry((comp, format!("{:?}", o.snap)))
|
||||
.entry((keyed, format!("{:?}", (&o.inside, &o.snap))))
|
||||
.or_insert_with(|| resolve_origin(doc, st, o).map_err(|e| e.to_string()))
|
||||
.clone()
|
||||
.map_err(DocError::Invalid)
|
||||
@@ -2056,7 +2342,7 @@ fn build<'a>(doc: &'a Document, st: &ModelState, vals: &Values, sol: &mut Soluti
|
||||
// Every joint's values are known, suppressed ones too (their motion links still set values).
|
||||
Tree { joints: asm.joints.iter().map(|j| (j.id, j)).collect(), frames, fixed: placed.clone(), parent: BTreeMap::new(), order: Vec::new() };
|
||||
let mut used: BTreeSet<u64> = BTreeSet::new();
|
||||
let mut queue: VecDeque<u64> = placed.keys().copied().collect();
|
||||
|
||||
// An occurrence's degrees of freedom are the distinct values that move it: those of the
|
||||
// joints on its path, a value a motion link sets standing for the values its link chain
|
||||
// starts from (a driven gear turns with its driving gear's one value). Kept per occurrence as
|
||||
@@ -2065,51 +2351,106 @@ fn build<'a>(doc: &'a Document, st: &ModelState, vals: &Values, sol: &mut Soluti
|
||||
let sources = link_sources(asm);
|
||||
let shared: BTreeSet<(u64, usize)> = sources.values().flatten().copied().collect();
|
||||
let mut moved_by: BTreeMap<u64, (usize, BTreeSet<(u64, usize)>)> = BTreeMap::new();
|
||||
// The joints at each occurrence, in the joints' order (a large assembly is not walked joint by
|
||||
// joint for every occurrence).
|
||||
let mut at: BTreeMap<u64, Vec<&Joint>> = BTreeMap::new();
|
||||
for j in joints.iter().copied() {
|
||||
at.entry(j.a.occurrence).or_default().push(j);
|
||||
|
||||
// Adjacency list: each occurrence's joints, in joint definition order. The FIFO tie-break uses
|
||||
// this order for the seed (several fixed occurrences push their edges in that order), and the
|
||||
// order in which the neighbours of a freshly placed occurrence are enqueued.
|
||||
let mut at: BTreeMap<u64, Vec<(usize, &Joint)>> = BTreeMap::new();
|
||||
for (idx, j) in joints.iter().copied().enumerate() {
|
||||
at.entry(j.a.occurrence).or_default().push((idx, j));
|
||||
if j.b.occurrence != j.a.occurrence {
|
||||
at.entry(j.b.occurrence).or_default().push(j);
|
||||
at.entry(j.b.occurrence).or_default().push((idx, j));
|
||||
}
|
||||
}
|
||||
while let Some(occ) = queue.pop_front() {
|
||||
let Some(t) = placed.get(&occ).copied() else { continue };
|
||||
for j in at.get(&occ).map(Vec::as_slice).unwrap_or_default() {
|
||||
if used.contains(&j.id) || !tree.frames.contains_key(&j.id) {
|
||||
|
||||
// Topological distance from the fixed occurrences (filled, kept for callers that inspect it).
|
||||
let mut depths: BTreeMap<u64, usize> = BTreeMap::new();
|
||||
for &occ in placed.keys() {
|
||||
depths.insert(occ, 0);
|
||||
}
|
||||
|
||||
// Spanning tree by BFS: candidates are popped FIFO, so a joint enqueued by a parent popped
|
||||
// earlier at the previous depth is placed before one enqueued by a later parent at that depth.
|
||||
// This is exactly the pre-`BinaryHeap` ordering: the earliest-queued parent wins the tie.
|
||||
// `idx` (the joint's creation index) is carried alongside in case a future ordering needs it;
|
||||
// the FIFO tie-break does not use it.
|
||||
// Tuple: (depth, idx, j_id, occ, other, from_a)
|
||||
let mut queue: VecDeque<(usize, usize, u64, u64, u64, bool)> = VecDeque::new();
|
||||
// A datum joint (a plane or axis snap) anchors its part to the design's own frame rather
|
||||
// than to another part: where one competes with a chain out of a grounded occurrence, the
|
||||
// chain keeps the part — at any depth — and the datum joint closes a loop on it. So with a
|
||||
// datum snap among the joints, every fixed occurrence but the root is walked to exhaustion
|
||||
// before the root's joints. Without one, the seeds keep their pre-change order (the root
|
||||
// first, then the grounded occurrences in id order), so assemblies built of the existing
|
||||
// snaps alone solve exactly as before.
|
||||
let datum = joints
|
||||
.iter()
|
||||
.any(|j| matches!(j.a.snap, Snap::Plane { .. } | Snap::Axis { .. }) || matches!(j.b.snap, Snap::Plane { .. } | Snap::Axis { .. }));
|
||||
let waves: Vec<Vec<u64>> =
|
||||
if datum { vec![placed.keys().copied().filter(|&o| o != 0).collect(), vec![0]] } else { vec![placed.keys().copied().collect()] };
|
||||
for seeds in waves {
|
||||
for occ in seeds {
|
||||
for &(idx, j) in at.get(&occ).map(Vec::as_slice).unwrap_or_default() {
|
||||
if !tree.frames.contains_key(&j.id) {
|
||||
continue;
|
||||
}
|
||||
let (other, from_a) = if j.a.occurrence == occ {
|
||||
(j.b.occurrence, true)
|
||||
} else if j.b.occurrence == occ {
|
||||
(j.a.occurrence, false)
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
if !placed.contains_key(&other) {
|
||||
queue.push_back((1, idx, j.id, occ, other, from_a));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while let Some((depth, _, j_id, occ, other, from_a)) = queue.pop_front() {
|
||||
if placed.contains_key(&other) || used.contains(&j_id) {
|
||||
continue;
|
||||
}
|
||||
let (other, from_a) = if j.a.occurrence == occ {
|
||||
(j.b.occurrence, true)
|
||||
} else if j.b.occurrence == occ {
|
||||
(j.a.occurrence, false)
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
if placed.contains_key(&other) {
|
||||
continue;
|
||||
}
|
||||
let Some(m) = tree.step(j.id, from_a, &t, vals) else { continue };
|
||||
used.insert(j.id);
|
||||
let Some(t) = placed.get(&occ).copied() else { continue };
|
||||
let Some(m) = tree.step(j_id, from_a, &t, vals) else { continue };
|
||||
used.insert(j_id);
|
||||
placed.insert(other, m);
|
||||
tree.parent.insert(other, (occ, j.id, from_a));
|
||||
depths.insert(other, depth);
|
||||
tree.parent.insert(other, (occ, j_id, from_a));
|
||||
tree.order.push(other);
|
||||
let (mut own, mut common) = moved_by.get(&occ).cloned().unwrap_or_default();
|
||||
for v in (0..j.kind.dofs().len()).map(|i| (j.id, i)) {
|
||||
match sources.get(&v) {
|
||||
Some(from) => common.extend(from.iter().copied()),
|
||||
None if shared.contains(&v) => {
|
||||
common.insert(v);
|
||||
if let Some(j) = tree.joints.get(&j_id) {
|
||||
for v in (0..j.kind.dofs().len()).map(|i| (j.id, i)) {
|
||||
match sources.get(&v) {
|
||||
Some(from) => common.extend(from.iter().copied()),
|
||||
None if shared.contains(&v) => {
|
||||
common.insert(v);
|
||||
}
|
||||
None => own += 1,
|
||||
}
|
||||
None => own += 1,
|
||||
}
|
||||
}
|
||||
dof.insert(other, own + common.len());
|
||||
moved_by.insert(other, (own, common));
|
||||
queue.push_back(other);
|
||||
let next_depth = depth + 1;
|
||||
for &(idx, next_j) in at.get(&other).map(Vec::as_slice).unwrap_or_default() {
|
||||
if used.contains(&next_j.id) || !tree.frames.contains_key(&next_j.id) {
|
||||
continue;
|
||||
}
|
||||
let (next_other, next_from_a) = if next_j.a.occurrence == other {
|
||||
(next_j.b.occurrence, true)
|
||||
} else if next_j.b.occurrence == other {
|
||||
(next_j.a.occurrence, false)
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
if !placed.contains_key(&next_other) {
|
||||
queue.push_back((next_depth, idx, next_j.id, other, next_other, next_from_a));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Joints that close loops: the solve moves the loops' values to meet them, then checks they
|
||||
// agree.
|
||||
let closing: Vec<u64> = joints
|
||||
@@ -2230,6 +2571,8 @@ pub fn frame_of(o: Vec3, z: Vec3, x: Option<Vec3>) -> Option<Mat> {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::FeatureKind;
|
||||
use crate::construct::DatumItem;
|
||||
|
||||
thread_local! {
|
||||
pub(super) static PLACEMENT_STEPS: std::cell::Cell<usize> = const { std::cell::Cell::new(0) };
|
||||
@@ -2393,7 +2736,7 @@ mod tests {
|
||||
/// Revolute joints 1…n (joint 1 at `start`, the others at 0) linked 1 → 2 → … → n with
|
||||
/// ratio 2, the links stored from the end of the chain; joint 3 limited to ±50.
|
||||
pub(super) fn chain(n: u64, start: f64) -> Assembly {
|
||||
let origin = JointOrigin { occurrence: 0, snap: Snap::Point { point: Vec3::ZERO, z: None, x: None } };
|
||||
let origin = JointOrigin::new(0, Snap::Point { point: Vec3::ZERO, z: None, x: None });
|
||||
let joints = (1..=n)
|
||||
.map(|id| Joint {
|
||||
id,
|
||||
@@ -2468,7 +2811,7 @@ mod tests {
|
||||
let back = serde_json::to_value(&l).unwrap();
|
||||
assert_eq!(back["coupling"], serde_json::json!({"type": "gear", "ra": 10.0, "rb": "r2 * 2", "internal": true}));
|
||||
let picked: Size = serde_json::from_str(r#"{"occurrence": 3, "snap": {"type": "circle_center", "pick": [1, 0, 0]}}"#).unwrap();
|
||||
assert!(matches!(picked, Size::Circle(JointOrigin { occurrence: 3, snap: Snap::CircleCenter { .. } })));
|
||||
assert!(matches!(picked, Size::Circle(JointOrigin { occurrence: 3, snap: Snap::CircleCenter { .. }, .. })));
|
||||
let screw: Coupling = serde_json::from_str(r#"{"type": "screw", "pitch": 1.5, "reverse": true}"#).unwrap();
|
||||
assert_eq!(screw, Coupling::Screw { pitch: Size::Length(1.5), reverse: true });
|
||||
}
|
||||
@@ -2550,4 +2893,106 @@ mod tests {
|
||||
assert_eq!(values, vec![vec![0.0], vec![0.75]]);
|
||||
assert!(!doc.apply_joint_solution(&Solution { world, ..Solution::default() }), "applied twice, nothing moves");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn resolve_plane_and_axis_origins() {
|
||||
let mut doc = Document::default();
|
||||
// The constructs are features: registered in the document (the owner the side resolvers
|
||||
// check against), with their evaluated geometry in the model state.
|
||||
let spine_feature = doc
|
||||
.add_feature(
|
||||
FeatureKind::ConstructionAxis {
|
||||
def: crate::construct::AxisDef::TwoPoints {
|
||||
a: crate::construct::GeoRef::Point { p: Vec3::ZERO },
|
||||
b: crate::construct::GeoRef::Point { p: Vec3::new(0.0, 0.0, 50.0) },
|
||||
},
|
||||
},
|
||||
Some("Spine"),
|
||||
)
|
||||
.unwrap();
|
||||
let plane_feature =
|
||||
doc.add_feature(FeatureKind::ConstructionPlane { plane: PlaneRef::Origin { name: "XY".into() } }, Some("WorkPlane")).unwrap();
|
||||
let mut st = ModelState::default();
|
||||
st.construct.push(crate::construct::Construct {
|
||||
feature: spine_feature,
|
||||
name: "Spine".into(),
|
||||
geom: ConstructGeom::Axis { origin: Vec3::new(10.0, 5.0, 0.0), dir: Vec3::Z },
|
||||
bodies: Vec::new(),
|
||||
});
|
||||
st.construct.push(crate::construct::Construct {
|
||||
feature: plane_feature,
|
||||
name: "WorkPlane".into(),
|
||||
geom: ConstructGeom::Plane(Plane::new(Vec3::new(0.0, 0.0, 15.0), Vec3::X, Vec3::Y).unwrap()),
|
||||
bodies: Vec::new(),
|
||||
});
|
||||
|
||||
// 1. Origin plane XY
|
||||
let o_xy = JointOrigin::new(0, Snap::Plane { plane: Box::new(PlaneRef::Origin { name: "XY".into() }), pick: None, x: None });
|
||||
let m = resolve_origin(&doc, &st, &o_xy).unwrap();
|
||||
assert_eq!(apply_point(&m, Vec3::ZERO), Vec3::ZERO);
|
||||
assert_eq!(apply_vector(&m, Vec3::Z), Vec3::Z);
|
||||
|
||||
// 2. Origin plane XY with pick projected
|
||||
let o_xy_pick = JointOrigin::new(
|
||||
0,
|
||||
Snap::Plane { plane: Box::new(PlaneRef::Origin { name: "XY".into() }), pick: Some(Vec3::new(12.0, 34.0, 56.0)), x: None },
|
||||
);
|
||||
let m_pick = resolve_origin(&doc, &st, &o_xy_pick).unwrap();
|
||||
assert_eq!(apply_point(&m_pick, Vec3::ZERO), Vec3::new(12.0, 34.0, 0.0));
|
||||
|
||||
// 3. Construction plane by feature (PlaneRef::Construction: the name-overload of
|
||||
// PlaneRef::Origin is gone — a construction plane is a feature, bound to its
|
||||
// component).
|
||||
let o_wp =
|
||||
JointOrigin::new(0, Snap::Plane { plane: Box::new(PlaneRef::Construction { feature: plane_feature.into() }), pick: None, x: None });
|
||||
let m_wp = resolve_origin(&doc, &st, &o_wp).unwrap();
|
||||
assert_eq!(apply_point(&m_wp, Vec3::ZERO), Vec3::new(0.0, 0.0, 15.0));
|
||||
assert_eq!(apply_vector(&m_wp, Vec3::Z), Vec3::Z);
|
||||
|
||||
// 4. Origin axis Z
|
||||
let o_z = JointOrigin::new(0, Snap::Axis { axis: Box::new(AxisRef::origin("Z")), pick: None, x: None });
|
||||
let m_z = resolve_origin(&doc, &st, &o_z).unwrap();
|
||||
assert_eq!(apply_point(&m_z, Vec3::ZERO), Vec3::ZERO);
|
||||
assert_eq!(apply_vector(&m_z, Vec3::Z), Vec3::Z);
|
||||
|
||||
// 5. Construction axis
|
||||
let o_spine = JointOrigin::new(0, Snap::Axis { axis: Box::new(AxisRef::Name("Spine".into())), pick: None, x: None });
|
||||
let m_spine = resolve_origin(&doc, &st, &o_spine).unwrap();
|
||||
assert_eq!(apply_point(&m_spine, Vec3::ZERO), Vec3::new(10.0, 5.0, 0.0));
|
||||
assert_eq!(apply_vector(&m_spine, Vec3::Z), Vec3::Z);
|
||||
|
||||
// 6. A placement's datum, on a side of that placement: the XY datum of a moved
|
||||
// occurrence, in its component's own frame (the exact placement, not a first one).
|
||||
let mut placed = Document::new("placed");
|
||||
let comp = placed.add_component(Some("Part"), 0).unwrap();
|
||||
let occ = placed.occurrences.iter().find(|o| o.component == comp).unwrap().id;
|
||||
let away: crate::Mat = [[1.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0], [100.0, 0.0, 0.0, 1.0]];
|
||||
placed.occurrences.iter_mut().find(|o| o.id == occ).unwrap().transform = away;
|
||||
let datum = DatumRef { path: vec![occ], item: DatumItem::XY };
|
||||
let o_datum =
|
||||
JointOrigin::new(occ, Snap::Plane { plane: Box::new(PlaneRef::Datum { datum }), pick: Some(Vec3::new(3.0, 0.0, 7.0)), x: None });
|
||||
let m_datum = resolve_origin(&placed, &st, &o_datum).unwrap();
|
||||
assert_eq!(apply_point(&m_datum, Vec3::ZERO), Vec3::new(3.0, 0.0, 0.0), "the pick, projected onto the component's own XY");
|
||||
assert_eq!(apply_vector(&m_datum, Vec3::Z), Vec3::Z);
|
||||
let o_datum_axis = JointOrigin::new(
|
||||
occ,
|
||||
Snap::Axis { axis: Box::new(AxisRef::datum(DatumRef { path: vec![occ], item: DatumItem::X })), pick: None, x: None },
|
||||
);
|
||||
let m_axis = resolve_origin(&placed, &st, &o_datum_axis).unwrap();
|
||||
assert_eq!(apply_point(&m_axis, Vec3::ZERO), Vec3::ZERO, "the component's own X datum in its own frame");
|
||||
assert_eq!(apply_vector(&m_axis, Vec3::Z), Vec3::X);
|
||||
|
||||
// 7. Serde roundtrip (plane and geometry axis)
|
||||
let json = serde_json::to_string(&o_xy).unwrap();
|
||||
let decoded: JointOrigin = serde_json::from_str(&json).unwrap();
|
||||
assert_eq!(o_xy, decoded);
|
||||
|
||||
let o_geo = JointOrigin::new(
|
||||
0,
|
||||
Snap::Axis { axis: Box::new(AxisRef::geo(crate::construct::GeoRef::World { axis: "Z".into() })), pick: None, x: None },
|
||||
);
|
||||
let json_geo = serde_json::to_string(&o_geo).unwrap();
|
||||
let decoded_geo: JointOrigin = serde_json::from_str(&json_geo).unwrap();
|
||||
assert_eq!(o_geo, decoded_geo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -930,7 +930,7 @@ mod tests {
|
||||
/// a guide only on the cam's own side is refused.
|
||||
#[test]
|
||||
fn the_guide_is_the_side_fewer_moving_joints_from_the_frame() {
|
||||
let origin = JointOrigin { occurrence: 0, snap: super::super::Snap::Point { point: Vec3::ZERO, z: None, x: None } };
|
||||
let origin = JointOrigin::new(0, super::super::Snap::Point { point: Vec3::ZERO, z: None, x: None });
|
||||
let joint = |id: u64, kind: JointKind, a: u64, b: u64| super::super::Joint {
|
||||
id,
|
||||
name: format!("J{id}"),
|
||||
|
||||
@@ -27,7 +27,7 @@ pub fn relation_values(doc: &Document, st: &ModelState, j: &Joint) -> Option<Vec
|
||||
// B's joint frame in A's as it is.
|
||||
let now = mat_mul(&mat_inverse(&fa)?, &fb);
|
||||
// A turn weighs as far as it moves a point B's size away.
|
||||
let size = component_of(doc, j.b.occurrence).map(|c| component_bodies(doc, st, c).iter().map(|b| b.body.size()).fold(0.0, f64::max));
|
||||
let size = component_of(doc, j.b.part()).map(|c| component_bodies(doc, st, c).iter().map(|b| b.body.size()).fold(0.0, f64::max));
|
||||
let scale = size.unwrap_or(0.0).clamp(1.0, 1e5);
|
||||
let n = j.kind.dofs().len();
|
||||
let angles: Vec<usize> = (0..n).filter(|i| j.kind.is_angle(*i)).collect();
|
||||
@@ -79,7 +79,7 @@ mod tests {
|
||||
use solidcore_record::Vec3;
|
||||
|
||||
fn joint(kind: JointKind) -> Joint {
|
||||
let at = |occurrence| JointOrigin { occurrence, snap: Snap::Point { point: Vec3::ZERO, z: None, x: None } };
|
||||
let at = |occurrence| JointOrigin::new(occurrence, Snap::Point { point: Vec3::ZERO, z: None, x: None });
|
||||
Joint {
|
||||
id: 1,
|
||||
name: "R".into(),
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user