Compare commits

..

48 Commits

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

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

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

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

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

This reverts commit cac4bccea8.

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

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

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

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

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

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

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

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

* CI: a test filter YAML parses

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

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

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

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

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

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

---------

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

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

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

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

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

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

---------

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

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

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

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 12:56:47 +00:00
749 changed files with 4784 additions and 129935 deletions
+6 -113
View File
@@ -15,9 +15,7 @@
# nightly. The reference tests and the doc tests run in the merge queue, on main and nightly, not
# on pull requests (the fast lane, in Select checks); a break there is fixed forward on main. The
# Windows jobs (D3D12 shaders and app startup) run nightly, and in the merge queue only for a group
# that changes what they exercise. The wasm compile check runs in the merge queue for a group that
# touches the crates below the apps, the web app or the manifests. Dependency advisories run nightly
# and on any pull request or merge group that changes Cargo.lock or a Cargo.toml. Only main saves the build caches; pull requests restore them.
# that changes what they exercise. Only main saves the build caches; pull requests restore them.
# sccache is on a Blacksmith sticky disk that only main commits.
# A push to main runs only the repository checks when a passing merge-queue run tested that very
# commit, or when nothing a build reads changed since the last push to main whose run passed.
@@ -80,13 +78,8 @@ env:
jobs:
dependency-advisories:
# Nightly and by hand: advisories, bans and sources for everything. A pull request or merge
# group that changes Cargo.lock or a Cargo.toml (Select checks' `deps`) checks the advisories
# only, so a dependency with a known vulnerability is caught before it lands, not the next
# morning; other pull requests skip it. `ci` requires it whenever `deps` is true.
name: Dependency advisories
needs: changes
if: ${{ !cancelled() && (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || needs.changes.outputs.deps == 'true') }}
if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
runs-on: blacksmith-4vcpu-ubuntu-2404
timeout-minutes: 20
steps:
@@ -95,12 +88,7 @@ jobs:
- name: Install advisory scanner
run: cargo install cargo-deny --version 0.20.2 --locked
- name: Check locked dependencies
if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
run: cargo deny --locked check --warn unmaintained advisories bans sources
# deny.toml denies unmaintained crates; like the nightly, they are reported, not fatal.
- name: Check advisories for the changed dependencies
if: github.event_name != 'schedule' && github.event_name != 'workflow_dispatch'
run: cargo deny --locked check --warn unmaintained advisories
changes:
name: Select checks
@@ -127,10 +115,6 @@ jobs:
packages: ${{ steps.paths.outputs.packages }}
oracle: ${{ steps.paths.outputs.oracle }}
doctests: ${{ steps.paths.outputs.doctests }}
# Cargo.lock or a Cargo.toml changed (pull requests and merge groups): Dependency advisories.
deps: ${{ steps.paths.outputs.deps }}
# A merge group reaches the wasm build: Compile WebAssembly.
wasm: ${{ steps.paths.outputs.wasm }}
# The passing run a merge of main carries forward (its URL), when this push is only that.
carried: ${{ steps.paths.outputs.carried }}
steps:
@@ -159,8 +143,6 @@ jobs:
goldens=false
windows=false
gpu_paths=false
deps=false
wasm=false
full=true
packages=
# Whether the NUL-separated paths in $1 reach any code: scripts/ci/affected.py selects
@@ -201,21 +183,6 @@ jobs:
esac
done < "$1"
}
# Whether the NUL-separated paths in $1 change the dependencies (Cargo.lock or any
# Cargo.toml: deps), and whether they reach what `cargo xtask wasm` compiles (wasm): the
# crates below the apps, the web app, the vendored crates, the manifests and lockfile, the
# toolchain and cargo config, and this workflow. #8227 put a native-only call in
# crates/ui-egui and the merge queue passed it, because nothing built for wasm there.
deps_wasm_paths() {
while IFS= read -r -d '' path; do
case "$path" in
Cargo.lock|Cargo.toml|*/Cargo.toml) deps=true ;;
esac
case "$path" in
crates/*|apps/solidcraft-web/*|vendor/*|Cargo.lock|Cargo.toml|rust-toolchain*|.cargo/*|.github/workflows/ci.yml) wasm=true ;;
esac
done < "$1"
}
# Opt-in for a big render change: a pull request labelled render-tests, or a merge group
# holding one (its pull requests are the (#N) of its squash commits), runs them whatever
# the paths say.
@@ -261,17 +228,14 @@ jobs:
if git diff --no-renames --name-only -z "$GROUP_BASE_SHA...$GROUP_HEAD_SHA" > "$RUNNER_TEMP/ci-paths"; then
windows_paths "$RUNNER_TEMP/ci-paths" "$GROUP_BASE_SHA...$GROUP_HEAD_SHA"
gpu_paths "$RUNNER_TEMP/ci-paths"
deps_wasm_paths "$RUNNER_TEMP/ci-paths"
if [ "$gpu_paths" = false ] && group_has_render_label "$GROUP_BASE_SHA..$GROUP_HEAD_SHA"; then
gpu_paths=true
fi
else
windows=true
gpu_paths=true
deps=true
wasm=true
fi
echo "windows=$windows gpu_paths=$gpu_paths deps=$deps wasm=$wasm for $GROUP_BASE_SHA...$GROUP_HEAD_SHA"
echo "windows=$windows gpu_paths=$gpu_paths for $GROUP_BASE_SHA...$GROUP_HEAD_SHA"
elif [ "$EVENT_NAME" != pull_request ]; then
# The nightly run and Run workflow: everything, Windows included.
native=true
@@ -292,10 +256,6 @@ jobs:
done < "$RUNNER_TEMP/ci-paths"
# Computed as for a merge group, then turned off below (the fast lane).
windows_paths "$RUNNER_TEMP/ci-paths" "$BASE_SHA...$HEAD_SHA"
# The advisories run on the pull request itself (it builds nothing of ours: about two minutes, most of it installing cargo-deny);
# the wasm compile waits for the merge queue.
deps_wasm_paths "$RUNNER_TEMP/ci-paths"
wasm=false
# Pull requests build and test the touched packages and their dependents; nothing
# selected means no code changed.
select_packages "$RUNNER_TEMP/ci-paths"
@@ -367,8 +327,6 @@ jobs:
echo "windows=$windows"
echo "oracle=$oracle"
echo "doctests=$doctests"
echo "deps=$deps"
echo "wasm=$wasm"
echo "carried=$carried"
echo "full=$full"
echo "quick=$quick"
@@ -406,9 +364,6 @@ jobs:
cargo test -p xtask ui_containers --locked
- name: Sorted lists
run: cargo xtask lists
# New UI text must reach every complete catalog; report it here, before review (#8542).
- name: Translations in the complete catalogs
run: cargo xtask i18n --check
- name: Agent router and skills cite real files
run: |
cargo xtask skills
@@ -988,7 +943,7 @@ jobs:
# commit's real run instead: the merge queue reads `ci` from the newest run of a commit, so a
# run without a passing `ci` would block a pull request that passed (#1850, #3182, #3252).
name: ci
needs: [changes, checks, quick-compile, clippy, build-tests, tests, gpu-path-tests, doc-tests, oracle, windows-fxc, windows-startup, dependency-advisories, wasm]
needs: [changes, checks, quick-compile, clippy, build-tests, tests, gpu-path-tests, doc-tests, oracle, windows-fxc, windows-startup]
if: always() && (github.event_name != 'pull_request' || !github.event.pull_request.draft)
runs-on: blacksmith-2vcpu-ubuntu-2404
permissions:
@@ -1042,10 +997,6 @@ jobs:
ORACLE: ${{ needs.oracle.result }}
WINDOWS_FXC: ${{ needs.windows-fxc.result }}
WINDOWS_STARTUP: ${{ needs.windows-startup.result }}
DEPS_RUN: ${{ needs.changes.outputs.deps }}
ADVISORIES: ${{ needs.dependency-advisories.result }}
WASM_RUN: ${{ needs.changes.outputs.wasm }}
WASM: ${{ needs.wasm.result }}
run: |
test "$CHANGES" = success
test "$CHECKS" = success
@@ -1075,14 +1026,6 @@ jobs:
test "$WINDOWS_FXC" = success
test "$WINDOWS_STARTUP" = success
fi
# Cargo.lock or a Cargo.toml changed on a pull request or in a merge group.
if [ "$DEPS_RUN" = true ]; then
test "$ADVISORIES" = success
fi
# A merge group that reaches the wasm build.
if [ "$WASM_RUN" = true ]; then
test "$WASM" = success
fi
- name: Note a carried result
if: needs.changes.outputs.carried != ''
env:
@@ -1090,13 +1033,9 @@ jobs:
run: |
echo "This push only merges main into a change that already passed; the heavy checks were not repeated. Passing run: $CARRIED" >> "$GITHUB_STEP_SUMMARY"
# Every crate below the apps and the web app must build for the browser (`cargo xtask wasm`, a
# cargo check, no tests). In the merge queue for a group that reaches the wasm build (Select
# checks' `wasm`), where `ci` requires it; by hand with cross_compile.
wasm:
name: Compile WebAssembly
needs: changes
if: ${{ !cancelled() && ((github.event_name == 'workflow_dispatch' && inputs.cross_compile) || needs.changes.outputs.wasm == 'true') }}
name: Compile WebAssembly (manual)
if: github.event_name == 'workflow_dispatch' && inputs.cross_compile
runs-on: blacksmith-8vcpu-ubuntu-2404
timeout-minutes: 30
steps:
@@ -1157,49 +1096,3 @@ jobs:
. "$HOME/.cargo/env"
export CRAFT_FONTS_DIR="$PWD/craft-fonts"
cargo check --all-targets --locked --target riscv64gc-unknown-linux-gnu
# Nobody watches the nightly run, and it failed every day from 2026-10-16 to 2026-10-28 before
# anyone noticed. When a nightly fails, open one issue, "Nightly CI is failing" (label `ci`), or
# comment on it if it is already open; when a nightly passes, close it. A nightly that neither
# failed nor fully passed (cancelled) leaves the issue as it is. The only job that may write issues.
nightly-alert:
name: Nightly alert
needs: [dependency-advisories, changes, checks, ci, build-tests, action-matrix, action-matrix-determinism, property-tests]
if: always() && github.event_name == 'schedule'
runs-on: blacksmith-2vcpu-ubuntu-2404
timeout-minutes: 5
permissions:
issues: write
steps:
- name: Open, update or close the nightly issue
env:
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}
RESULTS: ${{ toJSON(needs) }}
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
SHA: ${{ github.sha }}
run: |
title="Nightly CI is failing"
failed=$(jq -r 'to_entries[] | select(.value.result == "failure") | .key' <<<"$RESULTS")
unfinished=$(jq -r 'to_entries[] | select(.value.result != "success" and .value.result != "failure") | "\(.key) (\(.value.result))"' <<<"$RESULTS")
issue=$(gh issue list --state open --label ci --limit 100 --json number,title \
--jq "[.[] | select(.title == \"$title\")] | first | .number // empty")
if [ -n "$failed" ]; then
body="The nightly run on ${SHA:0:9} failed: $RUN_URL
Failed jobs: $(paste -sd , - <<<"$failed" | sed 's/,/, /g')."
if [ -n "$issue" ]; then
gh issue comment "$issue" --body "$body"
else
gh issue create --title "$title" --label ci --body "$body
This issue is opened and updated by the nightly run (the nightly-alert job in .github/workflows/ci.yml) and closed by the first nightly that passes."
fi
elif [ -z "$unfinished" ]; then
if [ -n "$issue" ]; then
gh issue close "$issue" --comment "The nightly run on ${SHA:0:9} passed: $RUN_URL"
fi
echo "The nightly passed."
else
echo "Nothing failed, but not every job finished: $unfinished. The issue is left as it is."
fi
-1
View File
@@ -52,7 +52,6 @@ jobs:
# effort: a fork PR just doesn't get the `changes-default` label from here.
label:
name: Label changes-default
if: github.event.pull_request.head.repo.full_name == github.repository
runs-on: ubuntu-24.04
timeout-minutes: 5
continue-on-error: true
+2 -42
View File
@@ -10,7 +10,6 @@
# (see the windows job). Nothing else is signed yet.
#
# Linux x86_64, aarch64 AppImage (+ .zsync), .deb, .rpm, .flatpak, .snap, .tar.gz packaging/linux
# Arch Linux x86_64, aarch64 .pkg.tar.zst, repackaged from the .tar.gz the arch job
# FreeBSD x86_64 .tar.gz (built in a FreeBSD VM) packaging/freebsd
# macOS universal .dmg, and the CLI as a .zip (both archs built in parallel) packaging/macos
# Windows x64, x86, arm64 .msi and a portable .zip; x64 also the plain .exe packaging/windows
@@ -207,45 +206,6 @@ jobs:
path: dist/release/*.flatpak
if-no-files-found: error
arch:
name: Arch Linux ${{ matrix.arch }}
needs: [version, linux]
if: needs.version.outputs.build == 'true'
# makepkg only repackages the tarball's prebuilt binaries, so both architectures build here.
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix:
arch: [x86_64, aarch64]
env:
VERSION: ${{ needs.version.outputs.version }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: release-linux-${{ matrix.arch }}
path: dist/linux
# The Craft apps' shared Arch packaging (storytold/craft-common-actions, MIT OR Apache-2.0):
# makepkg in an archlinux:base-devel container. The package is named after the tarball's
# .desktop file (io.tangencylabs.solidcraft) and written as
# dist/release/solidcraft-<version>-linux-<arch>.pkg.tar.zst.
- uses: storytold/craft-common-actions/actions/arch-package@fa5ef18780cf5e7d5d3b8de068de56cffc83cac5 # main
with:
tarball: dist/linux/solidcraft-${{ env.VERSION }}-linux-${{ matrix.arch }}.tar.gz
arch: ${{ matrix.arch }}
- name: Check the package
env:
PKG: dist/release/solidcraft-${{ env.VERSION }}-linux-${{ matrix.arch }}.pkg.tar.zst
run: |
tar --zstd -tf "$PKG" | grep -E '^usr/bin/solidcraft$|^usr/bin/solidcraft-cli$|^usr/share/applications/io\.tangencylabs\.solidcraft\.desktop$'
tar --zstd -xOf "$PKG" .PKGINFO | grep -E '^(pkgname|pkgver|arch) = '
tar --zstd -xOf "$PKG" .PKGINFO | grep -qx 'pkgname = io.tangencylabs.solidcraft'
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: release-arch-${{ matrix.arch }}
path: dist/release/*.pkg.tar.zst
if-no-files-found: error
snap:
@@ -611,7 +571,7 @@ jobs:
release:
name: GitHub Release or dry-run artifacts
needs: [version, linux, flatpak, arch, snap, freebsd, macos, windows, web]
needs: [version, linux, flatpak, snap, freebsd, macos, windows, web]
if: needs.version.outputs.build == 'true'
runs-on: ubuntu-latest
permissions:
@@ -637,7 +597,7 @@ jobs:
shopt -s nullglob
for f in "solidcraft-$VERSION-"*; do
case "$f" in
*.msi | *-portable.zip | *.dmg | *.AppImage | *.deb | *.rpm | *.flatpak | *.snap | *.pkg.tar.zst)
*.msi | *-portable.zip | *.dmg | *.AppImage | *.deb | *.rpm | *.flatpak | *.snap)
cp -- "$f" "solidcraft-${f#"solidcraft-$VERSION-"}" ;;
esac
done
-25
View File
@@ -603,31 +603,6 @@ Original SolidCraft drawings, Open for owner review; no runtime assignments.
| assets/icons/ui/design/svg/model/finish_edit.svg | SolidCraft contributors | original icon master (64 grid) | MIT OR Apache-2.0 |
| `assets/locales/pending/sketch-tracking-guides.json` | SolidCraft contributors | Original alignment-guide preference labels and help text | MIT OR Apache-2.0 |
| assets/locales/pending/point-clouds.json | SolidCraft contributors | Original point-cloud UI strings and translations | MIT OR Apache-2.0 |
| assets/icons/ui/design/svg/model/feature_group.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
| assets/icons/ui/design/svg/model/mesh_body.svg | SolidCraft contributors | two-tone modelling icon master (64 grid), original SolidCraft artwork | MIT OR Apache-2.0 |
| assets/icons/ui/design/svg/model/timeline_play.svg | SolidCraft contributors | Original history playback icon; canonical grey_cube base and original action cue | MIT OR Apache-2.0 |
| assets/icons/ui/design/svg/model/timeline_stop.svg | SolidCraft contributors | Original history playback icon; canonical grey_cube base and original action cue | MIT OR Apache-2.0 |
| assets/icons/ui/design/svg/flat/status_pin.svg | SolidCraft contributors | Original analytic pin icon for persistent viewport results | MIT OR Apache-2.0 |
| assets/locales/pending/render-wear.json | SolidCraft contributors | Original UI labels and translations | MIT OR Apache-2.0 |
| 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 |
| 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 |
| 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 |
| docs/book/src/generated/equation-line.png | SolidCraft contributors | rendered by `cargo xtask book` (`solidcraft-cli snapshot docs/book/scripts/equation-line.json`; gitignored) | MIT OR Apache-2.0 |
| 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 |
## Code adapted from sibling projects
+2 -10
View File
@@ -117,8 +117,7 @@ The [architecture page](docs/architecture.md) has the layer table. The short ver
not.) Permissive
dependencies are fine. Note which one you're adding and why in the PR. THIRD-PARTY-LICENSES.txt
lists it once the change lands: the Generated files workflow rewrites it on `main`.
Nightly/manual CI also scans advisories, bans and sources with cargo-deny, and a PR that
changes Cargo.lock or a Cargo.toml checks the advisories; see
Nightly/manual CI also scans advisories, bans and sources with cargo-deny; see
[the local command and coverage limits](docs/book/src/dev/testing.md#dependency-advisories).
3. **Every asset is original or openly licensed and has a row in
[ATTRIBUTION.md](ATTRIBUTION.md).** Icons are drawn in code (`crates/ui-egui/src/icons.rs`).
@@ -279,11 +278,6 @@ Some files gain an item in many pull requests at once. They are kept so that two
each add an item only meet when their items are neighbours, which spares everyone a conflict
and a fresh CI run:
- **Growing Rust lists**: use slices (`const ITEMS: &[Item] = &[...];`) without a written
length. `cargo xtask lists` rejects non-test const/static arrays with more than ten lines
of entries, except fixed standard or algorithm tables listed with reasons in `xtask/src/lists.rs`.
Built-in themes need only a JSON file in `assets/styles/ui/themes/`, with a unique nonnegative
integer `order` (the picker order) and its own `provenance` line; keep existing order values.
- **Message catalogs** (`assets/locales/*.json`): one message per line, sorted by id. Add your
message anywhere and run `cargo xtask lists --fix`; `cargo xtask lists` (in `cargo xtask ci`
and the Lists workflow) fails on an unsorted catalog or an id that appears twice.
@@ -306,9 +300,7 @@ and a fresh CI run:
- **Design format**: one file per change, never an edit to a shared number (above).
- **New UI strings and attribution rows**: one new file per change, `assets/locales/pending/<slug>.json`
and `attribution/pending/<slug>.md`, instead of editing the catalogs or the ATTRIBUTION.md table;
`cargo xtask fold-pending` folds them on `main` (see the README in each folder). A new English
message also needs every catalog delivered complete (`COMPLETE` in `crates/ui-egui/src/i18n.rs`:
today ar, he, ja, vi, and zh) in the same pending file; `cargo xtask i18n --check` reports any gap.
`cargo xtask fold-pending` folds them on `main` (see the README in each folder).
## Sending a change
Generated
+24 -23
View File
@@ -3773,9 +3773,9 @@ checksum = "eec689c0bc40ff2458a5977b6619cb718087084a18e02a131c599b62d05e1a5f"
[[package]]
name = "rustls-webpki"
version = "0.103.16"
version = "0.103.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4443b1b6d39d7c663139942cc4558262562d2c84123bb6282ef177009ca8b281"
checksum = "f3c3cf1d8b1e7d4927e2d154c3fcb02979afb9939629c62cd9048d4f07b60ac2"
dependencies = [
"ring",
"rustls-pki-types",
@@ -4210,7 +4210,7 @@ dependencies = [
[[package]]
name = "solidcraft"
version = "0.27.1"
version = "0.26.0"
dependencies = [
"block2 0.6.2",
"eframe",
@@ -4235,7 +4235,6 @@ dependencies = [
"serde_json",
"solidcraft-3dx-client",
"solidcraft-engine",
"solidcraft-gpu",
"solidcraft-space-mouse",
"solidcraft-ui-egui",
"ureq",
@@ -4246,11 +4245,11 @@ dependencies = [
[[package]]
name = "solidcraft-3dx-client"
version = "0.27.1"
version = "0.26.0"
[[package]]
name = "solidcraft-cli"
version = "0.27.1"
version = "0.26.0"
dependencies = [
"image",
"log",
@@ -4262,7 +4261,7 @@ dependencies = [
[[package]]
name = "solidcraft-derive"
version = "0.27.1"
version = "0.26.0"
dependencies = [
"proc-macro2",
"quote",
@@ -4271,7 +4270,7 @@ dependencies = [
[[package]]
name = "solidcraft-doc"
version = "0.27.1"
version = "0.26.0"
dependencies = [
"log",
"serde",
@@ -4288,7 +4287,7 @@ dependencies = [
[[package]]
name = "solidcraft-engine"
version = "0.27.1"
version = "0.26.0"
dependencies = [
"image",
"log",
@@ -4309,7 +4308,7 @@ dependencies = [
[[package]]
name = "solidcraft-geom"
version = "0.27.1"
version = "0.26.0"
dependencies = [
"serde",
"serde_json",
@@ -4318,7 +4317,7 @@ dependencies = [
[[package]]
name = "solidcraft-gpu"
version = "0.27.1"
version = "0.26.0"
dependencies = [
"image",
"log",
@@ -4338,7 +4337,7 @@ dependencies = [
[[package]]
name = "solidcraft-io"
version = "0.27.1"
version = "0.26.0"
dependencies = [
"cadmpeg-core",
"cadmpeg-ir",
@@ -4362,7 +4361,7 @@ dependencies = [
[[package]]
name = "solidcraft-kernel"
version = "0.27.1"
version = "0.26.0"
dependencies = [
"log",
"proptest",
@@ -4382,7 +4381,7 @@ dependencies = [
[[package]]
name = "solidcraft-mcp"
version = "0.27.1"
version = "0.26.0"
dependencies = [
"serde_json",
"solidcraft-engine",
@@ -4391,7 +4390,7 @@ dependencies = [
[[package]]
name = "solidcraft-render"
version = "0.27.1"
version = "0.26.0"
dependencies = [
"image",
"moxcms",
@@ -4405,7 +4404,7 @@ dependencies = [
[[package]]
name = "solidcraft-sketch"
version = "0.27.1"
version = "0.26.0"
dependencies = [
"harfrust",
"serde",
@@ -4418,14 +4417,14 @@ dependencies = [
[[package]]
name = "solidcraft-space-mouse"
version = "0.27.1"
version = "0.26.0"
dependencies = [
"serde",
]
[[package]]
name = "solidcraft-ui-egui"
version = "0.27.1"
version = "0.26.0"
dependencies = [
"arboard",
"egui",
@@ -4455,7 +4454,7 @@ dependencies = [
[[package]]
name = "solidcraft-web"
version = "0.27.1"
version = "0.26.0"
dependencies = [
"eframe",
"egui",
@@ -4566,7 +4565,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd"
dependencies = [
"fastrand",
"getrandom 0.3.4",
"getrandom 0.4.3",
"once_cell",
"rustix 1.1.5",
"windows-sys 0.61.2",
@@ -5363,9 +5362,9 @@ dependencies = [
[[package]]
name = "webpki-root-certs"
version = "1.0.10"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58ec80e73fd8baf57bf0d9615554c75348bda990d6d5bbeab964dd068319fecb"
checksum = "b96554aa2acc8ccdb7e1c9a58a7a68dd5d13bccc69cd124cb09406db612a1c9b"
dependencies = [
"rustls-pki-types",
]
@@ -5846,6 +5845,8 @@ checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650"
[[package]]
name = "winit"
version = "0.30.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6755fa58a9f8350bd1e472d4c3fcc25f824ec358933bba33306d0b63df5978d"
dependencies = [
"ahash",
"android-activity",
@@ -5998,7 +5999,7 @@ checksum = "e450f9b2ed1dff33c94c12589a87338689467b9c4f5d8a5710bd09a847d2c8a7"
[[package]]
name = "xtask"
version = "0.27.1"
version = "0.26.0"
dependencies = [
"proc-macro2",
"serde",
+1 -5
View File
@@ -5,7 +5,7 @@ members = ["crates/*", "apps/*", "xtask"]
exclude = ["vendor"]
[workspace.package]
version = "0.27.1"
version = "0.26.0"
edition = "2024"
license = "MIT OR Apache-2.0"
rust-version = "1.95"
@@ -161,10 +161,6 @@ matext4cgmath = { path = "vendor/matext4cgmath" }
# Keep OpenGL pipelines, resolve textures and CAD callbacks at the same safe sample count.
egui-wgpu = { path = "vendor/egui-wgpu" }
# Deliver trackpad pinch and rotation gestures on Wayland (zwp_pointer_gestures_v1), which
# winit 0.30 never binds and eframe 0.36 still requires winit 0.30.
winit = { path = "vendor/winit" }
# Mutation testing (cargo-mutants, docs/mutation-testing.md): the ci profile with incremental
# builds, since every mutant rebuilds the crates above the one it changes.
[profile.mutants]
+3 -4
View File
@@ -42,8 +42,8 @@
</p>
<p align="center">
<a href="https://trendshift.io/repositories/296178?utm_source=trendshift-badge&utm_medium=badge&utm_campaign=badge-trendshift-296178" target="_blank" rel="noopener noreferrer"><img src="https://trendshift.io/api/badge/trendshift/repositories/296178/daily" alt="tangency-labs%2Fsolidcraft | Trendshift" width="250" height="55"/></a>
<a href="https://trendshift.io/repositories/296178?utm_source=trendshift-badge&utm_medium=badge&utm_campaign=badge-trendshift-296178" target="_blank" rel="noopener noreferrer"><img src="https://trendshift.io/api/badge/trendshift/repositories/296178/daily?language=Rust" alt="tangency-labs%2Fsolidcraft | Trendshift (Rust)" width="250" height="55"/></a>
<a href="https://trendshift.io/repositories/296178?utm_source=trendshift-badge&amp;utm_medium=badge&amp;utm_campaign=badge-trendshift-296178" target="_blank" rel="noopener noreferrer"><img src="https://trendshift.io/api/badge/trendshift/repositories/296178/daily" alt="tangency-labs%2Fsolidcraft | Trendshift" width="250" height="55"/></a>
<a href="https://trendshift.io/repositories/296178?utm_source=trendshift-badge&amp;utm_medium=badge&amp;utm_campaign=badge-trendshift-296178" target="_blank" rel="noopener noreferrer"><img src="https://trendshift.io/api/badge/trendshift/repositories/296178/daily?language=Rust" alt="tangency-labs%2Fsolidcraft | Trendshift (Rust)" width="250" height="55"/></a>
</p>
![SolidCraft: model a Raspberry Pi 4 case from an empty design: a sketch dimensioned with parameters, extrude, fillets and shell, a rim rounded in one pick, standoffs patterned on the board's mounting holes, port cut-outs, vent slots, "Pi 4" engraved in a font, a PETG material with its mass in Properties, and a height change in Parameters](docs/screenshots/demo.gif)
@@ -98,7 +98,7 @@ More commands, the Windows cross-build and the browser build are in [docs/buildi
runs its own design session, or with `--connect` it drives the running app so you can watch.
Claude Code: `claude mcp add solidcraft -- solidcraft-cli mcp`. If a terminal doesn't find
`solidcraft-cli` (older Windows installers don't put it on `PATH`), give its full path (by default
`"C:\\Program Files\\SolidCraft\\solidcraft-cli.exe"`). Tools, access rules and an example session:
`"C:\Program Files\SolidCraft\solidcraft-cli.exe"`). Tools, access rules and an example session:
[docs/mcp.md](docs/mcp.md).
## Scripts
@@ -150,4 +150,3 @@ Tinkercad are trademarks of their respective owners, named only to describe comp
[linux-appimage]: https://github.com/tangency-labs/solidcraft/releases/latest/download/solidcraft-linux-x86_64.AppImage
[snap-store]: https://snapcraft.io/solidcraft
[web-app]: https://solidcraft.io/app
+9 -9
View File
@@ -353,7 +353,7 @@ rustls-native-certs 0.8.5 (Apache-2.0 OR ISC OR MIT)
rustls-pki-types 1.15.1 (MIT OR Apache-2.0)
rustls-platform-verifier 0.7.1 (MIT OR Apache-2.0)
rustls-platform-verifier-android 0.2.0 (MIT OR Apache-2.0)
rustls-webpki 0.103.16 (ISC)
rustls-webpki 0.103.15 (ISC)
rustversion 1.0.23 (MIT OR Apache-2.0)
ruzstd 0.9.1 (MIT)
schannel 0.1.29 (MIT)
@@ -435,7 +435,7 @@ truck-topology 0.6.0 (Apache-2.0)
ttf-parser 0.25.1 (MIT OR Apache-2.0)
twox-hash 2.1.5 (MIT)
type-map 0.5.1 (MIT/Apache-2.0)
typed-path 0.13.0 (MIT OR Apache-2.0)
typed-path 0.12.3 (MIT OR Apache-2.0)
typeid 1.0.3 (MIT OR Apache-2.0)
typenum 1.20.1 (MIT OR Apache-2.0)
uds_windows 1.2.1 (MIT)
@@ -474,7 +474,7 @@ wayland-sys 0.31.11 (MIT)
web-sys 0.3.106 (MIT OR Apache-2.0)
web-time 1.1.0 (MIT OR Apache-2.0)
webbrowser 1.2.4 (MIT OR Apache-2.0)
webpki-root-certs 1.0.10 (CDLA-Permissive-2.0)
webpki-root-certs 1.0.9 (CDLA-Permissive-2.0)
weezl 0.1.12 (MIT OR Apache-2.0)
wgpu 30.0.1 (MIT OR Apache-2.0)
wgpu-core 30.0.1 (MIT OR Apache-2.0)
@@ -552,7 +552,7 @@ zeroize_derive 1.5.0 (Apache-2.0 OR MIT)
zerotrie 0.2.5 (Unicode-3.0)
zerovec 0.11.8 (Unicode-3.0)
zerovec-derive 0.11.6 (Unicode-3.0)
zip 9.1.3 (MIT)
zip 9.0.4 (MIT)
zlib-rs 0.6.8 (Zlib)
zmij 1.0.23 (MIT)
zopfli 0.8.3 (Apache-2.0)
@@ -596,7 +596,7 @@ pin-project 1.1.13, pin-project-internal 1.1.13, pin-project-lite 0.2.17, piper
rustix 0.38.44, rustix 1.1.5, rustversion 1.0.23, semver 1.0.28, serde 1.0.229, serde_core 1.0.229,
serde_derive 1.0.229, serde_derive_internals 0.30.0, serde_json 1.0.151, serde_path_to_error 0.1.20,
serde_repr 0.1.21, simd_cesu8 1.2.0, smol_str 0.2.2, syn 1.0.109, syn 2.0.119, syn 3.0.6, thiserror
1.0.69, thiserror 2.0.21, thiserror-impl 1.0.69, thiserror-impl 2.0.21, typed-path 0.13.0, typeid
1.0.69, thiserror 2.0.21, thiserror-impl 1.0.69, thiserror-impl 2.0.21, typed-path 0.12.3, typeid
1.0.3, unicode-ident 1.0.26, utf8-zero 0.8.1, wasi 0.11.1+wasi-snapshot-preview1, wasip2
1.0.4+wasi-0.2.12, wit-bindgen 0.57.1, x11-dl 2.21.0, xdg-home 1.3.0, zbus-lockstep 0.5.2,
zbus-lockstep-macros 0.5.2, zbus_names 3.0.0, zmij 1.0.23, zvariant_utils 2.1.0, zvariant_utils
@@ -1339,7 +1339,7 @@ libc 0.2.190, litrs 1.0.0, num_enum 0.7.6, num_enum_derive 0.7.6, proc-macro2 1.
ref-cast 1.0.27, ref-cast-impl 1.0.27, rustc-hash 2.1.3, rustversion 1.0.23, semver 1.0.28, serde
1.0.229, serde_core 1.0.229, serde_derive 1.0.229, serde_derive_internals 0.30.0, serde_json
1.0.151, serde_path_to_error 0.1.20, serde_repr 0.1.21, syn 2.0.119, syn 3.0.6, thiserror 1.0.69,
thiserror 2.0.21, thiserror-impl 1.0.69, thiserror-impl 2.0.21, typed-path 0.13.0, typeid 1.0.3,
thiserror 2.0.21, thiserror-impl 1.0.69, thiserror-impl 2.0.21, typed-path 0.12.3, typeid 1.0.3,
unicode-ident 1.0.26, utf8-zero 0.8.1
================================================================================
@@ -12431,7 +12431,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================================================
rustls-webpki 0.103.16
rustls-webpki 0.103.15
================================================================================
Except as otherwise noted, this project is licensed under the following
@@ -15274,7 +15274,7 @@ IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
================================================================================
webpki-root-certs 1.0.10
webpki-root-certs 1.0.9
================================================================================
# Community Data License Agreement - Permissive - Version 2.0
@@ -16401,7 +16401,7 @@ IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
================================================================================
zip 9.1.3
zip 9.0.4
================================================================================
The MIT License (MIT)
@@ -66,7 +66,7 @@ fn run() -> Result<(), String> {
let mut session = Session::default();
eprintln!("Generating original CAD scene from {recipe_path}");
let generation_start = Instant::now();
let (commands, command_timings) = session.run_script_timed(&recipe, false, &mut |_, _| {}).map_err(|e| e.to_string())?;
let (commands, command_timings) = session.run_script_timed(&recipe, false).map_err(|e| e.to_string())?;
let generation_seconds = generation_start.elapsed().as_secs_f64();
let design_path = output.with_extension(solidcraft_engine::io::DESIGN_EXT);
session.execute("file.save_as", &json!({"path":design_path})).map_err(|e| e.to_string())?;
@@ -87,7 +87,7 @@ fn run() -> Result<(), String> {
let gpu_host_start = Instant::now();
let policy = solidcraft_gpu::select::Policy::from_env().map_err(|e| e.to_string())?;
let (adapter, report) =
solidcraft_gpu::select::pick_path(policy, |_| true).ok_or("no Vulkan or Metal adapter satisfies the requested GPU policy")?;
solidcraft_gpu::select::pick_vulkan(policy, |_| true).ok_or("no Vulkan adapter satisfies the requested GPU policy")?;
session.register_render_job_host(solidcraft_gpu::path::host_on_adapter(&adapter).map_err(|e| e.to_string())?).map_err(|e| e.to_string())?;
(Some(report), Some(gpu_host_start.elapsed().as_secs_f64()))
} else {
+36 -57
View File
@@ -2,7 +2,6 @@
//!
//! ```text
//! solidcraft-cli run <script.json|design.sc|part.step|mesh.3mf> [--in design|part.step|mesh.3mf] [--out FILE]... [--save FILE] [--quiet] [--results] [--timings] [--profile] [--json-out FILE] [--allow-errors]
//! [--param-check off|warn|strict]
//! solidcraft-cli eval <script.json|design.sc|part.step> [--in design.sc|part.step] [--json-out FILE] (alias: inspect) measurements as JSON
//! solidcraft-cli script <design.sc> [--out script.json] the design's history as a command script
//! solidcraft-cli bench-open <design.sc | part.step> [--parse-only] [--save OUT.sc] [--display LEVEL [--edit NAME EXPR]] [--ops script.json] loading timings as JSON lines
@@ -58,7 +57,7 @@ struct Command {
}
/// `run`'s lines in the usage.
const USAGE_RUN: &str = " solidcraft-cli run <script.json|design.sc|part.step> [--in design.sc|part.step] [--out FILE]... [--save FILE] [--quiet] [--results] [--timings] [--profile] [--json-out FILE] [--allow-errors]\n [--param-check off|warn|strict]\n solidcraft-cli run --in <design.sc|part.step> [--out FILE]...\n (a timeline feature that fails fails the run and nothing is written; --allow-errors writes anyway)\n (--param-check checks each step against its command's contract: warn reports on stderr, strict stops the run)\n (--timings prints {timings: [{index, command, ms}], total_ms} for a script, with --results its results too;\n --profile adds each command's profile: {boolean_ms, tessellate_ms, other_ms}, the kernel's share)\n";
const USAGE_RUN: &str = " solidcraft-cli run <script.json|design.sc|part.step> [--in design.sc|part.step] [--out FILE]... [--save FILE] [--quiet] [--results] [--timings] [--profile] [--json-out FILE] [--allow-errors]\n solidcraft-cli run --in <design.sc|part.step> [--out FILE]...\n (a timeline feature that fails fails the run and nothing is written; --allow-errors writes anyway)\n (--timings prints {timings: [{index, command, ms}], total_ms} for a script, with --results its results too;\n --profile adds each command's profile: {boolean_ms, tessellate_ms, other_ms}, the kernel's share)\n";
/// `eval`'s lines in the usage.
const USAGE_EVAL: &str = " solidcraft-cli eval <script.json|design.sc|part.step> [--in design.sc|part.step] [--json-out FILE] (alias: inspect)\n solidcraft-cli eval --in <script.json|design.sc|part.step> [--json-out FILE]\n (with both inputs, runs the positional script on --in before measuring; does not automatically save the modified design)\n (--json-out FILE writes the JSON that run (with --results, else the measurement) and eval print to FILE instead of stdout,\n as plain UTF-8: a shell's > can re-encode it, e.g. Windows PowerShell adds a byte-order mark)\n";
/// `script`'s lines in the usage.
@@ -300,36 +299,18 @@ fn load_checked(path: &str, check: solidcraft_engine::schema::ParamCheck) -> Res
s.execute("doc.open", &json!({"path": path})).map_err(|e| e.to_string())?;
} else {
let script = if v.get("features").is_some() && v.get("commands").is_none() { recipe::to_script(&v)? } else { v };
run_script_warning(&mut s, path, &script)?;
// Warn level: each step's `param_warnings` as it completes, even when a later step fails
// (stderr, so stdout stays the caller's).
let mut warn = |step: usize, r: &Value| {
for w in r.get("param_warnings").and_then(Value::as_array).into_iter().flatten() {
eprintln!("{path}: step {}: {}", step + 1, w.as_str().unwrap_or_default());
}
};
s.run_script_each(&script, &mut warn).map_err(|e| e.to_string())?;
}
Ok(s)
}
/// Run `script`, read from `path`, on `s`. At the warn level each step's `param_warnings` go to
/// stderr as the step completes, even when a later step fails (stdout stays the caller's).
fn run_script_warning(s: &mut Session, path: &str, script: &Value) -> Result<Vec<Value>, String> {
s.run_script_each(script, &mut |step, r| print_param_warnings(path, step, r)).map_err(|e| e.to_string())
}
/// Step `step`'s `param_warnings` on stderr, one per line, named after the script at `path`.
fn print_param_warnings(path: &str, step: usize, r: &Value) {
for w in r.get("param_warnings").and_then(Value::as_array).into_iter().flatten() {
eprintln!("{path}: step {}: {}", step + 1, w.as_str().unwrap_or_default());
}
}
/// `--param-check off|warn|strict`: how calls that break a command's parameter contract are
/// treated (docs/mcp.md); off when the option isn't given.
fn parse_param_check(cmd: &str, args: &[String]) -> Result<solidcraft_engine::schema::ParamCheck, String> {
match flag(args, "--param-check") {
None if args.iter().any(|a| a == "--param-check") => Err(format!("{cmd}: --param-check wants off, warn or strict")),
None => Ok(solidcraft_engine::schema::ParamCheck::Off),
Some(v) => {
solidcraft_engine::schema::ParamCheck::parse(v).ok_or_else(|| format!("{cmd}: --param-check wants off, warn or strict, not `{v}`"))
}
}
}
fn flag<'a>(args: &'a [String], name: &str) -> Option<&'a str> {
args.iter().position(|a| a == name).and_then(|i| args.get(i + 1)).map(String::as_str)
}
@@ -386,15 +367,7 @@ fn print_json(v: &Value, file: Option<&str>) -> Result<(), String> {
fn cmd_run(args: &[String]) -> Result<(), String> {
install_renderer();
let json_out = json_out(args)?;
// Before the option check, so a bare `--param-check` gets the words `mcp` uses.
let check = parse_param_check("run", args)?;
known_args(
"run",
args,
&["--in", "--out", "--save", "--json-out", "--param-check"],
&["--quiet", "--results", "--timings", "--profile", "--allow-errors"],
true,
)?;
known_args("run", args, &["--in", "--out", "--save", "--json-out"], &["--quiet", "--results", "--timings", "--profile", "--allow-errors"], true)?;
let base = flag(args, "--in");
let path = positional(args);
if path.is_none() && base.is_none() {
@@ -407,25 +380,23 @@ fn cmd_run(args: &[String]) -> Result<(), String> {
let (mut s, results) = if want_results || timings {
// Collect every command's result or time (scripts only), then process requested files too.
let mut s = match base {
Some(b) => load_checked(b, check)?,
Some(b) => load(b)?,
None => Session::default(),
};
s.param_check = check;
let needs = if want_results { "--results needs a script" } else { "--timings needs a script" };
let script = path.ok_or(needs)?;
let v = read_json(script)?;
let v = read_json(path.ok_or(needs)?)?;
let out = if timings {
let (r, mut t) = s.run_script_timed(&v, profile, &mut |step, r| print_param_warnings(script, step, r)).map_err(|e| e.to_string())?;
let (r, mut t) = s.run_script_timed(&v, profile).map_err(|e| e.to_string())?;
if want_results && let Some(o) = t.as_object_mut() {
o.insert("results".into(), Value::Array(r));
}
t
} else {
Value::Array(run_script_warning(&mut s, script, &v)?)
Value::Array(s.run_script(&v).map_err(|e| e.to_string())?)
};
(s, Some(out))
} else {
(open(base, path, check)?, None)
(open(base, path)?, None)
};
// A feature that fails leaves the bodies as they were before it (a parameter change can
// break a feature without failing the command that made it): writing them would hand out
@@ -450,16 +421,16 @@ fn cmd_run(args: &[String]) -> Result<(), String> {
}
/// The session `run`, `eval` and `snapshot` start from: `--in` (a design or STEP file) with the
/// positional script run on top of it, or either one alone, with scripts run at `check`.
fn open(base: Option<&str>, path: Option<&String>, check: solidcraft_engine::schema::ParamCheck) -> Result<Session, String> {
/// positional script run on top of it, or either one alone.
fn open(base: Option<&str>, path: Option<&String>) -> Result<Session, String> {
match (base, path) {
(Some(b), Some(p)) => {
let mut s = load_checked(b, check)?;
run_script_warning(&mut s, p, &read_json(p)?)?;
let mut s = load(b)?;
s.run_script(&read_json(p)?).map_err(|e| e.to_string())?;
Ok(s)
}
(Some(b), None) => load_checked(b, check),
(None, Some(p)) => load_checked(p, check),
(Some(b), None) => load(b),
(None, Some(p)) => load(p),
(None, None) => Err(usage()),
}
}
@@ -502,7 +473,7 @@ fn timeline_ok(s: &Session) -> Result<(), String> {
fn cmd_eval(args: &[String]) -> Result<(), String> {
let json_out = json_out(args)?;
known_args("eval", args, &["--in", "--json-out"], &[], true)?;
let mut s = open(flag(args, "--in"), positional(args), solidcraft_engine::schema::ParamCheck::Off)?;
let mut s = open(flag(args, "--in"), positional(args))?;
let m = s.execute("inspect.measure", &json!({})).map_err(|e| e.to_string())?;
let d = s.execute("document.inspect", &json!({})).map_err(|e| e.to_string())?;
let out = json!({
@@ -596,7 +567,7 @@ fn cmd_snapshot(args: &[String]) -> Result<(), String> {
Some(x) => x.parse().ok().filter(|n| (16..=8192).contains(n)).ok_or_else(|| format!("{name} must be 16 to 8192 pixels, not `{x}`")),
};
let (w, h) = (size("--width", 1280)?, size("--height", 800)?);
let mut s = open(flag(args, "--in"), positional(args), solidcraft_engine::schema::ParamCheck::Off)?;
let mut s = open(flag(args, "--in"), positional(args))?;
// How the bodies are drawn and where the model is cut, through the commands the app's
// Appearance dialog and Section Analysis run (`preview`).
preview::apply(&mut s, &flags(args, "--body"), &flags(args, "--tool"), flag(args, "--section"))?;
@@ -720,8 +691,17 @@ fn cmd_mcp(args: &[String]) -> Result<(), String> {
eprintln!("solidcraft mcp: the design's folder is left out because {why}; add it with --allow-path if you mean it");
}
}
// How calls that break a command's parameter contract are treated, headless or bridged.
let param_check = parse_param_check("mcp", args)?;
// How a headless session treats calls that break a command's parameter contract (docs/mcp.md).
let param_check = match flag(args, "--param-check") {
None if args.iter().any(|a| a == "--param-check") => return Err("mcp: --param-check wants off, warn or strict".into()),
None => solidcraft_engine::schema::ParamCheck::Off,
Some(v) => {
solidcraft_engine::schema::ParamCheck::parse(v).ok_or_else(|| format!("mcp: --param-check wants off, warn or strict, not `{v}`"))?
}
};
if param_check != solidcraft_engine::schema::ParamCheck::Off && flag(args, "--connect").is_some() {
eprintln!("solidcraft mcp: --param-check applies to headless sessions; calls to the app are not checked yet");
}
let backend: Box<dyn solidcraft_mcp::Backend> = match (flag(args, "--connect"), flag(args, "--in")) {
(Some(_), Some(_)) => return Err("mcp: use either --connect or --in, not both".into()),
(Some(addr), None) => {
@@ -729,7 +709,7 @@ fn cmd_mcp(args: &[String]) -> Result<(), String> {
return Err(format!("mcp: --connect wants HOST:PORT, such as 127.0.0.1:7878, not `{addr}`"));
};
// Serve without the app too: the tools connect once it runs, and say it isn't until then.
let mut remote = solidcraft_mcp::Remote::new(addr, flag(args, "--token")).with_param_check(param_check);
let mut remote = solidcraft_mcp::Remote::new(addr, flag(args, "--token"));
if let Err(e) = remote.try_connect() {
eprintln!(
"solidcraft mcp: no SolidCraft app at {addr} yet ({e}); start it with `solidcraft --control {port}` \
@@ -749,8 +729,7 @@ fn cmd_mcp(args: &[String]) -> Result<(), String> {
let auto = !args.iter().any(|a| a == "--headless");
if auto && let Some(port) = discover_app() {
eprintln!("solidcraft mcp: bridged to the running app at 127.0.0.1:{port} (--headless starts a session of its own)");
let remote = solidcraft_mcp::Remote::new(&format!("127.0.0.1:{port}"), flag(args, "--token")).with_param_check(param_check);
return serve_mcp(Box::new(remote), scope);
return serve_mcp(Box::new(solidcraft_mcp::Remote::new(&format!("127.0.0.1:{port}"), flag(args, "--token"))), scope);
}
let mut headless = solidcraft_mcp::Headless::default();
headless.session.param_check = param_check;
-44
View File
@@ -288,47 +288,3 @@ fn undoing_an_edit_after_opening_reuses_the_saved_results() {
let _ = std::fs::remove_file(&path);
let _ = std::fs::remove_file(format!("{}.bak", path.display()));
}
/// A design saved before body names were pinned (#6403) pins them as it opens, as its first
/// command would, and opening it is no change. That command pinned them as part of itself, so
/// undoing it went back to the unpinned design, which no evaluated result matched: the first
/// undo after opening from the command line evaluated every feature again (82-93 s in a
/// 5,484-feature design); `doc.open` pinned them after opening, which marked the design changed.
#[test]
fn a_design_saved_before_names_were_pinned_opens_pinned_and_unchanged() {
let plate = solidcraft_engine::sample::samples().into_iter().find(|s| s.name == "Sample Plate").unwrap();
let mut built = Session::default();
for c in (plate.script)()["commands"].as_array().unwrap() {
built.execute(c["command"].as_str().unwrap(), &c["params"]).unwrap();
}
let mut doc = built.design().into_owned();
for f in &mut doc.features {
f.body_names.clear();
}
doc.reserved_body_names.clear();
let unpinned = Session::new(doc);
let design = unpinned.design();
let saved = unpinned.model.saved(&design).unwrap();
let bytes = solidcraft_engine::io::write_design_container_with_cache(&design, solidcraft_engine::io::DesignCompression::Fast, None, Some(&saved))
.unwrap();
let path = temp("unpinned");
std::fs::write(&path, &bytes).unwrap();
let file = path.to_string_lossy().to_string();
// As the command line opens a design (`load`), and as the app does (`doc.open`).
let (doc, saved) = solidcraft_engine::io::read_design_file(&file, None::<fn(solidcraft_engine::io::DesignPreview)>).unwrap();
for (how, mut s) in [("opened_at", Session::opened_at(doc, saved.as_ref(), Some(&file))), ("doc.open", open(&path))] {
assert_eq!(s.model.last_recomputed, 0, "{how}: taken from the file");
assert!(s.doc.features.iter().any(|f| !f.body_names.is_empty()), "{how}: the names are pinned");
assert!(!s.is_dirty(), "{how}: opening is no change");
let read: Vec<Arc<ModelState>> = s.model.results.iter().map(|r| r.state.clone()).collect();
s.execute("solid.box", &json!({"length": 3, "width": 3, "height": 3, "operation": "new"})).unwrap();
// As in a large design, whose evaluation cache keeps only a few results: undo finds the
// results in the model itself or evaluates them again.
*s.model.cache.lock().unwrap() = Default::default();
s.execute("edit.undo", &json!({})).unwrap();
assert_eq!(s.model.last_recomputed, 0, "{how}: the first undo evaluates nothing");
assert!(s.model.results.iter().zip(&read).all(|(r, st)| Arc::ptr_eq(&r.state, st)), "{how}: the states read from the file");
assert!(!s.is_dirty(), "{how}: undone to the design as opened");
}
let _ = std::fs::remove_file(&path);
}
-72
View File
@@ -496,78 +496,6 @@ fn timings_and_profile_report_each_command() {
assert!(String::from_utf8_lossy(&output.stderr).contains("--timings needs a script"));
}
/// #6921: `--param-check` checks a script's steps against their contracts on every path `run`
/// takes (a script alone, on an `--in` design or script, with `--results`, `--timings` or
/// `--profile`), and a warning reaches stderr even when a later step fails.
#[test]
fn param_check_reaches_every_script_run_takes() {
let dir = Scratch::new();
let typo = dir.0.join("typo.json");
let step = json!({"command": "solid.box", "params": {"length": 2, "width": 3, "height": 4, "operaton": "new"}});
std::fs::write(&typo, json!({"commands": [step.clone()]}).to_string()).unwrap();
let base = dir.0.join("base.solidcraft");
json_output(cli().arg("run").arg(dir.script()).arg("--save").arg(&base).output().unwrap());
let saved = dir.0.join("saved.solidcraft");
let start = dir.script();
let (typo, base, saved_arg, start) = (typo.to_str().unwrap(), base.to_str().unwrap(), saved.to_str().unwrap(), start.to_str().unwrap());
let paths = [&[][..], &["--in", base], &["--in", start], &["--results"], &["--timings"], &["--timings", "--profile"]];
let run = |level: Option<&str>, extra: &[&str]| {
std::fs::remove_file(&saved).ok();
let check = level.map(|l| ["--param-check", l]).into_iter().flatten();
cli().args(["run", typo, "--save", saved_arg]).args(check).args(extra).output().unwrap()
};
// Off, the default: the step runs as it always has, without a word.
let off = run(None, &[]);
assert!(off.status.success() && !String::from_utf8_lossy(&off.stderr).contains("operaton"), "{off:?}");
assert_eq!(body_count(&saved), 1);
// Warn: each path runs the step, saves, and reports it on stderr; `--results` keeps it too.
for extra in paths {
let output = run(Some("warn"), extra);
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(output.status.success(), "{extra:?}: {stderr}");
assert!(stderr.contains("step 1: unknown key `operaton`; did you mean `operation`?"), "{extra:?}: {stderr}");
assert!(saved.exists(), "{extra:?}");
if extra == ["--results"] {
let results: Value = serde_json::from_slice(&output.stdout).unwrap();
assert!(results[0]["param_warnings"][0].as_str().is_some_and(|w| w.contains("operaton")), "{results}");
}
}
// Strict: on each path the run stops at the step, and nothing is written.
for extra in paths {
let output = run(Some("strict"), extra);
let stderr = String::from_utf8_lossy(&output.stderr);
assert_eq!(output.status.code(), Some(1), "{extra:?}: {stderr}");
assert!(stderr.contains("unknown key `operaton`"), "{extra:?}: {stderr}");
assert!(!saved.exists(), "{extra:?}");
}
// Warn, with a later step that fails: the run fails, and the first step's warning is still
// reported, timed or not.
let failing = dir.0.join("failing.json");
let fail = json!({"command": "solid.extrude", "params": {"sketch": "Nope"}});
std::fs::write(&failing, json!({"commands": [step, fail]}).to_string()).unwrap();
for extra in [&[][..], &["--timings"]] {
let output = cli().arg("run").arg(&failing).args(["--param-check", "warn"]).args(extra).output().unwrap();
let stderr = String::from_utf8_lossy(&output.stderr);
assert_eq!(output.status.code(), Some(1), "{extra:?}: {stderr}");
assert!(stderr.contains("step 1: unknown key `operaton`") && stderr.contains("no sketch `Nope`"), "{extra:?}: {stderr}");
}
// A level it doesn't know and a missing value fail.
for (bad, says) in [
(&["--param-check", "loud"][..], "--param-check wants off, warn or strict, not `loud`"),
(&["--param-check"], "run: --param-check wants off, warn or strict"),
] {
let output = cli().args(["run", typo]).args(bad).output().unwrap();
let stderr = String::from_utf8_lossy(&output.stderr);
assert_eq!(output.status.code(), Some(1), "{bad:?}: {stderr}");
assert!(stderr.contains(says), "{bad:?}: {stderr}");
}
}
fn render_setup_script(dir: &Scratch, job: Value) -> PathBuf {
let path = dir.0.join("render.json");
std::fs::write(
+1 -1
View File
@@ -34,7 +34,7 @@ serde_json = { workspace = true }
web-sys = { version = "0.3", features = [
"Window", "Document", "Element", "HtmlElement", "HtmlCanvasElement", "Location", "Navigator", "StorageManager",
"FileSystemHandle", "FileSystemDirectoryHandle", "FileSystemFileHandle", "FileSystemGetFileOptions", "FileSystemWritableFileStream",
"WritableStream", "File", "FileList", "Blob", "BlobPropertyBag", "Url", "HtmlAnchorElement", "HtmlInputElement", "Storage", "StorageEvent",
"WritableStream", "File", "FileList", "Blob", "BlobPropertyBag", "Url", "HtmlAnchorElement", "HtmlInputElement", "Storage",
"IdbFactory", "IdbDatabase", "IdbObjectStore", "IdbOpenDbRequest", "IdbRequest", "IdbTransaction", "IdbTransactionMode",
"Headers", "ReadableStream", "ReadableStreamDefaultReader",
"BeforeUnloadEvent", "Event", "EventTarget", "KeyboardEvent", "Response", "FormData", "RequestInit", "MediaQueryList", "Gamepad", "Performance",
+5 -131
View File
@@ -119,43 +119,6 @@ fn closes_design(key: &str, command: bool, shift: bool, alt: bool, design_shown:
design_shown && command && !shift && !alt && key.eq_ignore_ascii_case("w")
}
/// The settings a tab last wrote to the browser's storage, or loaded from another tab (#8644).
/// Every open tab of the app shares that storage, and eframe saves each tab's whole copy every
/// 30 s and when the page loses focus, so a tab still holding old settings put them back over a
/// change made in another. A change is now written in the frame it is made, and the other tabs
/// load it ([`settings_written`]).
#[cfg(any(target_arch = "wasm32", test))]
#[derive(Default, Debug)]
struct PrefsWriter {
written: Option<String>,
}
#[cfg(any(target_arch = "wasm32", test))]
impl PrefsWriter {
/// `prefs` if they are not the settings written or loaded last (they count as written from
/// now on).
fn take(&mut self, prefs: String) -> Option<String> {
if self.written.as_deref() == Some(prefs.as_str()) {
return None;
}
self.written = Some(prefs.clone());
Some(prefs)
}
/// The settings the tab holds after loading another tab's: the tab doesn't write them back.
fn loaded(&mut self, prefs: String) {
self.written = Some(prefs);
}
}
/// The settings another tab wrote, from a `storage` event (the browser sends one to every other
/// tab of the page when one tab writes). Other keys, and settings taken away (clearing the site's
/// data), leave this tab's settings as they are.
#[cfg(any(target_arch = "wasm32", test))]
fn settings_written(key: Option<&str>, value: Option<String>) -> Option<String> {
value.filter(|_| key == Some(solidcraft_ui_egui::prefs::STORAGE_KEY))
}
#[cfg(target_arch = "wasm32")]
mod web {
use std::rc::Rc;
@@ -254,24 +217,6 @@ mod web {
on_key.forget();
}
/// Settings another tab wrote, waiting for this tab's next frame (#8644).
type PrefsInbox = Rc<std::cell::Cell<Option<String>>>;
/// Settings another tab of the app writes go to `inbox`, and this tab draws a frame, which
/// loads them.
fn hear_settings_from_other_tabs(window: &web_sys::Window, ctx: &egui::Context, inbox: PrefsInbox) {
let ctx = ctx.clone();
let on_storage = wasm_bindgen::closure::Closure::<dyn FnMut(web_sys::StorageEvent)>::new(move |e: web_sys::StorageEvent| {
if let Some(prefs) = crate::settings_written(e.key().as_deref(), e.new_value()) {
inbox.set(Some(prefs));
ctx.request_repaint();
}
});
let _ = window.add_event_listener_with_callback("storage", on_storage.as_ref().unchecked_ref());
// The listener lives as long as the page.
on_storage.forget();
}
const JAPANESE_FONT_PATH: &str = "./fonts/BIZUDPGothic-Regular.ttf";
type FontLoadResult = Rc<std::cell::RefCell<Option<Result<Vec<u8>, String>>>>;
@@ -301,48 +246,9 @@ mod web {
font_language: String,
space_mouse: SpaceMouse,
wheel_gestures: solidcraft_ui_egui::WebWheelGestures,
/// The settings this tab wrote or loaded last, and those another tab wrote since (#8644).
prefs_writer: crate::PrefsWriter,
other_tab_prefs: PrefsInbox,
}
impl Shell {
/// The settings as they are kept between visits: with the user's own language, not a
/// session-only English fallback.
fn persisted_prefs(&mut self) -> String {
let saved = self.font.persisted_language(&self.app.preferences.language).to_owned();
let live = std::mem::replace(&mut self.app.preferences.language, saved);
let prefs = self.app.prefs();
self.app.preferences.language = live;
prefs
}
/// A settings change goes to the browser's storage in the frame it is made, and from
/// there to the other open tabs (#8644). Input is what changes settings, so a frame
/// without any is skipped; eframe's own save still catches anything else.
fn store_prefs(&mut self, ctx: &egui::Context) {
if !self.launch.persists() || ctx.input(|i| i.events.is_empty()) {
return;
}
let prefs = self.persisted_prefs();
let Some(prefs) = self.prefs_writer.take(prefs) else { return };
let stored =
web_sys::window().and_then(|w| w.local_storage().ok().flatten()).map(|s| s.set_item(solidcraft_ui_egui::prefs::STORAGE_KEY, &prefs));
if !matches!(stored, Some(Ok(()))) {
log::warn!("settings: the browser's storage did not take them; they are saved again later");
self.prefs_writer = crate::PrefsWriter::default();
}
}
/// Settings another tab wrote replace this tab's, so this tab's own saves keep them
/// instead of putting its older copy back (#8644).
fn load_other_tabs_prefs(&mut self) {
let Some(prefs) = self.other_tab_prefs.take() else { return };
self.app.load_prefs(&prefs);
let held = self.persisted_prefs();
self.prefs_writer.loaded(held);
}
/// Files from the computer, writes to store, messages and the autosave.
fn files_tick(&mut self, ctx: &egui::Context) {
if !self.launch.persists() {
@@ -741,8 +647,6 @@ mod web {
impl eframe::App for Shell {
fn logic(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
// First: a language another tab chose fetches its font this frame.
self.load_other_tabs_prefs();
self.tick_font(ctx);
self.app.logic(ctx);
self.api.poll();
@@ -785,7 +689,6 @@ mod web {
self.recovery_prompt(&ctx);
}
self.watch_text_for_font(&ctx);
self.store_prefs(&ctx);
}
fn persist_egui_memory(&self) -> bool {
self.launch.persists()
@@ -794,8 +697,11 @@ mod web {
if !self.launch.persists() {
return;
}
let prefs = self.persisted_prefs();
storage.set_string(solidcraft_ui_egui::prefs::STORAGE_KEY, prefs);
// Persist the user's own language, not a session-only English fallback.
let saved = self.font.persisted_language(&self.app.preferences.language).to_owned();
let live = std::mem::replace(&mut self.app.preferences.language, saved);
storage.set_string(solidcraft_ui_egui::prefs::STORAGE_KEY, self.app.prefs());
self.app.preferences.language = live;
}
}
@@ -916,12 +822,6 @@ mod web {
let (sender, receiver) = std::sync::mpsc::channel();
let mut app = SolveApp::new(Session::default(), services).with_control(receiver);
app.embedded = launch.embed;
// Listening before reading: settings another tab writes from now on are
// newer than those read here.
let other_tab_prefs = PrefsInbox::default();
if launch.persists() {
hear_settings_from_other_tabs(&window, &cc.egui_ctx, other_tab_prefs.clone());
}
if launch.persists() && let Some(p) = cc.storage.and_then(|s| solidcraft_ui_egui::prefs::stored(|k| s.get_string(k))) {
app.load_prefs(&p);
}
@@ -965,8 +865,6 @@ mod web {
font_language,
space_mouse: SpaceMouse::default(),
wheel_gestures: solidcraft_ui_egui::WebWheelGestures::default(),
prefs_writer: crate::PrefsWriter::default(),
other_tab_prefs,
}))
}),
)
@@ -1103,28 +1001,4 @@ mod tests {
assert!(!closes_design("w", false, false, false, true));
assert!(!closes_design("s", true, false, false, true));
}
/// A tab writes its settings when they change, and not again while they stay the same; the
/// settings it loaded from another tab aren't written back (#8644).
#[test]
fn changed_settings_are_written_once_and_loaded_ones_not_at_all() {
let mut writer = PrefsWriter::default();
assert_eq!(writer.take(r#"{"a":1}"#.into()).as_deref(), Some(r#"{"a":1}"#), "the first settings are written");
assert_eq!(writer.take(r#"{"a":1}"#.into()), None, "the same settings are not written again");
assert_eq!(writer.take(r#"{"a":2}"#.into()).as_deref(), Some(r#"{"a":2}"#), "a change is written at once");
writer.loaded(r#"{"a":3}"#.into());
assert_eq!(writer.take(r#"{"a":3}"#.into()), None, "settings from another tab are not written back");
assert_eq!(writer.take(r#"{"a":4}"#.into()).as_deref(), Some(r#"{"a":4}"#), "this tab's next change is written");
}
/// Only the settings another tab wrote are loaded: not other keys, and not settings taken
/// away by clearing the site's data (#8644).
#[test]
fn only_settings_another_tab_wrote_are_loaded() {
let key = solidcraft_ui_egui::prefs::STORAGE_KEY;
assert_eq!(settings_written(Some(key), Some("{}".into())).as_deref(), Some("{}"));
assert_eq!(settings_written(Some("solidcraft.webgl"), Some("1".into())), None);
assert_eq!(settings_written(Some(key), None), None, "removed settings leave this tab's");
assert_eq!(settings_written(None, None), None, "clearing all storage leaves this tab's settings");
}
}
-2
View File
@@ -28,8 +28,6 @@ neg_cmp_op_on_partial_ord = "allow"
[dependencies]
solidcraft-engine = { workspace = true }
# The D3D12 shader compiler the window starts with (#6756).
solidcraft-gpu = { workspace = true }
solidcraft-ui-egui = { workspace = true }
solidcraft-space-mouse = { workspace = true }
eframe = { workspace = true, features = ["default_fonts", "wgpu", "accesskit", "wayland", "x11", "links"] }
+1 -16
View File
@@ -4,7 +4,6 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let icon = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("../../assets/icons/app/windows/exports/solidcraft-executable.ico");
println!("cargo:rerun-if-changed={}", icon.display());
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-env-changed=CARGO_PKG_VERSION");
if std::env::var("CARGO_CFG_TARGET_OS")? != "windows" {
return Ok(());
}
@@ -12,21 +11,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let copy = out.join("solidcraft.ico");
std::fs::copy(icon, &copy)?;
let rc = out.join("solidcraft.rc");
let icon_line = format!("1 ICON \"{}\"\n", copy.display().to_string().replace('\\', "/"));
std::fs::write(&rc, format!("{icon_line}{}", version_resource(&std::env::var("CARGO_PKG_VERSION")?)))?;
std::fs::write(&rc, format!("1 ICON \"{}\"\n", copy.display().to_string().replace('\\', "/")))?;
embed_resource::compile_for(&rc, ["solidcraft"], embed_resource::NONE).manifest_required()?;
Ok(())
}
/// The Windows version resource (what Explorer's Details tab shows and what a launcher reads).
/// `FileVersion` and `ProductVersion` are the package version verbatim (`0.25.1`, `0.26.0-rc.1`):
/// ArtCraft's launcher parses the `ProductVersion` string as semver, so a fourth `.0` would not
/// read. The binary `FILEVERSION` fields need four numbers and take the leading `major.minor.patch`.
fn version_resource(version: &str) -> String {
let mut numbers = version.split(['-', '+']).next().unwrap_or("").split('.').map(|p| p.parse::<u16>().unwrap_or(0));
let mut next = || numbers.next().unwrap_or(0);
let (major, minor, patch) = (next(), next(), next());
format!(
"1 VERSIONINFO\nFILEVERSION {major},{minor},{patch},0\nPRODUCTVERSION {major},{minor},{patch},0\nFILEOS 0x40004\nFILETYPE 0x1\n{{\nBLOCK \"StringFileInfo\"\n{{\nBLOCK \"040904B0\"\n{{\nVALUE \"CompanyName\", \"SolidCraft contributors\"\nVALUE \"FileDescription\", \"SolidCraft, parametric 3D CAD\"\nVALUE \"FileVersion\", \"{version}\"\nVALUE \"InternalName\", \"solidcraft\"\nVALUE \"OriginalFilename\", \"solidcraft.exe\"\nVALUE \"ProductName\", \"SolidCraft\"\nVALUE \"ProductVersion\", \"{version}\"\n}}\n}}\nBLOCK \"VarFileInfo\"\n{{\nVALUE \"Translation\", 0x0409, 1200\n}}\n}}\n"
)
}
+16 -36
View File
@@ -24,9 +24,9 @@ const MAX_BAD_LINES: usize = 8;
const EVENT_GAP: Duration = Duration::from_millis(100);
static OPEN: AtomicUsize = AtomicUsize::new(0);
/// 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.
static TOKEN_FILES: std::sync::Mutex<Vec<(std::path::PathBuf, String)>> = std::sync::Mutex::new(Vec::new());
/// The token files this launch wrote (its control port, the agent chat's endpoint), removed
/// when the app ends.
static TOKEN_FILES: std::sync::Mutex<Vec<std::path::PathBuf>> = std::sync::Mutex::new(Vec::new());
/// A new random token: 32 bytes from the operating system, as hex.
fn new_token() -> Option<String> {
@@ -35,21 +35,20 @@ fn new_token() -> Option<String> {
Some(bytes.iter().map(|b| format!("{b:02x}")).collect())
}
/// Remove this launch's token files and discovery file (at exit), leaving any that another
/// launch has written since (#8794).
/// Remove this launch's token file (at exit).
pub fn remove_token_file() {
if let Ok(files) = TOKEN_FILES.lock() {
for (path, token) in files.iter() {
control_auth::remove_token_file(path, token);
for p in files.iter() {
control_auth::remove_token_file(p);
}
}
if let Some((port, token)) = APP_PORT.lock().ok().and_then(|p| p.clone()) {
control_auth::remove_current_port(port, &token);
if let Some(port) = APP_PORT.lock().ok().and_then(|p| *p) {
control_auth::remove_current_port(port);
}
}
/// 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);
/// The port the app's own channel listens on, for removing the discovery file at exit.
static APP_PORT: std::sync::Mutex<Option<u16>> = std::sync::Mutex::new(None);
pub fn start(listen_on: control_auth::Listen, ctx: egui::Context) -> Receiver<ControlRequest> {
let (tx, rx) = channel::<ControlRequest>();
@@ -62,7 +61,7 @@ pub fn start(listen_on: control_auth::Listen, ctx: egui::Context) -> Receiver<Co
};
match listener {
Ok(l) => {
if let Some(port) = listen_on_listener(l, token.clone(), tx, ctx, false) {
if let Some(port) = listen_on_listener(l, token, tx, ctx, false) {
if matches!(listen_on, control_auth::Listen::Default) {
eprintln!("solidcraft: control channel on the default port 127.0.0.1:{port} (Preferences > Assistant turns it off)");
}
@@ -70,7 +69,7 @@ pub fn start(listen_on: control_auth::Listen, ctx: egui::Context) -> Receiver<Co
match control_auth::write_current_port(port) {
Ok(_) => {
if let Ok(mut p) = APP_PORT.lock() {
*p = Some((port, token));
*p = Some(port);
}
}
Err(e) => eprintln!("solidcraft: could not write the control discovery file ({e})"),
@@ -113,7 +112,7 @@ fn listen_on_listener(listener: TcpListener, token: String, tx: Sender<ControlRe
Ok(()) => {
eprintln!("solidcraft: control server listening on 127.0.0.1:{port} (token in {})", path.display());
if let Ok(mut files) = TOKEN_FILES.lock() {
files.push((path, token.clone()));
files.push(path);
}
}
Err(e) => eprintln!(
@@ -475,14 +474,6 @@ fn send_events(design: &DesignWatch, lines: &Lines, stop: &AtomicBool, mut seen:
}
}
/// What this app's control channel does beyond the methods every version has, for a client to
/// find out before it relies on it (an older app answers `control.capabilities` with "unknown
/// method"). `param_check`: the levels `engine.execute`, `engine.batch` and `engine.script` take
/// as a request's own parameter check (#9184).
fn capabilities() -> Value {
json!({"param_check": solidcraft_engine::schema::ParamCheck::ALL.map(|l| l.name())})
}
/// Write `reply` on the connection: through its subscription once it has one.
fn answer(out: &mut TcpStream, events: Option<&Subscription>, reply: &Value) -> std::io::Result<()> {
match events {
@@ -543,20 +534,15 @@ fn serve_with(
let id = msg.get("id").cloned().unwrap_or(Value::Null);
let method = msg.get("method").and_then(Value::as_str).unwrap_or("").to_string();
let params = msg.get("params").cloned().unwrap_or(json!({}));
// A request that timed out may have finished since (#1618). `control.running` and
// `control.capabilities` only look, so they leave that reply where it is.
let late = pending.as_ref().filter(|_| !matches!(method.as_str(), "control.running" | "control.capabilities")).and_then(|p| match p
.reply
.try_recv()
{
// A request that timed out may have finished since (#1618). `control.running` only
// looks, so it leaves that reply where it is.
let late = pending.as_ref().filter(|_| method != "control.running").and_then(|p| match p.reply.try_recv() {
Ok(reply) => Some(reply),
Err(TryRecvError::Disconnected) => Some(json!({"ok": false, "error": "the app ended the request without a reply"})),
Err(TryRecvError::Empty) => None,
});
let mut r = if method == "control.running" {
json!({"ok": true, "result": running.result(connection)})
} else if method == "control.capabilities" {
json!({"ok": true, "result": capabilities()})
} else if method == "control.pending" {
match (pending.take(), late) {
(None, _) => json!({"ok": true, "result": {"pending": null}}),
@@ -763,9 +749,6 @@ mod tests {
let mut watcher = open();
let (r, rows) = running(&mut watcher, &|_| true);
assert!(r["ok"] == true && rows.is_empty(), "idle: {r}");
// What the app's control channel does beyond the methods every version has (#9184).
let r = watcher(json!({"id": 0, "method": "control.capabilities", "token": token}));
assert_eq!((&r["ok"], &r["result"]["param_check"]), (&json!(true), &json!(["off", "warn", "strict"])), "{r}");
let mut export = open();
let path = "/private/part.step";
@@ -797,9 +780,6 @@ mod tests {
let own: Vec<&Value> = r["result"]["running"].as_array().unwrap().iter().filter(|row| row["self"] == true).collect();
assert_eq!(own.len(), 1, "{r}");
assert_eq!(own[0]["command"], "file.export", "{r}");
// So may it ask what the app can do: answered at once, not refused as busy.
let r = export(json!({"id": 8, "method": "control.capabilities"}));
assert_eq!(r["result"]["param_check"], json!(["off", "warn", "strict"]), "{r}");
gate_tx.send(()).unwrap();
assert_eq!(queued.join().unwrap()["result"], "engine.batch");
-6
View File
@@ -1016,10 +1016,6 @@ fn main() -> eframe::Result {
app.session.doc_mut().name = "Sample Plate".into();
app.session.mark_saved();
app.session.undo.clear();
// Built straight into the session, so nothing asked for a fit: frame it at the
// home view as any opened design is (#9195). The fit waits for the first layout.
app.cam.set_view(solidcraft_engine::render::StandardView::Iso);
app.fit_view();
}
// Lock files next to open designs: a design open on another computer says so (#5467),
// the files given at launch included.
@@ -1128,8 +1124,6 @@ fn wgpu_options(cpu: bool, preference: Option<&str>) -> eframe::egui_wgpu::WgpuC
let intel_mac = cfg!(all(target_os = "macos", target_arch = "x86_64"));
let indirect = std::env::var(startup::INDIRECT_VALIDATION_ENV).ok();
setup.instance_descriptor.flags = startup::window_instance_flags(setup.instance_descriptor.flags, intel_mac, indirect.as_deref());
// Never a `dxcompiler.dll` another program put on PATH (#6756).
setup.instance_descriptor.backend_options.dx12.shader_compiler = solidcraft_gpu::dx12_compiler();
let environment = std::env::var("WGPU_ADAPTER_NAME").ok();
let adapter = graphics().and_then(|v| v.get("adapter").and_then(serde_json::Value::as_str).map(str::to_string));
startup::configure_adapter(setup, cpu, environment, adapter);
+2 -3
View File
@@ -255,7 +255,7 @@ pub const FLOAT_DEPTH_STENCIL: eframe::wgpu::Features = eframe::wgpu::Features::
/// asks for a float one only when whichever it picks has it.
pub fn float_depth_everywhere(options: &eframe::egui_wgpu::WgpuConfiguration) -> bool {
let eframe::egui_wgpu::WgpuSetup::CreateNew(setup) = &options.wgpu_setup else { return false };
let mut desc = solidcraft_gpu::instance_descriptor_from_env();
let mut desc = eframe::wgpu::InstanceDescriptor::new_without_display_handle_from_env();
desc.backends = setup.instance_descriptor.backends;
let instance = eframe::wgpu::Instance::new(desc);
let adapters = pollster::block_on(instance.enumerate_adapters(setup.instance_descriptor.backends));
@@ -272,7 +272,6 @@ pub fn has_hardware_adapter(backends: eframe::wgpu::Backends) -> bool {
let mut desc = eframe::wgpu::InstanceDescriptor::new_without_display_handle();
desc.backends = backends;
desc.flags = eframe::wgpu::InstanceFlags::from_build_config().with_env();
desc.backend_options.dx12.shader_compiler = solidcraft_gpu::dx12_compiler();
let instance = eframe::wgpu::Instance::new(desc);
let adapters = pollster::block_on(instance.enumerate_adapters(backends));
let found: Vec<String> = adapters.iter().map(|a| format!("{} ({:?})", a.get_info().name, a.get_info().device_type)).collect();
@@ -592,7 +591,7 @@ mod tests {
if cfg!(target_os = "windows") && std::env::var_os(WGPU_BACKEND_ENV).is_none() {
assert_eq!(backends, eframe::wgpu::Backends::DX12);
}
let mut desc = solidcraft_gpu::instance_descriptor_from_env();
let mut desc = eframe::wgpu::InstanceDescriptor::new_without_display_handle_from_env();
desc.backends = backends;
let instance = eframe::wgpu::Instance::new(desc);
let adapters = pollster::block_on(instance.enumerate_adapters(backends));
+1 -1
View File
@@ -1,5 +1,5 @@
//! Built-in model appearances: names, sRGB colours and metalness.
pub const LIBRARY: &[(&str, [u8; 3], f64)] = &[
pub const LIBRARY: [(&str, [u8; 3], f64); 20] = [
("Aluminum - Satin", [204, 208, 214], 1.0),
("Aluminum - Anodized Black", [44, 46, 50], 1.0),
("Aluminum - Anodized Blue", [52, 92, 160], 1.0),
+1 -1
View File
@@ -1,7 +1,7 @@
//! Original illustrative opaque finishes; not measured optical or engineering data.
//! (name, sRGB color, metal fraction, perceptual roughness). IOR is an illustrative 1.5.
//! Separate names preserve the scalar library's appearance and saved assignments.
pub const OPAQUE_FINISHES: &[(&str, [u8; 3], f64, f64)] = &[
pub const OPAQUE_FINISHES: [(&str, [u8; 3], f64, f64); 6] = [
("Steel - Satin PBR", [158, 164, 172], 1.0, 0.4),
("Aluminum - Satin PBR", [204, 208, 214], 1.0, 0.3),
("Copper - Clean PBR", [204, 122, 80], 1.0, 0.25),
+1 -1
View File
@@ -16,7 +16,7 @@ const fn glass(transmission_linear_rgb: [f64; 3], ior: f64, reference_path_mm: f
GlassRecipe { transmission_linear_rgb, dielectric_ior: ior, reference_path_mm, boundary }
}
pub const STARTER_PACK: &[VisualPreset] = &[
pub const STARTER_PACK: [VisualPreset; 40] = [
VisualPreset::opaque(
"starter.wood.oak-honey",
"Wood - Honey Oak Uniform Preview",
+2 -8
View File
@@ -188,7 +188,7 @@ surface = [
sketch = [
"arc3", "arc_center", "arc_slot", "arc_slot_center", "arc_tangent",
"blend", "circle", "circle2", "circle3", "circle_tt",
"circle_ttt", "conic", "constrainer", "dimension", "ellipse", "equation_curve",
"circle_ttt", "conic", "constrainer", "dimension", "ellipse",
"extend", "finish", "fit_section", "include",
"intersect", "intersection_curve", "iso_curve", "line", "line_mid",
"offset", "offset_two_sides", "offset_symmetric", "point", "polygon", "polygon_circumscribed", "polygon_edge",
@@ -204,11 +204,5 @@ constraint = [
"c_polygon", "c_smooth", "c_symmetry", "c_tangent",
]
construction = [
"centerline", "construction", "construction_line", "construction_line_angle",
"construction_line_bisector", "construction_line_horizontal", "construction_line_parallel",
"construction_line_perpendicular", "construction_line_tangent_at", "construction_line_tangent_external",
"construction_line_tangent_two", "construction_line_vertical", "infinite",
]
mesh = [
"mesh_body",
"centerline", "construction", "infinite",
]
@@ -70,16 +70,6 @@ configuration_table false
conic false
constrainer false
construction false
construction_line false
construction_line_angle false
construction_line_bisector false
construction_line_horizontal false
construction_line_parallel false
construction_line_perpendicular false
construction_line_tangent_at false
construction_line_tangent_external false
construction_line_tangent_two false
construction_line_vertical false
contact_all false
contact_new false
contact_off false
@@ -105,7 +95,6 @@ edit false
ellipse false
emboss false
environment_map false
equation_curve false
error false
explode false
export false
@@ -114,7 +103,6 @@ extend false
extrude false
eye false
fastener false
feature_group false
fillet false
finish false
finish_edit false
@@ -155,7 +143,6 @@ loft false
lookat false
material false
measure false
mesh_body false
mesh_export false
min_radius false
mirror false
@@ -235,7 +222,6 @@ settings_monitor false
settings_mouse false
settings_palette false
settings_plug false
sheet false
sheet_rules false
shell false
shield false
@@ -271,7 +257,6 @@ split_face false
spun false
star false
status_error false
status_pin false
status_recovery false
style false
style_hidden_edges false
@@ -303,8 +288,6 @@ svg false
sweep false
text false
thread false
timeline_play false
timeline_stop false
torus false
trace false
trim false
@@ -1,5 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
<title>Pinned result</title>
<path d="M32 57C25 48 14 35 14 24A18 18 0 0 1 50 24C50 35 39 48 32 57Z" fill="none" stroke="currentColor" stroke-width="5.6" stroke-linejoin="round" stroke-linecap="round"/>
<path d="M25 24A7 7 0 1 0 39 24A7 7 0 1 0 25 24Z" fill="none" stroke="currentColor" stroke-width="5.6" stroke-linejoin="round" stroke-linecap="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 429 B

@@ -1,8 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
<title>Construction line through two points</title>
<path d="M8 52L56 12" fill="none" stroke="#236ead" stroke-width="4.25" stroke-linejoin="round" stroke-linecap="round" stroke-dasharray="10 5"/>
<circle cx="20" cy="42" r="5.8" fill="#ffffff"/>
<circle cx="20" cy="42" r="3.4" fill="#236ead"/>
<circle cx="44" cy="22" r="5.8" fill="#ffffff"/>
<circle cx="44" cy="22" r="3.4" fill="#236ead"/>
</svg>

Before

Width:  |  Height:  |  Size: 472 B

@@ -1,8 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
<title>Construction line at an angle</title>
<path d="M10.26 48.66L58.26 48.66" fill="none" stroke="#6f879c" stroke-width="2.55" stroke-linejoin="round" stroke-linecap="round"/>
<path d="M28.65 33.23A24 24 0 0 1 34.26 48.66" fill="none" stroke="#6f879c" stroke-width="2.55" stroke-linejoin="round" stroke-linecap="round"/>
<path d="M10.26 48.66L54.26 11.66" fill="none" stroke="#236ead" stroke-width="4.25" stroke-linejoin="round" stroke-linecap="round"/>
<circle cx="10.26" cy="48.66" r="5.8" fill="#ffffff"/>
<circle cx="10.26" cy="48.66" r="3.4" fill="#236ead"/>
</svg>

Before

Width:  |  Height:  |  Size: 646 B

@@ -1,6 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
<title>Angle bisector</title>
<path d="M13.92 12.18L9.92 52.17L54.92 44.17" fill="none" stroke="#6f879c" stroke-width="2.55" stroke-linejoin="round" stroke-linecap="round"/>
<path d="M12.11 30.29A22 22 0 0 1 31.58 48.33" fill="none" stroke="#6f879c" stroke-width="2.55" stroke-linejoin="round" stroke-linecap="round"/>
<path d="M9.92 52.17L47.3 11.83" fill="none" stroke="#236ead" stroke-width="4.25" stroke-linejoin="round" stroke-linecap="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 526 B

@@ -1,6 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
<title>Horizontal construction line</title>
<path d="M8 32L56 32" fill="none" stroke="#236ead" stroke-width="4.25" stroke-linejoin="round" stroke-linecap="round" stroke-dasharray="10 5"/>
<circle cx="32" cy="32" r="5.8" fill="#ffffff"/>
<circle cx="32" cy="32" r="3.4" fill="#236ead"/>
</svg>

Before

Width:  |  Height:  |  Size: 362 B

@@ -1,5 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
<title>Parallel construction line</title>
<path d="M9 37L41 9" fill="none" stroke="#6f879c" stroke-width="2.55" stroke-linejoin="round" stroke-linecap="round"/>
<path d="M23 55L55 27" fill="none" stroke="#236ead" stroke-width="4.25" stroke-linejoin="round" stroke-linecap="round" stroke-dasharray="10 5"/>
</svg>

Before

Width:  |  Height:  |  Size: 380 B

@@ -1,6 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
<title>Perpendicular construction line</title>
<path d="M8 44L56 44" fill="none" stroke="#6f879c" stroke-width="2.55" stroke-linejoin="round" stroke-linecap="round"/>
<path d="M32 8L32 56" fill="none" stroke="#236ead" stroke-width="4.25" stroke-linejoin="round" stroke-linecap="round"/>
<path d="M32 34L42 34L42 44" fill="none" stroke="#6f879c" stroke-width="2.55" stroke-linejoin="round" stroke-linecap="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 490 B

@@ -1,7 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
<title>Tangent at a curve point</title>
<circle cx="32" cy="34.26" r="17" fill="none" stroke="#6f879c" stroke-width="2.55" stroke-linejoin="round" stroke-linecap="round"/>
<path d="M8 17.26L56 17.26" fill="none" stroke="#236ead" stroke-width="4.25" stroke-linejoin="round" stroke-linecap="round"/>
<circle cx="32" cy="17.26" r="5.8" fill="#ffffff"/>
<circle cx="32" cy="17.26" r="3.4" fill="#236ead"/>
</svg>

Before

Width:  |  Height:  |  Size: 480 B

@@ -1,7 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
<title>Tangent through an external point</title>
<circle cx="21.74" cy="38.77" r="14" fill="none" stroke="#6f879c" stroke-width="2.55" stroke-linejoin="round" stroke-linecap="round"/>
<path d="M53.6 8.23L28.55 55.9" fill="none" stroke="#236ead" stroke-width="4.25" stroke-linejoin="round" stroke-linecap="round"/>
<circle cx="51.74" cy="11.77" r="5.8" fill="#ffffff"/>
<circle cx="51.74" cy="11.77" r="3.4" fill="#236ead"/>
</svg>

Before

Width:  |  Height:  |  Size: 502 B

@@ -1,6 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
<title>Common tangent to two curves</title>
<circle cx="20" cy="33.59" r="12" fill="none" stroke="#6f879c" stroke-width="2.55" stroke-linejoin="round" stroke-linecap="round"/>
<circle cx="46" cy="33.59" r="8" fill="none" stroke="#6f879c" stroke-width="2.55" stroke-linejoin="round" stroke-linecap="round"/>
<path d="M6 19.27L58 27.36" fill="none" stroke="#236ead" stroke-width="4.25" stroke-linejoin="round" stroke-linecap="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 509 B

@@ -1,6 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
<title>Vertical construction line</title>
<path d="M32 8L32 56" fill="none" stroke="#236ead" stroke-width="4.25" stroke-linejoin="round" stroke-linecap="round" stroke-dasharray="10 5"/>
<circle cx="32" cy="32" r="5.8" fill="#ffffff"/>
<circle cx="32" cy="32" r="3.4" fill="#236ead"/>
</svg>

Before

Width:  |  Height:  |  Size: 360 B

@@ -1,9 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
<title>Equation curve</title>
<path d="M12 8L12 56M6 32L58 32" fill="none" stroke="#6f879c" stroke-width="2.55" stroke-linejoin="round" stroke-linecap="round"/>
<path d="M12 32C15.42 24.83 18.72 18 22.5 18C26.28 18 29.58 24.83 33 32C36.42 39.17 39.72 46 43.5 46C47.28 46 50.58 39.17 54 32" fill="none" stroke="#236ead" stroke-width="4.25" stroke-linejoin="round" stroke-linecap="round"/>
<circle cx="12" cy="32" r="5.8" fill="#ffffff"/>
<circle cx="12" cy="32" r="3.4" fill="#236ead"/>
<circle cx="54" cy="32" r="5.8" fill="#ffffff"/>
<circle cx="54" cy="32" r="3.4" fill="#236ead"/>
</svg>

Before

Width:  |  Height:  |  Size: 666 B

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

Before

Width:  |  Height:  |  Size: 947 B

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

Before

Width:  |  Height:  |  Size: 1.1 KiB

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

Before

Width:  |  Height:  |  Size: 935 B

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

Before

Width:  |  Height:  |  Size: 1.1 KiB

-11
View File
@@ -15,17 +15,6 @@ pub(crate) fn transport_glyph(p: &egui::Painter, c: egui::Pos2, what: &str, col:
}
"back" => tri(-1.0, 0.0),
"forward" => tri(1.0, 0.0),
// Play History: larger than the step arrows so it doesn't read as Forward, and two bars
// while it plays.
"play" => {
let pts = vec![pos2(c.x - 4.5, c.y - 7.0), pos2(c.x + 6.5, c.y), pos2(c.x - 4.5, c.y + 7.0)];
p.add(egui::Shape::convex_polygon(pts, col, Stroke::NONE));
}
"pause" => {
for dx in [-3.0, 3.0] {
p.rect_filled(Rect::from_center_size(pos2(c.x + dx, c.y), vec2(3.0, 12.0)), 0.5, col);
}
}
_ => {
tri(1.0, -1.0);
bar(5.0);
+26 -668
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-16
View File
@@ -852,16 +852,6 @@
"cmd.sheet_refold": "Buk tilbage",
"cmd.sheet_rules": "Vis pladeregler",
"cmd.sheet_unfold": "Fold ud",
"cmd.sketch.construction_line": "Hjælpelinje",
"cmd.sketch.construction_line.angle": "Hjælpelinje med vinkel",
"cmd.sketch.construction_line.bisector": "Vinkelhalveringslinje",
"cmd.sketch.construction_line.horizontal": "Vandret hjælpelinje",
"cmd.sketch.construction_line.parallel": "Parallel hjælpelinje",
"cmd.sketch.construction_line.perpendicular": "Vinkelret hjælpelinje",
"cmd.sketch.construction_line.tangent_at": "Tangent i kurvepunkt",
"cmd.sketch.construction_line.tangent_external": "Tangent gennem eksternt punkt",
"cmd.sketch.construction_line.tangent_two": "Fælles tangent",
"cmd.sketch.construction_line.vertical": "Lodret hjælpelinje",
"cmd.sketch_arc_center_point": "Bue med centrum",
"cmd.sketch_arc_tangent": "Tangentbue",
"cmd.sketch_arc_three_point": "Trepunktsbue",
@@ -1913,7 +1903,6 @@
"ui.constant": "Konstant",
"ui.constraints_conflict": "Bindinger er i konflikt",
"ui.construction": "Konstruktionsgeometri",
"ui.construction.ribbon_label": "Hjælpelinjer",
"ui.context_menu": "Genvejsmenu",
"ui.continuity_g0": "G0-knæk",
"ui.continuity_g1": "G1-tangentkontinuitet",
@@ -2213,7 +2202,6 @@
"ui.pan_zoom_orbit": "Panorér, zoom, rotér visning",
"ui.parallel": "Parallel",
"ui.parameters": "Parametre",
"ui.part_size_needs_a_part": "Vælg en indsat standarddel (en skrue, møtrik, skive eller stift) for at ændre dens størrelse. Brug Skalering til at gøre et emne større eller mindre.",
"ui.part_size_shared": "Genopbygger delen og erstatter alle tilføjede features. Alle forekomster af komponenten opdateres.",
"ui.paste": "Indsæt",
"ui.path": "Bane",
@@ -2366,10 +2354,6 @@
"ui.symmetric": "Symmetrisk",
"ui.symmetry": "Symmetri",
"ui.system": "System",
"ui.tab_assemble": "Samling",
"ui.tab_manage": "Administrér",
"ui.tab_sheet_metal": "Plade",
"ui.tab_view": "Visning",
"ui.tangent": "Tangent",
"ui.taper_angle": "Konusvinkel",
"ui.tapped": "Med gevind",
+1 -609
View File
File diff suppressed because it is too large Load Diff
-121
View File
@@ -1,74 +1,22 @@
{
"A Single hole snaps to the middle of its face and to the centres of its round edges": "A Single hole snaps to the middle of its face and to the centres of its round edges",
"Base Center": "Base Centre",
"Center X": "Centre X",
"Center Y": "Centre Y",
"Center of mass": "Centre of mass",
"Centre to centre": "Centre to centre",
"Circle center": "Circle centre",
"Colour": "Colour",
"Copy all licences": "Copy all licences",
"Customize Toolbar": "Customise Toolbar",
"Customize…": "Customise…",
"Face center": "Face centre",
"Favorites": "Favourites",
"Favourite": "Favourite",
"Mass Center": "Mass Centre",
"Modeled": "Modelled",
"Select the centre the pattern turns around first": "Select the centre the pattern turns around first",
"Snap to face and edge centres": "Snap to face and edge centres",
"Specialise": "Specialise",
"cmd.appearance_favorite": "Favourite Look",
"cmd.component_cycle_color": "Cycle Component Colour",
"cmd.construct_point_center": "Point At Centre Of Circle/Sphere/Torus",
"cmd.inspect_center_of_mass": "Centre of Mass",
"cmd.inspect_colored_components": "Enable Component Colours",
"cmd.inspect_colored_components_disable": "Disable Component Colours",
"cmd.parameters_favorite": "Favourite Parameter",
"cmd.render_aging_describe": "Layered Surface Aging",
"cmd.render_effects_describe": "Lens and Creative Effects",
"cmd.sketch.construction_line": "Construction Line",
"cmd.sketch.construction_line.angle": "Construction Line at Angle",
"cmd.sketch.construction_line.bisector": "Angle Bisector",
"cmd.sketch.construction_line.horizontal": "Horizontal Construction Line",
"cmd.sketch.construction_line.parallel": "Parallel Construction Line",
"cmd.sketch.construction_line.perpendicular": "Perpendicular Construction Line",
"cmd.sketch.construction_line.tangent_at": "Tangent at Curve Point",
"cmd.sketch.construction_line.tangent_external": "Tangent through External Point",
"cmd.sketch.construction_line.tangent_two": "Common Tangent",
"cmd.sketch.construction_line.vertical": "Vertical Construction Line",
"cmd.sketch_arc_center_point": "Centre Point Arc",
"cmd.sketch_circle_center": "Centre Diameter Circle",
"cmd.sketch_rectangle_center": "Centre Rectangle",
"cmd.sketch_slot_arc_center": "Centre Point Arc Slot",
"cmd.sketch_slot_center_point": "Centre Point Slot",
"cmd.sketch_slot_center_to_center": "Centre to Centre Slot",
"color.copy": "Click to copy colour values",
"color.edit": "Click to edit colour",
"color.gamma": "Showing colour values in 0-255 gamma space",
"color.linear": "Showing colour values in 0-1 linear space",
"color.selected": "Selected colour",
"dxf.cancelled": "DXF export cancelled",
"dxf.cancelling": "Cancelling DXF export",
"help.apache": "Apache licence 2.0",
"help.appearance.assign": "Gives the selected bodies, faces or components a colour or a material look, without changing their weight. Use it to tell parts apart or to preview a finish.",
"help.face.delete": "Removes the selected faces and lets the neighbouring faces close the gap, or leaves the gap open as a surface. Use it to take off a rounded edge, a hole or a boss that is in the way.",
"help.font_details": "The interface uses egui's built-in fonts (Ubuntu Light and Hack, under the Ubuntu Font Licence and the MIT/Bitstream Vera licence; Noto Emoji and the emoji icon font, under the OFL and MIT). Sketch text uses Liberation Sans (SIL OFL 1.1). The Crafting Apps' optional font pack, craft-fonts (BIZ UDPGothic, Shippori Mincho, BIZ UDMincho, Noto Sans CJK SC, Noto Sans Arabic; SIL OFL 1.1), is not bundled in SolidCraft builds.",
"help.licences": "Licences",
"help.material.assign": "Sets what the selected bodies are made of, such as steel, aluminium or ABS. Use it so that the mass and weight match the real part.",
"help.mit": "MIT licence",
"help.solid.draft": "Tilts the selected faces by the angle you set, measured from a neutral plane. Use it on moulded or cast parts so that they slide out of the mould.",
"help.solid.revolve": "Spins a sketch profile around an axis to make a round solid. Use it for shafts, knobs, bowls and any part that is round about a centre line.",
"help.solid.split_body": "Cuts a body into separate bodies with a plane, the face of another body or a sketch line. Use it to make parts that are printed, machined or coloured on their own.",
"help.solid.split_face": "Divides the selected faces along a plane, the face of another body or sketch curves, without cutting the body. Use it to give part of a face its own draft, colour or offset.",
"help.third_party": "Third-party licences",
"home.new_mm_hint": "Millimetres · opens in Design",
"navbar.custom.customise": "Customise navigation bar…",
"navbar.custom.position_centre": "Centre",
"navbar.description.separator": "A thin line that groups neighbouring slots.",
"pattern.alignment_hint": "Counts include the original. Centre balances copies; Flip chooses the extra side for even totals.",
"prefs.bottom_centre": "Bottom centre",
"prefs.logo_theme": "Theme's colours",
"prefs.max_file_size": "Largest file to open",
"prefs.max_file_size_design": "Design files",
"prefs.max_file_size_flag": "This run started with --max-file-size {size}, which applies until SolidCraft closes. These settings apply when it starts without it.",
@@ -76,11 +24,6 @@
"prefs.max_file_size_step": "STEP and import files",
"prefs.max_file_size_web": "The web app opens STEP and import files up to 512 MB and designs up to 256 MB: a browser tab can't hold larger files. The desktop app can raise these limits.",
"prefs.megabytes": "MB",
"prefs.sketch_conflict_colour": "Conflicting geometry in the conflict colour",
"prefs.sketch_conflict_colour_note": "While a sketch's constraints conflict, the curves and points a failing constraint holds are drawn in the conflict colour too, not only its glyph or dimension. Off: they keep their usual colours.",
"prefs.sketch_construction_lines": "Extended construction line tools",
"prefs.sketch_recent_snap": "Auto snap to recent centres and midpoints",
"prefs.sketch_recent_snap_note": "While drawing, snap the cursor where the guides of the two most recent circle centres or straight-edge midpoints cross. Off: those guides stay visual and the cursor does not move.",
"prefs.sketch_state_icons": "Sketch icons in the colour of their state",
"prefs.sketch_state_icons_note": "In History and the browser, a sketch's icon takes the colour of its state (under constrained, fully constrained or conflicting) and its tooltip names the state. Off: every sketch has the same icon.",
"prefs.sketch_tracking_guides": "Centre and midpoint alignment guides",
@@ -92,9 +35,6 @@
"prefs.theme_follow_note": "Reloaded whenever another tool rewrites it. Choosing a theme stops following it.",
"prefs.theme_follow_off": "Off",
"prefs.theme_follow_stop": "Stop following",
"prefs.trackpad_zoom_modifier.help": "Hold only this key to zoom at the pointer with vertical scroll. Off keeps the existing scroll behaviour.",
"prefs.view": "View behaviour",
"prefs.viewport_background_colour": "Colour",
"render.aging_add": "Add aging layer",
"render.aging_airborne": "Airborne dust / participating medium",
"render.aging_airborne_help": "Airborne dust is a separate finite homogeneous scattering volume. It changes transport and raw EXR, not the surface-aging stack. Existing volume/glass/denoising restrictions remain explicit; no atmosphere is added automatically.",
@@ -122,9 +62,6 @@
"render.aging_target_help": "A named target must still match its captured index and name. Global masks are world-anchored; they do not follow moving parts. This is neither cavity detection nor true edge wear. Filter the list to reach additional bodies.",
"render.aging_target_search": "Filter body names",
"render.aging_upward": "Upward-facing deposition",
"render.appearance_editor.base_colour": "Base colour",
"render.backdrop_first": "Start / centre colour",
"render.backdrop_second": "End / edge colour",
"render.backdrop_x": "Centre X",
"render.backdrop_y": "Centre Y",
"render.background_camera_section": "Camera background · PNG presentation",
@@ -132,38 +69,20 @@
"render.background_hdr_separate": "The current HDR resources illuminate and reflect on surfaces; they are not automatically displayed as a panorama behind the subject. Changing a gradient does not rotate or recolour the lighting.",
"render.background_lighting_section": "HDR illumination · separate from camera background",
"render.background_no_alpha_override": "A camera background is not added to transparent output silently. Raw-master regrading uses captured coverage and does not reapply denoising; the source EXR remains unchanged.",
"render.background_not_light": "Background colour is presentation, not an additional lighting source.",
"render.background_regrade": "Apply to retained raw master",
"render.background_stage_occlusion": "This shot includes physical stage geometry. A large floor or wall can fill the frame and hide a camera-only background. Clear or resize the stage deliberately, or change its physical reflectance. Regrading cannot remove captured geometry.",
"render.background_workflow": "Choose the background you intend: a camera-only colour/gradient, a physical stage that receives light, or HDR illumination. They are independent. Live Preview is a modelling view; render a new image or regrade a retained master to see camera finishing.",
"render.base_color": "Base colour · sRGB",
"render.bloom_help": "Creative output-only glow from positive linear highlights, spread with three normalised box passes. Radius is in output pixels. Added in linear display light before sRGB; not a lens, volumetric effect or convergence improvement. The raw EXR is unchanged.",
"render.chromatic_offset": "Chromatic edge offset",
"render.cpu_area_editor_help": "Full side vectors in millimeters; U cross V points towards the emitting side. This differs from GPU half-edge vectors.",
"render.cpu_light_help": "Up to eight directional lights. An empty custom list turns them off; selecting a preset restores its lights. Colours are linear RGB and intensity is relative, not watts.",
"render.cpu_linear_color": "Linear colour (R, G, B)",
"render.effects_gpu_only": "These effects require GPU path tracing. Changing the page never switches the renderer automatically.",
"render.effects_help": "Combine ordered colour looks and image-space lens effects. Rendering and raw-master regrading use the same saved settings. Raw EXR stays unchanged. These are original artistic controls, not calibrated lens or branded-film emulations.",
"render.effects_reset_lens": "Reset lens effects",
"render.effects_seed": "Pattern seed",
"render.env_colour": "Colour",
"render.environment.radial_only": "Centre and radius apply to Radial mode.",
"render.error_finish_gesture": "finish the modelling gesture before previewing",
"render.error_finish_operation": "finish the current modelling operation before entering Render",
"render.film_grain": "Photographic grain",
"render.flare_ghosts": "Ghost rings per source",
"render.flare_halo": "Flare halo",
"render.flare_streak": "Anamorphic-style streak",
"render.flare_strength": "Highlight flare strength",
"render.flare_threshold": "Scene-linear flare threshold",
"render.frame_centre_mark": "Centre mark",
"render.hdr_primaries_declared": "The source declares its colour primaries.",
"render.hdr_primaries_srgb": "Colour primaries: sRGB/D65",
"render.hdr_primaries_undeclared": "The source does not declare primaries; review the renderer colour requirements.",
"render.image_cancelled": "Render cancelled",
"render.image_cancelling": "Cancelling",
"render.image_scene_stale": "Finish the modelling gesture or refresh the scene before checking or starting an image.",
"render.inspector_colour": "Colour",
"render.layer_down": "Move down",
"render.layer_enabled": "Layer enabled",
"render.layer_remove": "Remove layer",
@@ -171,18 +90,6 @@
"render.layer_up": "Move up",
"render.lens_effects_help": "Flare uses up to four separated bright sources in the actual linear image. Ghosts, halo, streaks, chromatic offsets and radial distortion are artistic image-space approximations. Spatial effects need opaque output; outside samples extend the image edge. Grain is deterministic. No physics, EXR or geometry is altered.",
"render.lens_effects_title": "Lens-inspired & photographic",
"render.library_center": "Rig centre",
"render.library_favorite": "Add favourite",
"render.library_favorites": "Favourites",
"render.library_inspect_only": "Select to inspect; nothing is applied automatically. Favourites and recent history belong to this open document session.",
"render.library_rig_help": "Fit once at an explicit centre and physical extent. Complete rigs include passive cards; calibration blockers still refuse. Conservative emitter/card clearance is checked before saving.",
"render.library_source_preview_help": "Authored base-colour source map. This is not a rendered or measured material preview.",
"render.library_unfavorite": "Remove favourite",
"render.light_behaviour": "BEHAVIOUR",
"render.light_preview_help": "Live view is unshadowed; Area lights use a centre-sample approximation. Render uses the complete light model.",
"render.light_product_centre": "Product centre",
"render.light_temperature": "Colour temperature",
"render.lighting_colour": "Colour",
"render.look_add": "Add colour look",
"render.look_bleach": "Bleach-bypass-inspired",
"render.look_cool": "Cool",
@@ -194,11 +101,6 @@
"render.look_teal_orange": "Teal / orange",
"render.look_title": "Creative look stack",
"render.look_warm": "Warm",
"render.material_color_map": "Base colour image (sRGB)",
"render.material_color_replace": "Base map replaces body colour",
"render.material_map_required": "Choose a colour image or a normal image before using maps.",
"render.material_maps": "Planar colour and normal maps",
"render.material_maps_help": "PNG/JPEG up to 1024×1024; 16 MiB encoded total. U and V are orthogonal world-mm repeat vectors (maximum 128 repeats). Colour is sRGB; normal data uses OpenGL +Y. Files are captured at Check/Start.",
"render.opaque_preview_help": "Opaque PBR and simple colours; blended transparency. Refraction, HDRI and final rendering are not available yet.",
"render.page_aging": "Aging & contamination",
"render.page_background": "Backgrounds",
@@ -206,45 +108,22 @@
"render.radial_distortion": "Radial distortion",
"render.ribbon_aging": "Aging",
"render.ribbon_effects": "Effects",
"render.ribbon_studios_help": "Browse implemented studio compositions and review their replacements before applying. Concept-only scenes remain labelled.",
"render.sharpening": "Detail sharpening",
"render.soft_focus": "Soft focus",
"render.stage_panels.centre": "Centre",
"render.stage_panels.source_note": "Authored base-colour source map. Not a measured material.",
"render.studio_area_help": "Up to four one-sided rectangles. Orthogonal half-edges U and V define size; U × V faces the lit side. Coordinates are world-space millimetres.",
"render.studio_center": "Centre X, Y, Z (mm)",
"render.studio_hdr_help": "Radiance .hdr, 2:1 panorama, up to 2048 × 1024. EXR is unavailable. The colour assumption applies only when primaries are unspecified.",
"sketch_text.align_center": "Centre",
"ui.3d_mouse_kind_cap": "Return to Centre",
"ui.3d_mouse_looks_like_cap": "The reading stays put while you hold it, the way a Return to Centre device does.",
"ui.3d_mouse_orbit_tip": "Traced: the 3D mouse turns the view around the part of the model in the middle of the view when the turn begins, marked by a faint ball. Classic: around the view's centre",
"ui.3d_mouse_step_pull": "Pull the cap towards you, hold it, then let go.",
"ui.3d_mouse_switch_cap": "Calibrate as Return to Centre",
"ui.agent_chat_minimize": "Minimise to a strip",
"ui.ai_mode_edits_note": "Modelling commands run without asking; saving, opening, exporting and other file or destructive actions still ask.",
"ui.center": "Centre",
"ui.center_arc_follows_cursor": "Centre point arc follows the cursor's direction",
"ui.center_arc_follows_cursor_tip": "A centre point arc runs clockwise or counter-clockwise the way the cursor goes round its centre. Off: always counter-clockwise from the start.",
"ui.centerline": "Centreline",
"ui.colour_vision": "Colour vision",
"ui.colour_vision_note": "Changes the colours that carry a meaning: sketch states, axes, bends, analyses and icons. If you use Windows colour filters, keep this Off.",
"ui.colour_vision_off_tip": "The theme's own colours",
"ui.construction.ribbon_label": "X-Lines",
"ui.customizeToolbar": "Customise Toolbar…",
"ui.default_modelling_orientation": "Default modelling orientation",
"ui.design_properties.license": "Licence",
"ui.design_properties.organization": "Organisation",
"ui.export_keymap_tip": "Keys, S box favourites and the toolbar, as a file",
"ui.layout_compact": "Compact",
"ui.layout_floating": "Floating",
"ui.material_review.claims": "Sources and licences are unverified claims. Missing values remain unknown.",
"ui.point_cloud_color_by": "Colour By",
"ui.point_cloud_file_colors": "File Colours",
"ui.point_cloud_no_file_colors": "The file has no colours",
"ui.point_cloud_single_color": "Single Colour",
"ui.properties.inertia_note": "About the centre of mass, in world axes (g·{unit}²)",
"ui.ribbon_labels": "Show text under ribbon icons",
"ui.view_centre": "View centre",
"ui.workspace_layout": "Workspace layout",
"ui.zoom_to_cursor_tip": "The wheel zooms towards the point under the cursor (off: towards the view's centre)",
"update.prefs_flatpak": "Flatpak updates this copy ({version}): run {command} or use your software centre. SolidCraft doesn't check."
+52 -694
View File
File diff suppressed because it is too large Load Diff
+41 -802
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-558
View File
@@ -692,9 +692,6 @@
"cam.roller": "롤러",
"cam.roller_pick": "롤러 (선택 사항)",
"cam.tip_pick": "끝점 (선택 사항)",
"camera.shot_pitch": "피치",
"camera.shot_roll": "롤",
"camera.shot_yaw": "요",
"choose a profile": "프로파일을 선택하세요",
"choose the cam's and the follower's joints": "캠과 종동절의 관절을 선택하세요",
"choose the joints to couple": "연결할 관절을 선택하세요",
@@ -702,12 +699,9 @@
"click sketch curves": "스케치 곡선 클릭",
"cmd.appearance_assign": "외관",
"cmd.appearance_chain": "외관 출처",
"cmd.appearance_copy": "외관 복사",
"cmd.appearance_favorite": "외관 즐겨찾기",
"cmd.appearance_library": "외관 라이브러리",
"cmd.appearance_list": "외관 목록",
"cmd.appearance_paint": "모양 칠하기",
"cmd.appearance_paste": "외관 붙여넣기",
"cmd.appearance_pick_up": "모양 가져오기",
"cmd.appearance_replace": "모양 바꾸기",
"cmd.assembly_bom": "자재 명세서",
@@ -716,7 +710,6 @@
"cmd.browser_move": "브라우저 항목 이동",
"cmd.browser_order": "브라우저 항목 정렬",
"cmd.browser_rename_group": "그룹 이름 변경",
"cmd.browser_reparent": "구성 요소로 이동",
"cmd.browser_ungroup": "그룹 해제",
"cmd.browser_visibility": "표시/숨기기",
"cmd.canvas_calibrate": "캔버스 보정",
@@ -739,7 +732,6 @@
"cmd.component_metadata": "부품 속성",
"cmd.component_metadata_set": "부품 속성 변경",
"cmd.component_move_bodies": "바디를 구성 요소로 이동",
"cmd.component_move_features": "특성을 구성 요소로 이동",
"cmd.component_move_sketches": "스케치를 구성 요소로 이동",
"cmd.component_paste_new": "새로 붙여넣기",
"cmd.component_properties": "구성 요소 물리 속성",
@@ -922,15 +914,9 @@
"cmd.render_library_surface_unbind": "Remove Surface Binding",
"cmd.render_library_targets": "렌더 리소스 대상 찾기",
"cmd.render_lights_add": "조명 추가",
"cmd.render_lights_duplicate": "렌더 조명 복제",
"cmd.render_lights_list": "렌더 조명 목록",
"cmd.render_lights_mute": "조명 음소거",
"cmd.render_lights_remove": "렌더 조명 제거",
"cmd.render_lights_set": "렌더 조명 설정",
"cmd.render_lights_solo": "광원 단독 표시",
"cmd.render_output_size": "렌더 출력 크기 설정",
"cmd.render_preflight": "렌더 요청 확인",
"cmd.render_preflight_copy": "렌더 검사 보고서 복사",
"cmd.render_result_close": "렌더 이미지 닫기",
"cmd.render_result_copy": "렌더 이미지 복사",
"cmd.render_result_pin": "표시된 렌더 결과 유지",
@@ -958,16 +944,6 @@
"cmd.sheet_refold": "다시 접기",
"cmd.sheet_rules": "판금 규칙 목록",
"cmd.sheet_unfold": "펼치기",
"cmd.sketch.construction_line": "보조 직선",
"cmd.sketch.construction_line.angle": "각도 지정 보조 직선",
"cmd.sketch.construction_line.bisector": "각의 이등분선",
"cmd.sketch.construction_line.horizontal": "수평 보조 직선",
"cmd.sketch.construction_line.parallel": "평행 보조 직선",
"cmd.sketch.construction_line.perpendicular": "직교 보조 직선",
"cmd.sketch.construction_line.tangent_at": "곡선 위 점에서의 접선",
"cmd.sketch.construction_line.tangent_external": "외부 점을 지나는 접선",
"cmd.sketch.construction_line.tangent_two": "공통 접선",
"cmd.sketch.construction_line.vertical": "수직 보조 직선",
"cmd.sketch_arc_center_point": "중심점 호",
"cmd.sketch_arc_tangent": "접선 호",
"cmd.sketch_arc_three_point": "3점 호",
@@ -997,8 +973,6 @@
"cmd.sketch_draw_dimensioned": "치수가 있는 스케치 개체 그리기",
"cmd.sketch_edit": "스케치 편집",
"cmd.sketch_edit_text": "텍스트 편집",
"cmd.sketch_equation_curve": "방정식 곡선",
"cmd.sketch_equation_curve_edit": "방정식 곡선 편집",
"cmd.sketch_export_dxf": "DXF로 저장",
"cmd.sketch_finish_auto_constrain": "자동 구속으로 완료",
"cmd.sketch_fit_curves_to_section": "메시 단면에 곡선 맞추기",
@@ -1082,18 +1056,15 @@
"cmd.timeline_export_script": "명령 스크립트 내보내기",
"cmd.timeline_inspect": "특성 검사",
"cmd.timeline_paste": "특성 붙여넣기",
"cmd.timeline_play": "기록 재생",
"cmd.timeline_redefine": "특성 편집",
"cmd.timeline_rename": "이름 변경",
"cmd.timeline_reorder": "특성 순서 변경",
"cmd.timeline_roll_to": "이력 마커 이동",
"cmd.timeline_rollback": "타임라인 마커 이동",
"cmd.timeline_stop": "기록 재생 중지",
"cmd.timeline_suppress": "특성 비활성화",
"cmd.view.render_browser": "렌더 브라우저",
"cmd.view.render_dock": "렌더 도크 이동",
"cmd.view.render_focus": "렌더 집중 보기",
"cmd.view.status_items": "뷰포트 상태 항목",
"cmd.view_ambient_occlusion": "앰비언트 오클루전",
"cmd.view_angle_readout": "뷰 각도",
"cmd.view_apply": "이름 있는 보기 복원",
@@ -1103,20 +1074,15 @@
"cmd.view_navigate": "보기 탐색",
"cmd.view_normal_to": "선택 항목에 수직",
"cmd.view_rename": "이름 있는 보기 이름 변경",
"cmd.view_render_frame": "렌더 프레임 가이드",
"cmd.view_save": "새 이름 있는 보기",
"cmd.view_shots_strip": "샷 스트립",
"color.copy": "클릭하여 색상 값 복사",
"color.edit": "클릭하여 색상 편집",
"color.gamma": "색상 값을 0-255 감마 공간으로 표시 중",
"color.hex": "Hex",
"color.hex_help": "#rrggbb 또는 #rrggbbaa 입력. 6자리 값은 불투명도 유지",
"color.hex_hint": "#rrggbb",
"color.hue": "색조",
"color.linear": "색상 값을 0-1 선형 공간으로 표시 중",
"color.saturation_value": "채도 및 명도",
"color.selected": "선택한 색상",
"config.column_filter_empty": "일치하는 열이 없습니다",
"contact.components_count": "구성요소 {count}개",
"contact.enabled_label": "활성화됨",
"coupling.gear_1": "기어 1",
@@ -1209,17 +1175,6 @@
"help.mit": "MIT 라이선스",
"help.notice": "NOTICE",
"help.pointcloud.insert": "PLY, XYZ 또는 PTS 스캔을 모델 옆에 포인트 클라우드로 삽입합니다. 측정 데이터를 참고하여 모델링할 때 사용합니다.",
"help.sketch.construction_line": "두 점을 지나는 무한 보조 직선을 만듭니다. 스케치 프로파일을 나누지 않고 작도할 수 있습니다.",
"help.sketch.construction_line.angle": "스케치 X축을 기준으로 지정한 각도의 무한 보조 직선을 만듭니다. 점을 선택한 뒤 각도를 입력하거나 방향을 선택합니다.",
"help.sketch.construction_line.bisector": "교차하는 두 스케치 직선을 선택한 뒤 두 각의 이등분선 중 하나를 선택합니다. 결과는 원본 직선의 편집을 따릅니다.",
"help.sketch.construction_line.horizontal": "한 점을 지나는 무한 수평 보조 직선을 만듭니다. 나중에 편집해도 수평 구속이 유지됩니다.",
"help.sketch.construction_line.parallel": "스케치 직선을 선택한 뒤 평행한 무한 보조 직선을 배치합니다. 다른 참조를 선택하려면 마우스 오른쪽 버튼을 클릭합니다.",
"help.sketch.construction_line.perpendicular": "스케치 직선을 선택한 뒤 직교하는 무한 보조 직선을 배치합니다. 다른 참조를 선택하려면 마우스 오른쪽 버튼을 클릭합니다.",
"help.sketch.construction_line.tangent_at": "원이나 원호 위의 점, 또는 열린 스플라인이나 원뿔 곡선의 끝점에 접선을 만듭니다. 곡선을 선택한 뒤 접점을 선택합니다.",
"help.sketch.construction_line.tangent_external": "원 또는 원호, 외부 점, 접선 해를 차례로 선택합니다. 미리보기에는 그려진 원호 위의 접점만 표시됩니다.",
"help.sketch.construction_line.tangent_two": "두 원 또는 원호를 선택한 뒤 미리보기에서 공통 접선을 선택합니다. 접점은 그려진 곡선 위에 있어야 합니다.",
"help.sketch.construction_line.vertical": "한 점을 지나는 무한 수직 보조 직선을 만듭니다. 나중에 편집해도 수직 구속이 유지됩니다.",
"help.sketch.equation_curve": "범위에 걸쳐 수식으로 곡선을 그립니다: x(t)와 y(t), 또는 y = f(x). 수식에 매개변수를 쓸 수 있으며 곡선이 그 값을 따라갑니다. 사인파, 나선, 기어 이의 인벌류트에 사용합니다.",
"help.solid.chamfer": "선택한 모서리를 지정한 거리만큼 평평하게 깎습니다. 날카로운 모서리를 다듬거나 핀 또는 나사가 쉽게 들어가도록 할 때 사용합니다.",
"help.solid.extrude": "스케치 프로파일을 지정한 거리만큼 3D로 밀어내 재료를 더하거나 제거합니다. 평면 윤곽을 블록, 보스 또는 포켓으로 만들 때 사용합니다.",
"help.solid.fillet": "선택한 모서리를 지정한 반지름의 매끄러운 원호로 둥글게 만듭니다. 강도, 편의성 또는 외관을 위해 날카로운 모서리를 부드럽게 할 때 사용합니다.",
@@ -1227,7 +1182,6 @@
"help.solid.revolve": "스케치 프로파일을 축을 중심으로 회전시켜 둥근 솔리드를 만듭니다. 샤프트, 손잡이, 그릇 및 중심선을 기준으로 둥근 모든 부품에 사용합니다.",
"help.solid.shell": "솔리드의 속을 비우고 지정한 두께의 벽을 남기며, 선택한 면을 열 수도 있습니다. 상자, 커버 및 기타 얇은 벽 부품에 사용합니다.",
"help.third_party": "타사 라이선스",
"help.timeline.play": "남은 피처를 하나씩 재생하고 각 재생성 후 0.5초 동안 멈춥니다. 이 명령을 다시 실행하거나 Escape 키를 누르면 중지됩니다. 끝으로 이동은 즉시 마지막 단계로 이동합니다.",
"history.sketch_under_constrained": "구속 부족 (자유도 {count}개)",
"history.sketch_under_constrained_one": "구속 부족 (자유도 {count}개)",
"home.back": "{name}(으)로 돌아가기",
@@ -1356,8 +1310,6 @@
"nav.maya.help": "Alt+왼쪽 드래그는 회전, Alt+가운데 드래그는 이동, Alt+오른쪽 드래그는 확대/축소입니다. 가운데 드래그로도 이동합니다",
"nav.openscad.help": "빈 공간에서 왼쪽 드래그는 회전, Shift+왼쪽 드래그는 상자 선택, 스케치 형상 드래그는 편집입니다. 오른쪽 또는 가운데 드래그는 이동, Shift+오른쪽 또는 Shift+가운데 드래그는 확대/축소입니다",
"nav.perspective.sketch": "스케치 편집 중에는 직교 뷰를 사용합니다. 원근 뷰를 전환하려면 스케치를 마치세요.",
"nav.right_drag_orbits.help": "끄면 오른쪽 드래그는 카메라에 영향을 주지 않고 오른쪽 버튼은 컨텍스트 메뉴만 엽니다. SolidWorks 마우스 매핑을 선택하면 꺼집니다.",
"nav.right_drag_orbits.label": "오른쪽 드래그로 회전",
"nav.solidworks.help": "가운데 드래그는 회전, Ctrl+가운데 드래그는 이동, Shift+가운데 드래그는 확대/축소, 오른쪽 드래그는 회전입니다",
"nav.tinkercad.help": "오른쪽 드래그는 회전, 가운데 또는 Shift+오른쪽 드래그는 이동입니다",
"nav.touchpad.help": "Shift를 누른 채 포인터를 움직이면 화면이 이동하고, Alt/Option을 누른 채 움직이면 회전합니다. 마우스 버튼은 필요 없습니다. 세로 스크롤로 확대/축소합니다.",
@@ -1522,8 +1474,6 @@
"prefs.bodies_folders_never": "표시 안 함",
"prefs.bodies_folders_several": "바디가 여러 개일 때만",
"prefs.bottom": "아래쪽",
"prefs.bottom_centre": "하단 가운데",
"prefs.bottom_right": "오른쪽 아래",
"prefs.browser": "브라우저",
"prefs.built_in": "기본 제공",
"prefs.button_left": "왼쪽 드래그",
@@ -1571,8 +1521,6 @@
"prefs.history": "이력",
"prefs.history_origin_bodies": "원점과 바디를 맨 위에 표시",
"prefs.history_origin_bodies_note": "왼쪽 또는 브라우저 아래의 히스토리가 활성 구성 요소의 바디 폴더와 원점으로 시작하며, 브라우저처럼 표시 아이콘과 메뉴가 있습니다. 아래쪽 히스토리는 바뀌지 않습니다.",
"prefs.history_play_button": "기록 컨트롤에 기록 재생 버튼 표시",
"prefs.history_play_button_note": "기록 컨트롤의 한 단계 뒤로와 한 단계 앞으로 사이에 기록 재생을 추가합니다. 컨트롤을 마우스 오른쪽 버튼으로 클릭해 표시하거나 숨길 수도 있습니다.",
"prefs.hold_stop_snapping": "누르고 있으면 스냅 중지",
"prefs.icons_only": "아이콘만",
"prefs.imported_file": "가져온 파일",
@@ -1586,8 +1534,6 @@
"prefs.layout_note": "컴팩트는 패널을 창 가장자리에 고정합니다. 브라우저 반투명은 플로팅에서 사용할 수 있습니다. 어시스턴트 위치는 어시스턴트 페이지에서 바꿀 수 있습니다.",
"prefs.left": "왼쪽",
"prefs.left_click": "왼쪽 클릭",
"prefs.line_drag_draws_one": "누른 채 드래그하면 선 하나 그리기",
"prefs.line_drag_draws_one_note": "선 도구에서 누르고 드래그한 뒤 놓으면 누른 곳에서 놓은 곳까지 선 하나를 그리고 거기서 끝납니다. 클릭하면 이전처럼 이어지는 선을 그립니다. 끄면: 드래그는 클릭처럼 놓은 곳에 점을 둡니다.",
"prefs.live_input": "실시간 입력",
"prefs.live_preview": "실시간 미리보기",
"prefs.max_file_size": "열 수 있는 최대 파일 크기",
@@ -1612,12 +1558,7 @@
"prefs.origin_plane_names": "원점 평면 이름",
"prefs.origin_plane_names_note": "브라우저, 대화 상자, 목록에 표시되는 이름입니다. {top}은 XY, {front}는 XZ, {right}는 YZ이며 Z가 위쪽입니다. 명령, 스크립트, 저장된 디자인은 XY, XZ, YZ를 유지합니다.",
"prefs.overall_speed": "전체 속도",
"prefs.persistent_ribbon_pressed": "활성 리본 명령 강조 표시",
"prefs.persistent_ribbon_pressed_help": "효과가 켜져 있는 동안 리본 명령을 강조 표시합니다. 끄면 이전의 중립적인 모양과 명령 도움말을 유지합니다.",
"prefs.perspective_fov": "시야각",
"prefs.preview_choices": "선택 항목 미리보기",
"prefs.project_options_dialog": "Project 옵션 대화상자",
"prefs.project_options_dialog_note": "켜기: 투영 전에 지오메트리 또는 바디와 투영 링크를 선택합니다. 끄기: 기존 직접 선택 작업 흐름을 유지합니다.",
"prefs.quality_default": "기본값",
"prefs.quality_fastest": "가장 빠름",
"prefs.quality_slowest": "가장 느림",
@@ -1636,17 +1577,6 @@
"prefs.shift_add_ctrl_toggle": "Shift는 추가만, Ctrl / Cmd는 토글",
"prefs.shift_add_note": "켬: Shift는 추가, Ctrl / Cmd는 토글. 끔(기본값): 둘 다 토글.",
"prefs.shortcuts": "단축키",
"prefs.single_surface_analysis": "표면 분석 하나만 사용",
"prefs.single_surface_analysis_help": "끄면 표면 음영 분석과 연속성 분석을 함께 유지할 수 있습니다. 켜면 마지막으로 시작하거나 변경한 분석만 유지됩니다.",
"prefs.sketch_align_points": "그리는 동안 다른 스케치 점에 맞추기",
"prefs.sketch_align_points_note": "그리는 동안 점이 한 스케치 점과 수평으로, 다른 점과 수직으로 동시에 맞춰지고 점선 안내선이 표시됩니다. 클릭하면 두 정렬이 모두 유지됩니다. 끄기: 이전 점에만, 한 번에 한 축씩 맞춥니다.",
"prefs.sketch_conflict_colour": "충돌하는 기하를 충돌 색상으로 표시",
"prefs.sketch_conflict_colour_note": "스케치의 구속 조건이 충돌하는 동안 실패한 구속 조건의 글리프나 치수뿐 아니라 그 구속 조건이 잡고 있는 곡선과 점도 충돌 색상으로 그립니다. 끄기: 평소 색상을 유지합니다.",
"prefs.sketch_construction_lines": "확장 보조 직선 도구",
"prefs.sketch_open_look_at": "스케치를 열 때 정면으로 돌리기",
"prefs.sketch_open_look_at_note": "끄기: 스케치를 만들거나 편집해도 뷰가 그대로입니다. 필요할 때 '바라보기'로 스케치를 정면으로 봅니다.",
"prefs.sketch_recent_snap": "최근 중심과 중점에 자동 스냅",
"prefs.sketch_recent_snap_note": "그리는 동안 최근에 사용한 두 원의 중심 또는 직선 모서리 중점의 안내선이 만나는 위치로 커서를 스냅합니다. 끄기: 안내선은 보기만 하고 커서는 움직이지 않습니다.",
"prefs.sketch_selection": "스케치 및 선택",
"prefs.sketch_selection_heading": "스케치 및 선택",
"prefs.sketch_selection_note": "스케치가 스냅되는 방식과 클릭으로 선택하는 방식입니다.",
@@ -1679,17 +1609,9 @@
"prefs.timeline_half_hour": "−30분",
"prefs.timeline_now": "지금",
"prefs.timeline_quarter_hour": "−15",
"prefs.toast_place": "알림",
"prefs.toggle_item": "항목을 추가하거나 다시 제거",
"prefs.toolbar": "도구 모음",
"prefs.toolbar_tabs": "도구 모음 탭",
"prefs.top": "위쪽",
"prefs.trackpad_zoom_modifier": "다음 키를 누른 채 두 손가락으로 스크롤하여 확대/축소",
"prefs.trackpad_zoom_modifier.alt": "⌥ / Alt",
"prefs.trackpad_zoom_modifier.cmd": "⌘",
"prefs.trackpad_zoom_modifier.ctrl": "Ctrl",
"prefs.trackpad_zoom_modifier.help": "이 키만 누른 채 세로로 스크롤하면 포인터 위치를 기준으로 확대/축소합니다. 끄면 기존 스크롤 동작을 유지합니다.",
"prefs.trackpad_zoom_modifier.off": "끄기",
"prefs.translucent": "반투명",
"prefs.under_browser": "브라우저 아래",
"prefs.under_cursor": "커서 아래",
@@ -1699,21 +1621,13 @@
"prefs.view_confirm_corner": "뷰 모서리에 확인 및 취소",
"prefs.view_confirm_corner_note": "대화 상자나 스케치가 열려 있는 동안 뷰 오른쪽 위의 체크와 X 표시가 대화 상자의 확인과 취소와 같은 동작을 하거나 스케치를 마치고 취소합니다. 뷰 탐색기는 그 아래로 내려갑니다.",
"prefs.viewport": "뷰포트",
"prefs.viewport_analysis_status": "뷰포트 해석 상태 표시",
"prefs.viewport_analysis_status_help": "활성 해석을 뷰포트 위에 표시하고 각 항목에서 범례를 엽니다. Esc로 최신 해석을 끕니다. 끄면 모서리 범례와 이전 Esc 동작으로 돌아갑니다.",
"prefs.wheel": "휠",
"prefs.wheel_trackpad": "휠 및 트랙패드",
"prefs.workspace": "작업 공간",
"prefs.zoom_stop_at_model": "모델에서 확대/축소 멈추기",
"prefs.zoom_stop_at_model_tip": "3D 마우스와 장치 앱은 뷰 중앙의 표면을 향해 확대/축소하고, 드래그 확대/축소는 드래그 시작점을 고정합니다. 끄면 모델을 통과할 수 있습니다. 휠과 핀치는 별도의 커서로 확대/축소 설정을 사용합니다",
"prefs.zoom_toward_cursor": "확대/축소, 커서 방향으로",
"properties.title": "속성: {name}",
"recovery.days_ago": "{count}일 전",
"recovery.detail": "{file} · 피처 {features}개 · {when} 자동 저장",
"recovery.discard_all": "모두 버리기",
"recovery.discard_all_detail": "이 작업은 되돌릴 수 없습니다.",
"recovery.discard_all_title": "자동 저장 {count}개를 버리시겠습니까?",
"recovery.discard_all_title_one": "자동 저장 1개를 버리시겠습니까?",
"recovery.hours_ago": "{count}시간 전",
"recovery.just_now": "방금",
"recovery.min_ago": "{count}분 전",
@@ -1760,7 +1674,6 @@
"render.appearance_editor.v_up": "텍스처 V가 위쪽을 향함",
"render.appearance_editor.weight": "가중치",
"render.appearances": "외관",
"render.assign_help": "클릭하여 선택 항목에 적용하거나 드래그하여 미리 보고 놓으세요. 선택이 없으면 칠하기를 시작합니다.",
"render.background": "장면 배경",
"render.bloom_enable": "표시 블룸",
"render.bloom_help": "양의 선형 하이라이트를 세 번의 정규화 필터로 확산하는 출력 전용 효과입니다. 반경은 출력 픽셀 단위이며 sRGB 전에 더합니다. 렌즈·볼륨·수렴 개선이 아니며 원본 EXR은 변하지 않습니다.",
@@ -1768,7 +1681,6 @@
"render.bloom_radius": "블룸 반경",
"render.bloom_strength": "블룸 강도",
"render.bloom_threshold": "선형 하이라이트 임계값",
"render.browse_looks": "찾아보기…",
"render.category_metal": "금속",
"render.category_paint": "페인트",
"render.category_plastic": "플라스틱",
@@ -1776,82 +1688,6 @@
"render.check_opaque": "투명도: 불투명 표면만 지원하며 배경 알파를 지원합니다.",
"render.check_sorted_alpha": "투명도: 정렬된 알파 근사.",
"render.check_transmission": "투명도: 물리적 투과.",
"render.children.absolute_floor": "절대 하한",
"render.children.adaptive": "적응형",
"render.children.add_look_reason": "활성 상태와 강도를 편집하려면 룩을 추가하세요.",
"render.children.all_shots": "모든 샷",
"render.children.bloom": "블룸",
"render.children.check": "검사",
"render.children.check_now": "지금 검사",
"render.children.chromatic": "색수차",
"render.children.compact": "소형",
"render.children.contrast": "대비",
"render.children.copy_image": "복사",
"render.children.copy_job": "작업 JSON 복사",
"render.children.copy_request": "요청 JSON 복사",
"render.children.coverage_error": "커버리지 오차",
"render.children.cpu": "CPU 레이 트레이싱",
"render.children.denoise": "완성 이미지의 노이즈 줄이기",
"render.children.depth": "경로 깊이",
"render.children.distortion": "왜곡",
"render.children.edge_samples": "모서리 샘플",
"render.children.effects_banner": "이 효과에는 GPU 경로 추적이 필요합니다. 열어도 방식은 바뀌지 않습니다.",
"render.children.enable_adaptive": "적응형 한도를 편집하려면 독립 파일럿을 활성화하세요.",
"render.children.enable_bloom": "강도, 임계값, 반경을 편집하려면 블룸을 활성화하세요.",
"render.children.finishing": "마무리",
"render.children.flare": "플레어",
"render.children.fresnel": "프레넬 계층",
"render.children.ghosts": "고스트 링",
"render.children.glass": "유리 광 전송",
"render.children.go_to": "{editor}(으)로 이동",
"render.children.grain": "입자",
"render.children.halo": "후광",
"render.children.hdr": "HDR",
"render.children.keep_master": "원시 선형 마스터 유지",
"render.children.last_result": "최근: {number} · {width} × {height} · {phase}",
"render.children.lens_effects": "렌즈 효과",
"render.children.look_summary": "{tone} · 룩 {count}개",
"render.children.looks": "크리에이티브 룩",
"render.children.memory": "메모리",
"render.children.method": "방식",
"render.children.minimum": "최소값",
"render.children.needs_cpu": "CPU 레이 트레이싱이 필요합니다. 열어도 방식은 바뀌지 않습니다.",
"render.children.nested": "인증된 중첩 유전체",
"render.children.not_checked": "검사 안 됨",
"render.children.path": "경로 추적",
"render.children.pilots": "파일럿 샘플",
"render.children.preview": "미리보기 데이터",
"render.children.progressive_reason": "샘플 수와 시드를 편집하려면 점진적 모드를 선택하세요.",
"render.children.radius": "반경",
"render.children.reflect_depth": "반사 깊이",
"render.children.reflect_samples": "반사 샘플",
"render.children.regrade": "다시 그레이딩",
"render.children.relative_error": "상대 오차",
"render.children.render": "렌더링",
"render.children.render_shot": "샷 렌더링",
"render.children.renderer": "렌더러",
"render.children.renderers": "렌더러",
"render.children.request": "이 요청",
"render.children.reset_finishing": "마무리 초기화",
"render.children.review_quality": "품질 사양 검토…",
"render.children.rgb_gain": "RGB 게인",
"render.children.samples": "샘플",
"render.children.sampling": "샘플링",
"render.children.saturation": "채도",
"render.children.scene_summary": "바디 {bodies}개 · 삼각형 {triangles}개",
"render.children.seed": "시드",
"render.children.sharpening": "선명도",
"render.children.single_image": "단일 이미지",
"render.children.soft_focus": "소프트 포커스",
"render.children.streak": "광선",
"render.children.strength": "강도",
"render.children.studio": "스튜디오",
"render.children.threshold": "임계값",
"render.children.tone": "톤",
"render.children.under_hood": "내부 정보",
"render.children.vignette": "비네트",
"render.children.workstation": "워크스테이션",
"render.choose_look": "먼저 외관 라이브러리에서 외관을 선택하세요",
"render.clear_stage": "Remove saved stage",
"render.cpu_budget": "CPU 리소스 프로필",
"render.cpu_budget_bodies": "바디 수 상한",
@@ -1866,86 +1702,6 @@
"render.cpu_budget_workstation": "워크스테이션 (대규모 장면)",
"render.effects_gpu_only": "이 효과를 사용하려면 GPU 경로 추적이 필요합니다. 페이지를 바꿔도 렌더러는 자동으로 전환되지 않습니다.",
"render.emitted_axis": "방출 축",
"render.env_advanced": "고급",
"render.env_backdrop": "배경",
"render.env_backdrop_pending": "렌더러가 환경 배경 표시와 흐림을 아직 지원하지 않습니다.",
"render.env_blur": "흐림",
"render.env_change": "변경",
"render.env_choose_source": "조명을 편집하기 전에 스튜디오 및 환경에서 환경을 선택하세요.",
"render.env_clear": "투명",
"render.env_colour": "색상",
"render.env_environments": "환경",
"render.env_ground": "지면",
"render.env_ground_pending": "물리적 지면은 유한한 확산 표면으로 그림자를 받습니다. 그림자만 포착하거나 지면에 반사하는 기능은 아직 지원하지 않습니다.",
"render.env_intensity": "강도",
"render.env_invalid_edit": "환경 편집 내용이 올바르지 않습니다.",
"render.env_physical_ground": "물리적 지면",
"render.env_preview_help": "구 예시이며 선택한 환경의 미리보기가 아닙니다.",
"render.env_reflection": "반사",
"render.env_ring_help": "링을 드래그하여 조명을 회전하세요. Shift를 누르면 15° 간격으로 스냅합니다.",
"render.env_rotate": "회전",
"render.env_set": "렌더 환경 설정",
"render.env_shadow_catcher": "그림자 포착",
"render.env_show_environment": "환경 표시",
"render.env_source": "소스",
"render.env_stage_details": "지면 편집에는 레이 트레이싱과 단일 지면 패널이 필요합니다. 다른 무대 패널은 장면에서 편집하세요.",
"render.env_studios": "스튜디오",
"render.environment.albedo": "알베도",
"render.environment.atmosphere": "대기",
"render.environment.backdrop_note": "배경은 카메라에만 보이며 조명, 그림자, 반사에 영향을 주지 않습니다. 투명 출력과 함께 사용할 수 없습니다.",
"render.environment.blur_pending": "흐림을 사용할 수 없습니다. 렌더러에 배경 흐림 설정이 없습니다.",
"render.environment.builtin": "내장 HDR",
"render.environment.check": "파일 확인",
"render.environment.checked": "HDR 파일을 확인했습니다. 저장하면 이 데이터가 포함됩니다.",
"render.environment.choose": "HDR 선택…",
"render.environment.constant": "상수",
"render.environment.cyclorama": "사이클로라마",
"render.environment.embedded": "이 디자인 안에 저장됨",
"render.environment.end": "끝",
"render.environment.extinction": "소광 계수",
"render.environment.file": "파일",
"render.environment.fit": "지면 맞춤 및 저장",
"render.environment.floor_wall": "바닥과 벽",
"render.environment.gap": "간격",
"render.environment.gradient": "그라데이션",
"render.environment.gradient_gpu": "그라데이션 배경에는 GPU 경로 추적이 필요합니다.",
"render.environment.ground": "지면과 스테이지",
"render.environment.hdr": "HDR",
"render.environment.hdr_file": "HDR 파일",
"render.environment.horizon": "수평선",
"render.environment.horizontal": "수평",
"render.environment.keep": "유지",
"render.environment.lighting_samples": "조명 샘플",
"render.environment.margin": "범위 여백",
"render.environment.max": "최대 경계",
"render.environment.medium": "참여 매질",
"render.environment.min": "최소 경계",
"render.environment.mode": "모드",
"render.environment.needs_gpu": "GPU 경로 추적이 필요합니다.",
"render.environment.none": "없음",
"render.environment.orientation": "방향과 강도",
"render.environment.phase": "위상",
"render.environment.primaries": "지정되지 않은 원색을 선형 sRGB로 처리",
"render.environment.primaries_gpu": "지정되지 않은 원색 해석에는 GPU 경로 추적이 필요합니다.",
"render.environment.radial": "방사형",
"render.environment.radial_only": "중심과 반경은 방사형 모드에 적용됩니다.",
"render.environment.reflectance": "반사율",
"render.environment.remove": "스테이지 제거",
"render.environment.remove_confirm": "저장된 스테이지를 제거할까요?",
"render.environment.remove_note": "이 샷에서 패시브 패널 {count}개를 제거합니다. 카메라 배경은 유지됩니다.",
"render.environment.replace": "기존 스테이지 교체 확인",
"render.environment.rotation_hdr": "CPU 광선 추적의 회전에는 HDR 광원이 필요합니다.",
"render.environment.samples_cpu": "GPU 조명 샘플은 경로 예산으로 정해집니다. 이 설정에는 CPU 광선 추적이 필요합니다.",
"render.environment.saved_panels": "저장된 패널 {count}",
"render.environment.sky_ground": "지면",
"render.environment.sky_note": "조명용 오리지널 하늘 그라데이션이며 보정된 대기 모델은 아닙니다.",
"render.environment.source_raytrace": "환경 광원에는 CPU 또는 GPU 광선 추적이 필요합니다.",
"render.environment.stage_raytrace": "물리 스테이지에는 CPU 또는 GPU 광선 추적이 필요합니다.",
"render.environment.start": "시작",
"render.environment.vertical": "수직",
"render.environment.world": "월드",
"render.environment.world_pending": "월드 배경을 사용할 수 없습니다. 환경의 카메라 표시를 저장하는 설정이 아직 없습니다.",
"render.environment.zenith": "천정",
"render.environment_tiles_require_raytrace": "환경에는 CPU 또는 GPU 광선 추적이 필요합니다. 출력 편집기에서 선택하세요.",
"render.error_area_samples": "area_samples는 1, 4, 16 또는 64여야 함",
"render.error_binding_allocation": "재질 연결을 할당할 수 없음",
@@ -2010,40 +1766,14 @@
"render.fixed_camera": "카메라",
"render.fixed_world": "월드",
"render.fold_browser": "브라우저 접기",
"render.frame_aspect": "화면 비율",
"render.frame_centre_mark": "중심 표시",
"render.frame_copy_limit": "사용 가능한 복제 샷 이름이 없습니다",
"render.frame_copy_name": "{name} 복사본 {number}",
"render.frame_custom": "사용자 지정",
"render.frame_distance_unit": " × 크기",
"render.frame_duplicate": "복제",
"render.frame_exposure": "노출",
"render.frame_fov": "시야각",
"render.frame_guides": "가이드",
"render.frame_invalid_aspect": "잘못된 화면 비율 프리셋",
"render.frame_lens": "시야각 {fov}° · 약 {mm} mm",
"render.frame_name": "이름",
"render.frame_output_size": "출력 크기",
"render.frame_photo": "3:2 · 사진",
"render.frame_portrait": "4:5 · 세로",
"render.frame_presets": "구도 프리셋",
"render.frame_presets_pending": "샷 편집기와 함께 제공 예정",
"render.frame_projection": "투영",
"render.frame_render_shot": "이 샷 렌더링",
"render.frame_rule_thirds": "삼분할 법칙",
"render.frame_safe_area": "안전 영역",
"render.frame_shot_title": "샷 · {name}",
"render.frame_square": "1:1 · 정사각형",
"render.frame_tall": "9:16 · 세로형",
"render.frame_thirds": "삼분할선",
"render.frame_wide": "16:9 · 와이드스크린",
"render.heading_batch": "일괄 처리",
"render.heading_frame": "프레임",
"render.heading_lens": "렌즈",
"render.heading_results": "결과",
"render.heading_shots": "샷",
"render.hide_shots_label": "샷 스트립 숨기기",
"render.hover_look": "{object} · {look} · 클릭하여 선택",
"render.image_cancelled": "렌더링 취소됨",
"render.image_cancelling": "취소 중",
"render.image_completed": "이미지 내보내기 준비됨",
@@ -2150,86 +1880,8 @@
"render.library_title": "렌더 리소스 라이브러리",
"render.library_uniform_ack": "공간 변화나 고급 효과 없는 균일 근사 사용",
"render.library_users": "사용 위치",
"render.light_aim": "조준 대상",
"render.light_anchor_pending": "조명 좌표계 변경은 아직 지원되지 않습니다.",
"render.light_azimuth": "방위각",
"render.light_backend_limit": "조명을 편집하려면 CPU 레이 트레이싱이나 명시적인 GPU 스튜디오를 선택하세요. 기존 GPU 스튜디오 조명은 읽기 전용입니다.",
"render.light_behaviour": "동작",
"render.light_default_fill": "필 라이트",
"render.light_default_key": "키 라이트",
"render.light_default_number": "조명 {number}",
"render.light_default_rim": "림 라이트",
"render.light_delete": "삭제",
"render.light_distance": "거리",
"render.light_duplicate": "복제",
"render.light_elevation": "고도각",
"render.light_gpu_punctual": "포인트와 스폿 조명은 CPU 레이 트레이싱에서 사용할 수 있습니다.",
"render.light_hard_shadow": "이 조명은 단단한 그림자만 지원합니다.",
"render.light_intensity": "강도",
"render.light_missing": "이 조명이 더 이상 없습니다. 브라우저에서 조명을 선택하세요.",
"render.light_place_highlight": "하이라이트로 배치",
"render.light_place_pending": "하이라이트 배치는 뷰포트 조명 선택이 필요하며 아직 지원되지 않습니다.",
"render.light_position": "위치",
"render.light_preview_help": "라이브 뷰에는 그림자가 없으며 영역 조명은 중심 샘플로 근사됩니다. 렌더는 전체 조명 모델을 사용합니다.",
"render.light_product_centre": "제품 중심",
"render.light_size": "크기",
"render.light_softness": "부드러움",
"render.light_temperature": "색온도",
"render.light_temperature_help": "흑체 색상 근사값이며 선형 RGB로 저장됩니다.",
"render.light_type": "유형",
"render.light_type_area": "영역",
"render.light_type_point": "포인트",
"render.light_type_spot": "스폿",
"render.light_type_sun": "태양",
"render.light_view_only": "솔로와 음소거는 이 뷰와 렌더에만 적용되며 디자인에 저장되지 않습니다.",
"render.light_world_origin": "월드 원점",
"render.lighting_aim_point": "조준점",
"render.lighting_apply": "프리셋 적용",
"render.lighting_area_samples": "영역 샘플",
"render.lighting_budget": "한도",
"render.lighting_budget_help": "개수는 읽기 전용입니다. 조명을 추가, 복제 또는 삭제하세요. 한도는 방식에 따라 정해집니다.",
"render.lighting_colour": "색상",
"render.lighting_consent": "이 프리셋으로 방향 조명 교체",
"render.lighting_custom": "사용자 조명",
"render.lighting_custom_help": "사용자 조명을 선택하면 프리셋이 트리의 각 행에서 편집 가능한 조명으로 변환됩니다.",
"render.lighting_direction": "방향 X Y Z",
"render.lighting_direction_help": "또는 조명 방향을 입력하세요 (X Y Z).",
"render.lighting_distance_unit": " × 크기",
"render.lighting_edge_u": "변 U 벡터",
"render.lighting_edge_v": "변 V 벡터",
"render.lighting_falloff": "감쇠",
"render.lighting_falloff_help": "강도는 기준 거리에서의 값입니다.",
"render.lighting_height": "높이 V",
"render.lighting_minimum": "최솟값",
"render.lighting_mute": "이 조명 끄기",
"render.lighting_point": "점",
"render.lighting_preset": "스튜디오 프리셋",
"render.lighting_preset_cpu": "방향 조명 프리셋에는 CPU 레이 트레이싱이 필요합니다. GPU는 명시적 태양 및 영역 조명을 사용합니다.",
"render.lighting_preset_row": "프리셋",
"render.lighting_radiance": "복사휘도",
"render.lighting_reference": "기준",
"render.lighting_review_help": "방향 조명 목록을 교체합니다. 점 및 영역 조명, 환경, 그림자, 카메라와 다른 샷 설정은 유지합니다.",
"render.lighting_review_title": "조명 프리셋 검토",
"render.lighting_samples_cpu": "영역 조명 샘플은 CPU 레이 트레이싱에 적용됩니다.",
"render.lighting_samples_need_area": "영역 샘플을 설정하려면 CPU 영역 조명을 추가하세요.",
"render.lighting_samples_reason": "영역 샘플은 1, 4, 16 또는 64여야 합니다.",
"render.lighting_shadow_cpu": "그림자 스위치에는 CPU 레이 트레이싱이 필요합니다. GPU 경로 추적은 항상 그림자를 계산합니다.",
"render.lighting_shadows": "그림자 투사",
"render.lighting_shadows_section": "그림자 및 샘플링",
"render.lighting_shape": "모양",
"render.lighting_solo": "이 조명만 표시",
"render.lighting_source": "광원",
"render.lighting_source_section": "광원",
"render.lighting_spot_preserved": "이 점 조명은 유형을 변경할 때까지 저장된 스폿 원뿔을 유지합니다.",
"render.lighting_sun_distance": "태양 방향은 거리 및 조준점과 무관합니다.",
"render.lighting_unsupported": "지원되지 않음",
"render.lighting_used": "{used} / {limit}",
"render.lighting_width": "너비 U",
"render.lighting_world_position": "월드 X Y Z",
"render.lights_fixed_to": "조명 고정 기준",
"render.look_applied": "{name} 적용됨",
"render.look_material": "재질",
"render.look_pasted": "외관 붙여넣음",
"render.material_color_replace": "기본 맵으로 바디 색상 교체",
"render.material_limits": "최대 128개 바디 설정, 분리된 유리 32개, 코팅 64개, 텍스처 연결 128개. 같은 맵은 메모리를 공유하며 실제 장치 및 전체 메모리 제한은 유지됩니다.",
"render.material_metallic_map": "금속성 맵 (선형)",
@@ -2242,11 +1894,9 @@
"render.output_advanced": "고급",
"render.output_backend_ready": "준비 완료",
"render.output_check": "확인",
"render.output_check_failed": "검사 · 오류",
"render.output_check_help": "확인을 실행하면 렌더링을 시작하지 않고 요청을 검토합니다.",
"render.output_check_summary": "검사 · 참고 {count}개",
"render.output_copy": "복사",
"render.output_copy_report": "보고서 복사",
"render.output_destination": "저장 위치",
"render.output_destination_help": "완성된 이미지를 내보낼 때 대상 파일을 선택합니다.",
"render.output_dimensions": "크기",
@@ -2256,20 +1906,16 @@
"render.output_fit": "맞춤",
"render.output_format": "형식",
"render.output_format_status": "PNG는 완료된 표시 이미지 그대로입니다. 선택적 GPU EXR은 표시 필터 전 선형 FLOAT32 방사 휘도를 보존합니다. 미리보기 캐시나 다른 작업으로 바꾸어 내보내지 않습니다.",
"render.output_grading": "색 보정",
"render.output_image": "이미지",
"render.output_largest": "{width} × {height} 최대",
"render.output_presets_help": "형식, 품질 및 검사 목록은 출력 편집기에 있습니다.",
"render.output_quality": "품질",
"render.output_quality_waiting": "품질 규약 대기 중",
"render.output_ready": "렌더링 준비 완료",
"render.output_run_check": "검사 실행",
"render.output_size_limit": "{method}: 한 변 최대 {dimension} px, 총 {pixels} 픽셀. 가능한 최대 크기: {width} × {height}.",
"render.output_size_ok": "크기 정상 · {width} × {height} px",
"render.output_tools_inspector": "출력 검사기에서 크기와 형식을 편집하세요.",
"render.output_view_image": "이미지 보기",
"render.paint_label": "칠하기",
"render.painting_with": "{name}(으)로 칠하는 중",
"render.passive_stage": "Render-only stage",
"render.passive_stage_help": "Finite passive panels belong only to rendered images. They do not add CAD bodies or mass. Placement is fixed after applying; intersecting product bounds refuse. CPU does not provide diffuse bounce lighting.",
"render.perspective": "원근 카메라",
@@ -2288,7 +1934,6 @@
"render.pick_help": "바디, 면 또는 구성요소를 선택합니다. 빈 공간을 클릭하면 선택이 해제되고 Shift 또는 Ctrl로 추가하거나 전환합니다. 강조 표시는 실시간 제품 뷰에만 나타납니다.",
"render.pick_label": "선택",
"render.pick_up_label": "가져오기",
"render.pick_up_prompt": "외관을 가져올 객체를 클릭하세요",
"render.pick_waiting": "제품 선택은 아직 지원되지 않습니다.",
"render.preview": "통합 미리보기",
"render.preview_help": "래스터 셰이딩과 블렌딩 투명도를 사용합니다. 굴절, HDRI 및 최종 렌더링은 아직 지원하지 않습니다.",
@@ -2307,14 +1952,10 @@
"render.radial_compare": "비교",
"render.radial_fit": "제품 맞추기",
"render.radial_save": "샷 저장",
"render.recent_looks": "최근 외관",
"render.regrade_label": "색상 재조정",
"render.reload_settings": "저장된 설정 다시 불러오기",
"render.remove_override": "재정의 제거",
"render.replace_all": "모두 바꾸기",
"render.replace_label": "바꾸기",
"render.replace_saved_surface": "Replace an existing saved binding for this target",
"render.replace_with": "바꿀 외관",
"render.restore_camera": "저장된 카메라 복원",
"render.result_actual": "100%",
"render.result_actual_size": "100%",
@@ -2347,43 +1988,11 @@
"render.saved_surface_remove": "Remove saved binding",
"render.saved_surfaces": "Saved surface bindings",
"render.saved_surfaces_help": "Pinned built-in maps follow the selected occurrence in local millimeters. A replaced or missing target is an error, never an automatic reassignment.",
"render.scene_all_shots": "모든 샷 ({count})",
"render.scene_batch_reason": "모든 샷에는 아직 지원되지 않는 저장된 샷 렌더링 대기열이 필요합니다.",
"render.scene_check_now": "지금 검사",
"render.scene_check_passed": "검사 통과 · 참고 {notes}개",
"render.scene_check_stale": "검사가 오래됨 · 다시 검사",
"render.scene_check_unchecked": "아직 검사하지 않음 · 참고 0개",
"render.scene_light_summary": "{environment} · 조명 {lights}개",
"render.scene_look_summary": "외관 {looks}개 · 재정의 {overrides}개",
"render.scene_open_check": "검사 열기",
"render.scene_ready": "렌더링 준비",
"render.scene_reminder": "장면은 설계를 보존합니다. 렌더링에서 형상, 엔지니어링 속성 및 CAD는 변경되지 않습니다.",
"render.scene_reminders": "알림",
"render.scene_renderer_ready": "{renderer} 준비됨",
"render.scene_stages": "단계",
"render.search_appearances": "외관 {count}개 검색",
"render.setup_name": "설정 이름",
"render.shell_tab_appearance": "모양",
"render.shell_tab_camera": "카메라",
"render.shell_tab_scene": "장면",
"render.shot_aperture": "조리개",
"render.shot_distance": "거리",
"render.shot_dof": "피사계 심도",
"render.shot_edit_output": "출력에서 편집",
"render.shot_exposure_reason": "노출에는 CPU 광선 추적 또는 GPU 경로 추적이 필요합니다.",
"render.shot_exposure_section": "노출",
"render.shot_focus_distance": "초점 거리",
"render.shot_fov_reason": "시야각에는 원근 투영이 필요합니다.",
"render.shot_frame_subject": "피사체 맞추기",
"render.shot_invalid_camera": "카메라 값은 범위 내의 유한한 수여야 합니다.",
"render.shot_lens": "렌즈",
"render.shot_lens_enable_reason": "조리개와 초점 거리를 편집하려면 피사계 심도를 켜세요.",
"render.shot_lens_gpu_reason": "피사계 심도에는 GPU 경로 추적이 필요합니다.",
"render.shot_lens_perspective_reason": "피사계 심도에는 원근 투영이 필요합니다.",
"render.shot_look_selection": "선택 항목 바라보기",
"render.shot_selection_reason": "바라볼 바디나 면을 선택하세요.",
"render.shot_size": "크기",
"render.shot_target": "대상",
"render.shots_camera_changed": "이 샷을 저장한 후 카메라가 변경되었습니다",
"render.shots_name_help": "현재 샷의 고유한 이름을 입력하세요.",
"render.shots_no_result": "렌더링 결과 없음",
@@ -2403,99 +2012,11 @@
"render.size_square": "정사각형",
"render.spot_cone": "스폿 원뿔",
"render.stage_frame": "구도",
"render.stage_layout.appearance_note": "클릭하여 선택 항목에 적용합니다.",
"render.stage_layout.studio_note": "클릭하여 적용 전에 검토하세요.",
"render.stage_light": "조명",
"render.stage_look": "외관",
"render.stage_orthographic": "직교 투영",
"render.stage_output": "출력",
"render.stage_panel_count": "Saved panels",
"render.stage_panels.acknowledge": "교체 내용과 제한 사항을 확인했습니다",
"render.stage_panels.appearance_note": "클릭하여 선택 항목에 적용합니다. 모델로 끌어 놓으세요. 선택 항목이 없으면 클릭하여 페인트를 시작합니다.",
"render.stage_panels.apply": "적용",
"render.stage_panels.apply_studio": "스튜디오 적용",
"render.stage_panels.badge_blocked": "차단됨",
"render.stage_panels.badge_native": "네이티브",
"render.stage_panels.badge_projection": "투영",
"render.stage_panels.badge_reference": "참조",
"render.stage_panels.badge_specification": "사양만",
"render.stage_panels.candidate_summary": "후보: 출처가 있는 값 {count}개. 등급과 마감 검토가 필요합니다.",
"render.stage_panels.captured_bounds": "캡처한 장면 경계 사용",
"render.stage_panels.centre": "중심",
"render.stage_panels.depth": "깊이",
"render.stage_panels.environments": "환경",
"render.stage_panels.extent": "크기",
"render.stage_panels.fit_save": "맞춤 및 저장",
"render.stage_panels.gpu_required": "GPU 경로 추적 필요",
"render.stage_panels.keep": "유지",
"render.stage_panels.kept": "유지",
"render.stage_panels.kept_fields": "카메라, 샘플링, 이미지 크기, 광학 바인딩, CAD 형상 및 공학 속성.",
"render.stage_panels.kept_quality": "방식, 카메라, 조명, 환경, 스테이지, 광학 설정, 노출 및 톤 매핑.",
"render.stage_panels.mine": "내 항목",
"render.stage_panels.mine_pending": "개인 스튜디오 저장은 아직 지원되지 않습니다.",
"render.stage_panels.omits": "생략",
"render.stage_panels.paint_pending": "페인트 및 끌어서 할당은 아직 지원되지 않습니다. 외관을 적용할 대상을 선택하세요.",
"render.stage_panels.partial_reference": "후보: 출처가 있는 값만 포함합니다. 등급, 상태 및 출처를 검토하세요. 알 수 없는 값은 그대로 유지됩니다.",
"render.stage_panels.plane": "평면",
"render.stage_panels.prepare_plan": "생성 계획 준비",
"render.stage_panels.projects": "투영",
"render.stage_panels.quality_ack": "고정 예산과 생략 사항을 확인했습니다",
"render.stage_panels.quality_omissions": "적응형 중지 및 오차 목표, 별도 투과 깊이, 러시안 룰렛 규칙, 원시 선형 출력, EXR 마스터 및 수렴 인증.",
"render.stage_panels.reference": "참조",
"render.stage_panels.references": "참조",
"render.stage_panels.remove_optics": "광학 설정 제거",
"render.stage_panels.remove_optics_help": "이 샷에 저장된 광학 설정을 제거합니다. 원본 형상은 유지됩니다.",
"render.stage_panels.remove_optics_title": "저장된 광학 설정을 제거할까요?",
"render.stage_panels.remove_shot": "샷 제거",
"render.stage_panels.remove_stage": "스테이지 제거",
"render.stage_panels.remove_stage_help": "이 샷에 저장된 수동 패널을 제거합니다. 카메라 배경은 유지됩니다.",
"render.stage_panels.remove_stage_title": "저장된 스테이지를 제거할까요?",
"render.stage_panels.repeat": "반복",
"render.stage_panels.replaces": "교체",
"render.stage_panels.replaces_environment": "환경",
"render.stage_panels.replaces_maps": "선택한 바디의 임시 맵. 저장된 광학 설정과 충돌할 수 있습니다.",
"render.stage_panels.replaces_physical": "없음. 이 계획은 읽기 전용입니다.",
"render.stage_panels.replaces_quality": "이미지 크기, 고정 샘플 수, 경로 깊이, 시드 및 노이즈 제거.",
"render.stage_panels.replaces_rig": "조명, 환경 및 스테이지",
"render.stage_panels.replaces_saved_maps": "선택한 바디에 저장된 표면 맵. 임시 설정과 충돌할 수 있습니다.",
"render.stage_panels.replaces_stage": "저장된 바닥 및 수동 스테이지 패널",
"render.stage_panels.replaces_studio": "조명, 환경, 노출 및 스테이지",
"render.stage_panels.replaces_uniform": "선택한 바디의 불투명 외관. 공간 맵은 균일한 값으로 근사합니다.",
"render.stage_panels.review_environment": "환경 검토",
"render.stage_panels.review_maps": "GPU 맵 검토",
"render.stage_panels.review_physical": "물리 참조 계획",
"render.stage_panels.review_quality": "고정 샘플링 예산 사용",
"render.stage_panels.review_rig": "조명 리그 맞춤",
"render.stage_panels.review_saved_maps": "저장된 맵 검토",
"render.stage_panels.review_stage": "바닥 및 스테이지 검토",
"render.stage_panels.review_studio": "네이티브 스튜디오 검토",
"render.stage_panels.review_uniform": "균일한 외관 검토",
"render.stage_panels.rig_summary": "제작된 조명 리그 · 광원 {emitters}개, 카드 {cards}개",
"render.stage_panels.rigs": "리그",
"render.stage_panels.save_maps": "이 샷에 맵 저장",
"render.stage_panels.scope": "범위",
"render.stage_panels.search_studios": "스튜디오 검색",
"render.stage_panels.search_surfaces": "표면 및 참조 검색",
"render.stage_panels.source_note": "제작된 기본 색상 소스 맵. 측정된 재질이 아닙니다.",
"render.stage_panels.specifications": "사양 · 읽기 전용",
"render.stage_panels.studio_ack": "조명, 환경, 노출 및 스테이지 교체 확인",
"render.stage_panels.studio_note": "클릭하여 검토하세요. 확인 후에만 조명, 환경 및 스테이지를 교체합니다. 조명은 계속 편집할 수 있습니다.",
"render.stage_panels.studios": "스튜디오",
"render.stage_panels.subtitle_environment": "원본 HDR 환경 · 전체 장면",
"render.stage_panels.subtitle_maps": "제작된 공간 맵 · 임시 미리 보기",
"render.stage_panels.subtitle_physical": "읽기 전용 계획 · 재질 생성 또는 할당 없음",
"render.stage_panels.subtitle_quality": "고정 GPU 예산 · 향후 요구 사항 생략",
"render.stage_panels.subtitle_rig": "제작된 조명 리그 · 광원 및 수동 카드",
"render.stage_panels.subtitle_saved_maps": "제작된 맵 · 이 샷에 저장",
"render.stage_panels.subtitle_stage": "물리적 바닥 및 스테이지 · 제품에 맞춤",
"render.stage_panels.subtitle_studio": "네이티브 스튜디오 · 전체 장면에 적용",
"render.stage_panels.subtitle_uniform": "균일한 근사 · 측정된 재질이 아님",
"render.stage_panels.surfaces": "표면",
"render.stage_panels.surfaces_references": "표면 및 참조",
"render.stage_panels.target": "대상",
"render.stage_panels.use_budget": "이 예산 사용",
"render.stage_panels.use_maps": "GPU 맵 사용",
"render.stage_panels.use_uniform": "균일한 외관 사용",
"render.stage_preview_note": "통합 미리 보기 · 직접광",
"render.state_completed": "완료된 이미지",
"render.state_in_progress": "이미지 생성 중",
@@ -2549,13 +2070,6 @@
"render.wait_pick_up": "아직 지원되지 않음: 제품 선택 및 모양 샘플링",
"render.wait_replace": "아직 지원되지 않음: 모양이 사용된 모든 곳 바꾸기",
"render.wait_solo": "아직 지원되지 않음: 조명 표시 및 단독 표시 제어",
"render.wear_applies_to": "적용 대상",
"render.wear_layer_count": "레이어 {count}개",
"render.wear_layer_one": "레이어 {count}개",
"render.wear_layers": "레이어",
"render.wear_no_layers": "레이어 없음",
"render.wear_selected_layer": "선택한 레이어",
"render.wear_title": "마모",
"sample.bracket.about": "2 mm 판금 규칙을 적용한 베이스 플랜지, 에지 플랜지, 헴",
"sample.bracket.name": "판금 브래킷",
"sample.enclosure.about": "리프, 나사 보스, 레스트, 스냅핏이 있는 쉘 처리된 박스",
@@ -2604,7 +2118,6 @@
"settings.display_quality_note": "세밀할수록 곡면과 모서리가 더 매끄럽게 표시되지만 메시 생성 시간이 늘어납니다. 뷰포트만 바뀌며 설계나 내보내기는 바뀌지 않습니다.",
"settings.double_click_components": "구성 요소를 두 번 클릭하여 활성화하거나 연결된 구성 요소를 제자리에서 편집",
"settings.frame_rate_note": "뷰의 오른쪽 아래에 초당 프레임 수를 표시합니다.",
"settings.insert_lists_open_designs": "설계 삽입에서 다른 탭에 열린 설계를 먼저 표시",
"settings.measure_axis_distances": "X/Y/Z 거리 표시",
"settings.measure_axis_distances_help": "측정 대화상자가 열려 있는 동안 전체 거리와 함께 월드 축 방향 치수와 거리를 표시합니다.",
"settings.msaa_applies_on_restart": "안티앨리어싱은 다음에 SolidCraft를 시작할 때 적용됩니다",
@@ -2624,10 +2137,6 @@
"shortcut.unpin": "고정 해제",
"sketch is missing": "스케치가 없습니다",
"sketch.degrees_of_freedom": "자유도 {count}개",
"sketch.dimension_added_driven": "스케치가 이미 이 치수를 결정하므로 종속(참조) 치수로 추가했습니다",
"sketch.dimension_applied": "치수를 적용했습니다",
"sketch.dimension_applied_defined": "치수를 적용했습니다. 매개변수 `{name}`을(를) 정의했습니다",
"sketch.dimension_applied_renamed": "치수를 적용했습니다. 매개변수 이름을 `{name}`(으)로 지정했습니다",
"sketch.dof_left": "남은 자유도 {count}개",
"sketch.dof_left_one": "남은 자유도 {count}개",
"sketch.draw_curves": "{linetype}(으)로 그리기",
@@ -2762,10 +2271,6 @@
"ui.3d_mouse_offer": "3D 마우스를 보정하면 바뀌거나 반전된 축이 바로잡히고 속도와 조작감이 맞춰집니다.",
"ui.3d_mouse_offer_never": "다시 표시하지 않음",
"ui.3d_mouse_offer_swap": "Hidraw(직접 드라이버)로 전환",
"ui.3d_mouse_orbit": "궤도 회전",
"ui.3d_mouse_orbit_classic": "클래식",
"ui.3d_mouse_orbit_tip": "추적: 회전을 시작할 때 뷰 가운데에 있는 모델 부분을 중심으로 3D 마우스가 뷰를 회전하며, 그 점을 희미한 구로 표시합니다. 클래식: 뷰의 중심을 기준으로",
"ui.3d_mouse_orbit_traced": "추적",
"ui.3d_mouse_reading": "읽은 값",
"ui.3d_mouse_reset_axes": "축 지정 초기화",
"ui.3d_mouse_reset_view": "뷰 초기화",
@@ -3099,15 +2604,6 @@
"ui.constant": "상수",
"ui.constraints_conflict": "구속 조건 충돌",
"ui.construction": "구성선",
"ui.construction.angle_hint": "보조 직선: 점 클릭 후 각도 입력 또는 방향 선택",
"ui.construction.bisector_hint": "이등분선: 교차하는 두 직선 선택 후 원하는 해 선택",
"ui.construction.common_hint": "공통 접선: 두 원/원호 선택 후 원하는 해 선택",
"ui.construction.contact_hint": "접선: 원/원호 또는 열린 스플라인/원뿔 곡선 선택 후 접점 선택 (자유 곡선은 끝점만)",
"ui.construction.external_hint": "접선: 원 또는 원호, 외부 점, 원하는 해를 차례로 선택",
"ui.construction.free_hint": "보조 직선: 두 점 클릭; 마우스 오른쪽 버튼으로 다시 시작",
"ui.construction.point_hint": "보조 직선: 통과할 점 클릭",
"ui.construction.reference_hint": "보조 직선: 직선 선택 후 점 선택; 마우스 오른쪽 버튼으로 참조 변경",
"ui.construction.ribbon_label": "보조선",
"ui.context_menu": "컨텍스트 메뉴",
"ui.continuity_g0": "G0 꺾임",
"ui.continuity_g1": "G1 접선",
@@ -3196,14 +2692,6 @@
"ui.end_scale": "끝 배율",
"ui.entities": "요소",
"ui.equal": "동일",
"ui.equation_end": "끝",
"ui.equation_explicit": "명시적",
"ui.equation_form": "형식",
"ui.equation_note": "변수는 단위가 없는 수입니다. sin(t)는 라디안으로 읽습니다. 단위가 없는 결과는 디자인 단위입니다.",
"ui.equation_parametric": "매개변수식",
"ui.equation_x_of_t": "x(t)",
"ui.equation_y_of_t": "y(t)",
"ui.equation_y_of_x": "y(x)",
"ui.equivalent_radius": "등가 반지름",
"ui.expand": "펼치기",
"ui.exportDxf": "DXF 내보내기…",
@@ -3262,7 +2750,6 @@
"ui.heading_design": "디자인",
"ui.heading_draft": "구배",
"ui.heading_edit": "편집",
"ui.heading_equation_curve": "방정식 곡선",
"ui.heading_extrude": "돌출",
"ui.heading_fillet": "필렛",
"ui.heading_finish_editing": "편집 완료",
@@ -3334,10 +2821,6 @@
"ui.history_marker_tip": "이력 마커: 드래그하여 모델을 되돌립니다. 새 피처는 여기에 추가됩니다",
"ui.history_names": "이름",
"ui.history_play": "끝까지 재생",
"ui.history_play_button_hide": "재생 버튼 숨기기",
"ui.history_play_button_show": "재생 버튼 표시",
"ui.history_play_finish_action": "기록을 재생하기 전에 현재 작업을 완료하세요",
"ui.history_play_roll_back": "재생하기 전에 기록 마커를 이전 단계로 이동하세요",
"ui.history_show_names": "이름 표시",
"ui.history_title": "기록",
"ui.history_toggle_names": "피처 이름 표시/숨기기",
@@ -3350,10 +2833,6 @@
"ui.import_ellipsis": "가져오기…",
"ui.infinite": "무한",
"ui.insert": "삽입",
"ui.insert_design.browse": "찾아보기…",
"ui.insert_design.open_designs": "열린 설계",
"ui.insert_design.saved_file": "{name}에 저장되지 않은 변경 사항이 있어 저장된 파일을 삽입했습니다. 저장한 다음 링크 업데이트로 변경 사항을 가져오세요.",
"ui.insert_design.unsaved": "저장되지 않은 변경 사항",
"ui.inspect": "검사",
"ui.intersect": "교차",
"ui.isolate": "분리 표시",
@@ -3444,7 +2923,6 @@
"ui.pan_zoom_orbit": "이동, 확대/축소, 궤도 회전",
"ui.parallel": "평행",
"ui.parameters": "매개변수",
"ui.part_size_needs_a_part": "크기를 바꿀 삽입된 표준 부품(나사, 너트, 와셔 또는 핀)을 선택하십시오. 바디를 키우거나 줄이려면 축척을 사용하십시오.",
"ui.part_size_shared": "부품을 다시 빌드하며 추가된 피처는 모두 대체됩니다. 이 구성요소의 모든 인스턴스가 업데이트됩니다.",
"ui.paste": "붙여넣기",
"ui.path": "경로",
@@ -3485,18 +2963,6 @@
"ui.project": "투영",
"ui.project_face_edges_sketch": "면 모서리를 새 스케치로 투영",
"ui.properties": "속성",
"ui.properties.copy_matrix": "행렬 복사",
"ui.properties.first_moments": "1차 모멘트",
"ui.properties.inertia": "관성 모멘트",
"ui.properties.inertia_note": "질량 중심 기준, 월드 축 (g·{unit}²)",
"ui.properties.inertia_unavailable": "사용할 수 없음: 바디의 메시가 닫혀 있지 않습니다.",
"ui.properties.inertia_x": "Ixx, Ixy, Ixz",
"ui.properties.inertia_y": "Iyx, Iyy, Iyz",
"ui.properties.inertia_z": "Izx, Izy, Izz",
"ui.properties.measuring": "측정 중…",
"ui.properties.measuring_failed": "측정이 끝나기 전에 중단되었습니다.",
"ui.properties.principal_axis": "주축 {number}",
"ui.properties.principal_moments": "주관성 모멘트",
"ui.pull_direction": "빼기 방향",
"ui.quality": "품질",
"ui.quantity": "수량",
@@ -3529,8 +2995,6 @@
"ui.restore_defaults": "기본값 복원",
"ui.reverse_horizontal_pan_direction": "수평 이동 방향 반전",
"ui.reverse_horizontal_pan_tip": "두 손가락 수평 스크롤과 엄지 휠이 반대 방향으로 이동합니다",
"ui.reverse_trackpad_orbit_direction": "트랙패드 회전 방향 반전",
"ui.reverse_trackpad_orbit_tip": "Shift를 누른 채 두 손가락으로 스크롤하면 반대 방향으로 회전합니다",
"ui.reverse_vertical_pan_direction": "수직 이동 방향 반전",
"ui.reverse_vertical_pan_tip": "두 손가락 수직 스크롤이 반대 방향으로 이동합니다",
"ui.reverse_zoom_direction": "확대/축소 방향 반전",
@@ -3554,7 +3018,6 @@
"ui.select": "선택",
"ui.selectOther": "기타 선택…",
"ui.selectTangentChain": "접선 체인 선택",
"ui.select_all": "모두 선택",
"ui.selection": "선택",
"ui.selection_modifiers": "선택 보조 키",
"ui.selection_shift_add_only": "Shift+클릭은 추가만 함",
@@ -3587,11 +3050,7 @@
"ui.sketch": "스케치",
"ui.sketch_dimension": "스케치 치수",
"ui.sketch_grid": "스케치 격자",
"ui.sketch_intersect_geometry": "형상",
"ui.sketch_intersect_projection_link": "투영 링크",
"ui.sketch_intersect_selection_filter": "선택 필터",
"ui.sketch_modifiers": "스케치 보조 키",
"ui.sketch_project_geometry": "형상",
"ui.sketch_scale": "스케치 축척",
"ui.sketches": "스케치",
"ui.slice": "슬라이스",
@@ -3627,11 +3086,6 @@
"ui.symmetric": "대칭",
"ui.symmetry": "대칭",
"ui.system": "시스템",
"ui.tab_assemble": "조립",
"ui.tab_manage": "관리",
"ui.tab_sheet_metal": "판금",
"ui.tab_view": "보기",
"ui.tab_weldments": "용접 구조물",
"ui.tangent": "접선",
"ui.taper_angle": "테이퍼 각도",
"ui.tapped": "탭",
@@ -3647,7 +3101,6 @@
"ui.tip_angle": "선단 각도",
"ui.to_object": "객체까지",
"ui.tool_direction": "공구 방향",
"ui.toolbar_tabs_hidden": "모든 도구 모음 탭이 숨겨져 있습니다. +를 클릭하거나 여기를 마우스 오른쪽 버튼으로 클릭하여 표시하세요.",
"ui.top": "상면",
"ui.top_diameter": "윗면 지름",
"ui.top_radius": "윗면 반지름",
@@ -3681,14 +3134,6 @@
"ui.view_angles_roll": "롤",
"ui.view_angles_yaw": "요",
"ui.view_centre": "뷰 중심",
"ui.viewport_status_clear": "{name} 끄기",
"ui.viewport_status_clear_hint": "{name} 끄기 · Esc",
"ui.viewport_status_edges": "모서리 {count}개",
"ui.viewport_status_from": "{direction} 방향에서",
"ui.viewport_status_key": "{name} 범례 표시",
"ui.viewport_status_minimum_radius": "최소 반지름",
"ui.viewport_status_pairs": "{count}쌍",
"ui.viewport_status_stripes": "줄무늬 {count}개",
"ui.viewport_theme_follow": "테마 따르기",
"ui.visual_shaded_hidden_edges": "음영 처리 및 숨겨진 모서리",
"ui.visual_shaded_with_edges": "음영 처리 및 모서리",
@@ -3741,9 +3186,6 @@
"update.prefs_label": "업데이트",
"update.prefs_note": "SolidCraft {version} ({kind})입니다. 확인 시 GitHub에 최신 릴리스만 요청하며 다른 정보는 보내지 않습니다.",
"update.prefs_web": "페이지를 새로고침하면 최신 웹 앱을 가져옵니다. 네트워크를 사용할 수 없거나 업데이트 다운로드가 제한 시간 안에 완료되지 않으면 저장된 버전이 열립니다. 진행 중인 다운로드는 다음 새로고침을 위해 계속됩니다.",
"update.refresh_checking": "최신 릴리스 확인 중…",
"update.refresh_fallback": "새 릴리스를 확인하지 못했습니다. 이전에 찾은 {version}(으)로 업데이트합니다.",
"update.refresh_selected": "{version}(으)로 업데이트 중.",
"update.release_page": "릴리스 페이지 열기",
"update.restart": "지금 다시 시작",
"update.restart_later": "나중에",
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+1 -785
View File
File diff suppressed because it is too large Load Diff
@@ -1,33 +0,0 @@
{
"bs": {
"browser.calibrate_click_a": "Kliknite sliku da zadate tačku A ili upišite njene koordinate.",
"browser.calibrate_click_b": "Kliknite sliku da zadate tačku B ili upišite njene koordinate.",
"help.sketch.construction_line": "Napravite beskonačnu pomoćnu pravu kroz dvije tačke. Koristite je da rasporedite skicu bez razdvajanja profila.",
"help.sketch.construction_line.angle": "Napravite beskonačnu pomoćnu pravu pod uglom od ose X skice. Izaberite tačku i upišite ugao ili izaberite smjer.",
"help.sketch.construction_line.bisector": "Izaberite dvije prave linije skice koje se sijeku, pa jednu od dvije simetrale ugla. Rezultat prati izvorne linije.",
"help.sketch.construction_line.horizontal": "Napravite beskonačnu horizontalnu pomoćnu pravu kroz tačku. Njeno ograničenje horizontalnosti ostaje na snazi pri kasnijim izmjenama.",
"help.sketch.construction_line.parallel": "Izaberite pravu liniju skice, pa postavite paralelnu beskonačnu pomoćnu pravu. Desnim klikom izaberite drugu referencu.",
"help.sketch.construction_line.perpendicular": "Izaberite pravu liniju skice, pa postavite okomitu beskonačnu pomoćnu pravu. Desnim klikom izaberite drugu referencu.",
"help.sketch.construction_line.tangent_at": "Napravite tangentu u tački na krugu ili kružnom luku, ili u krajnjoj tački otvorenog splajna ili konike. Izaberite krivu, pa tačku dodira.",
"help.sketch.construction_line.tangent_external": "Izaberite krug ili kružni luk, pa vanjsku tačku i rješenje tangente. Pregledi prikazuju samo dodirne tačke na nacrtanom luku.",
"help.sketch.construction_line.tangent_two": "Izaberite dva kruga ili kružna luka, pa u pregledu izaberite zajedničku tangentu. Dodirne tačke moraju ležati na nacrtanim krivama.",
"help.sketch.construction_line.vertical": "Napravite beskonačnu vertikalnu pomoćnu pravu kroz tačku. Njeno ograničenje vertikalnosti ostaje na snazi pri kasnijim izmjenama.",
"prefs.persistent_ribbon_pressed": "Istakni aktivne komande na traci",
"prefs.persistent_ribbon_pressed_help": "Ističe komande na traci dok su njihovi efekti uključeni. Isključite da biste zadržali prethodni neutralni izgled i pomoć za komande.",
"prefs.sketch_construction_lines": "Prošireni alati za pomoćne prave",
"prefs.sketch_open_look_at": "Okreni kameru prema skici kad se otvori",
"prefs.sketch_open_look_at_note": "Isključeno: kad napravite ili uredite skicu, prikaz ostaje onakav kakav jest. Pogledaj okreće prikaz prema skici kad to želite.",
"recovery.discard_all": "Odbaci sve",
"recovery.discard_all_detail": "Ovo se ne može poništiti.",
"recovery.discard_all_title": "Odbaciti automatska čuvanja ({count})?",
"recovery.discard_all_title_one": "Odbaciti 1 automatsko čuvanje?",
"ui.construction.angle_hint": "Pomoćna prava: kliknite tačku, pa upišite ugao ili izaberite smjer",
"ui.construction.bisector_hint": "Simetrala: izaberite dvije prave linije koje se sijeku, pa željeno rješenje",
"ui.construction.common_hint": "Zajednička tangenta: izaberite dva kruga ili luka, pa željeno rješenje",
"ui.construction.contact_hint": "Tangenta: izaberite krug/luk ili otvoreni splajn/koniku, pa tačku dodira (krive slobodnog oblika: krajnje tačke)",
"ui.construction.external_hint": "Tangenta: izaberite krug ili luk, vanjsku tačku, pa željeno rješenje",
"ui.construction.free_hint": "Pomoćna prava: kliknite dvije tačke; desnim klikom počnite ispočetka",
"ui.construction.point_hint": "Pomoćna prava: kliknite tačku kroz koju prolazi",
"ui.construction.reference_hint": "Pomoćna prava: izaberite pravu liniju, pa tačku; desnim klikom promijenite referencu"
}
}
@@ -1,33 +0,0 @@
{
"gl": {
"browser.calibrate_click_a": "Fai clic na imaxe para o punto A, ou escribe as súas coordenadas.",
"browser.calibrate_click_b": "Fai clic na imaxe para o punto B, ou escribe as súas coordenadas.",
"help.sketch.construction_line": "Crea unha recta de construción infinita por dous puntos. Úsaa para organizar un bosquexo sen dividir os perfís.",
"help.sketch.construction_line.angle": "Crea unha recta de construción infinita cun ángulo respecto do eixe X do bosquexo. Escolle o punto e escribe o ángulo, ou escolle a súa dirección.",
"help.sketch.construction_line.bisector": "Escolle dúas rectas do bosquexo que se crucen e despois unha das dúas bisectrices. O resultado segue as súas rectas de orixe.",
"help.sketch.construction_line.horizontal": "Crea unha recta de construción horizontal infinita por un punto. A súa restrición horizontal mantense nas edicións posteriores.",
"help.sketch.construction_line.parallel": "Escolle unha recta do bosquexo e despois coloca unha recta de construción infinita paralela. Fai clic co botón dereito para escoller outra referencia.",
"help.sketch.construction_line.perpendicular": "Escolle unha recta do bosquexo e despois coloca unha recta de construción infinita perpendicular. Fai clic co botón dereito para escoller outra referencia.",
"help.sketch.construction_line.tangent_at": "Crea unha tanxente nun punto dun círculo ou dun arco circular, ou no extremo dunha spline ou dunha cónica abertas. Escolle a curva e despois o seu punto de tanxencia.",
"help.sketch.construction_line.tangent_external": "Escolle un círculo ou un arco circular e despois un punto exterior e unha solución de tanxente. As vistas previas só mostran os puntos de tanxencia sobre o arco debuxado.",
"help.sketch.construction_line.tangent_two": "Escolle dous círculos ou arcos circulares e despois unha tanxente común na vista previa. Os puntos de tanxencia deben estar sobre as curvas debuxadas.",
"help.sketch.construction_line.vertical": "Crea unha recta de construción vertical infinita por un punto. A súa restrición vertical mantense nas edicións posteriores.",
"prefs.persistent_ribbon_pressed": "Resaltar as ordes activas da cinta",
"prefs.persistent_ribbon_pressed_help": "Resalta as ordes da cinta mentres os seus efectos están activados. Desactívao para manter o aspecto neutro e a axuda das ordes anteriores.",
"prefs.sketch_construction_lines": "Ferramentas ampliadas de rectas de construción",
"prefs.sketch_open_look_at": "Xirar para mirar cara ao bosquexo cando se abre",
"prefs.sketch_open_look_at_note": "Desactivado: crear ou editar un bosquexo deixa a vista tal e como está. Mirar cara a orienta a vista cara ao bosquexo cando o queres.",
"recovery.discard_all": "Descartar todo",
"recovery.discard_all_detail": "Esta acción non se pode desfacer.",
"recovery.discard_all_title": "Descartar {count} gardados automáticos?",
"recovery.discard_all_title_one": "Descartar 1 gardado automático?",
"ui.construction.angle_hint": "Recta de construción: fai clic nun punto e despois escribe un ángulo ou escolle unha dirección",
"ui.construction.bisector_hint": "Bisectriz: escolle dúas rectas que se crucen e despois a solución desexada",
"ui.construction.common_hint": "Tanxente común: escolle dous círculos/arcos e despois a solución desexada",
"ui.construction.contact_hint": "Tanxente: escolle un círculo/arco ou unha spline/cónica aberta e despois o punto de tanxencia (curvas de forma libre: extremos)",
"ui.construction.external_hint": "Tanxente: escolle un círculo ou arco, un punto exterior e despois a solución desexada",
"ui.construction.free_hint": "Recta de construción: fai clic en dous puntos; clic dereito para reiniciar",
"ui.construction.point_hint": "Recta de construción: fai clic no punto polo que debe pasar",
"ui.construction.reference_hint": "Recta de construción: escolle unha recta e despois un punto; clic dereito para cambiar a referencia"
}
}
@@ -1,33 +0,0 @@
{
"id": {
"browser.calibrate_click_a": "Klik gambar untuk Titik A, atau ketik koordinatnya.",
"browser.calibrate_click_b": "Klik gambar untuk Titik B, atau ketik koordinatnya.",
"help.sketch.construction_line": "Buat garis bantu tak hingga melalui dua titik. Gunakan untuk menata sketsa tanpa memecah profil.",
"help.sketch.construction_line.angle": "Buat garis bantu tak hingga dengan sudut terhadap sumbu X sketsa. Pilih titiknya dan ketik sudutnya, atau pilih arahnya.",
"help.sketch.construction_line.bisector": "Pilih dua garis sketsa lurus yang berpotongan, lalu pilih salah satu garis bagi sudut. Hasilnya mengikuti garis sumbernya.",
"help.sketch.construction_line.horizontal": "Buat garis bantu horizontal tak hingga melalui sebuah titik. Batasan horizontalnya tetap berlaku pada pengeditan berikutnya.",
"help.sketch.construction_line.parallel": "Pilih sebuah garis sketsa lurus, lalu tempatkan garis bantu tak hingga yang sejajar. Klik kanan untuk memilih referensi lain.",
"help.sketch.construction_line.perpendicular": "Pilih sebuah garis sketsa lurus, lalu tempatkan garis bantu tak hingga yang tegak lurus. Klik kanan untuk memilih referensi lain.",
"help.sketch.construction_line.tangent_at": "Buat garis singgung pada sebuah titik di lingkaran atau busur lingkaran, atau pada titik ujung spline atau kurva konik yang terbuka. Pilih kurvanya, lalu titik singgungnya.",
"help.sketch.construction_line.tangent_external": "Pilih lingkaran atau busur lingkaran, lalu sebuah titik luar dan satu solusi garis singgung. Pratinjau hanya menampilkan titik singgung pada busur yang digambar.",
"help.sketch.construction_line.tangent_two": "Pilih dua lingkaran atau busur lingkaran, lalu pilih garis singgung persekutuan di pratinjau. Titik singgung harus berada pada kurva yang digambar.",
"help.sketch.construction_line.vertical": "Buat garis bantu vertikal tak hingga melalui sebuah titik. Batasan vertikalnya tetap berlaku pada pengeditan berikutnya.",
"prefs.persistent_ribbon_pressed": "Sorot perintah ribbon yang aktif",
"prefs.persistent_ribbon_pressed_help": "Sorot perintah ribbon selama efeknya aktif. Matikan untuk mempertahankan tampilan netral dan bantuan perintah sebelumnya.",
"prefs.sketch_construction_lines": "Alat garis bantu lanjutan",
"prefs.sketch_open_look_at": "Putar untuk menghadap sketsa saat dibuka",
"prefs.sketch_open_look_at_note": "Mati: membuat atau mengedit sketsa membiarkan tampilan apa adanya. Look At menghadapkan tampilan ke sketsa saat Anda menginginkannya.",
"recovery.discard_all": "Buang semua",
"recovery.discard_all_detail": "Aksi ini tidak dapat diurungkan.",
"recovery.discard_all_title": "Buang {count} simpan otomatis?",
"recovery.discard_all_title_one": "Buang 1 simpan otomatis?",
"ui.construction.angle_hint": "Garis bantu: klik sebuah titik, lalu ketik sudut atau pilih arah",
"ui.construction.bisector_hint": "Garis bagi sudut: pilih dua garis lurus yang berpotongan, lalu solusi yang diinginkan",
"ui.construction.common_hint": "Garis singgung persekutuan: pilih dua lingkaran/busur, lalu solusi yang diinginkan",
"ui.construction.contact_hint": "Garis singgung: pilih lingkaran/busur atau spline/kurva konik terbuka, lalu titik singgung (kurva bentuk bebas: titik ujung)",
"ui.construction.external_hint": "Garis singgung: pilih lingkaran atau busur, sebuah titik luar, lalu solusi yang diinginkan",
"ui.construction.free_hint": "Garis bantu: klik dua titik; klik kanan untuk mengulang",
"ui.construction.point_hint": "Garis bantu: klik titik yang akan dilalui",
"ui.construction.reference_hint": "Garis bantu: pilih garis lurus, lalu sebuah titik; klik kanan untuk mengganti referensi"
}
}
-33
View File
@@ -1,33 +0,0 @@
{
"ms": {
"browser.calibrate_click_a": "Klik imej untuk Titik A, atau taip koordinatnya.",
"browser.calibrate_click_b": "Klik imej untuk Titik B, atau taip koordinatnya.",
"help.sketch.construction_line": "Cipta garis binaan tak terhingga melalui dua titik. Gunakannya untuk menyusun lakaran tanpa memisahkan profil.",
"help.sketch.construction_line.angle": "Cipta garis binaan tak terhingga pada sudut daripada paksi X lakaran. Pilih titik dan taip sudutnya, atau pilih arahnya.",
"help.sketch.construction_line.bisector": "Pilih dua garis lakaran lurus yang bersilang, kemudian pilih salah satu pembahagi dua sudut. Hasilnya mengikut garis sumbernya.",
"help.sketch.construction_line.horizontal": "Cipta garis binaan mendatar tak terhingga melalui satu titik. Kekangan mendatarnya kekal apabila disunting kemudian.",
"help.sketch.construction_line.parallel": "Pilih garis lakaran lurus, kemudian letakkan garis binaan tak terhingga yang selari. Klik kanan untuk memilih rujukan lain.",
"help.sketch.construction_line.perpendicular": "Pilih garis lakaran lurus, kemudian letakkan garis binaan tak terhingga yang serenjang. Klik kanan untuk memilih rujukan lain.",
"help.sketch.construction_line.tangent_at": "Cipta tangen pada satu titik pada bulatan atau lengkok bulat, atau pada titik hujung splin atau lengkung kon yang terbuka. Pilih lengkung itu, kemudian titik sentuhnya.",
"help.sketch.construction_line.tangent_external": "Pilih bulatan atau lengkok bulat, kemudian satu titik luar dan satu penyelesaian tangen. Pratonton hanya menunjukkan titik sentuh pada lengkok yang dilukis.",
"help.sketch.construction_line.tangent_two": "Pilih dua bulatan atau lengkok bulat, kemudian pilih tangen sepunya dalam pratonton. Titik sentuh mesti terletak pada lengkung yang dilukis.",
"help.sketch.construction_line.vertical": "Cipta garis binaan menegak tak terhingga melalui satu titik. Kekangan menegaknya kekal apabila disunting kemudian.",
"prefs.persistent_ribbon_pressed": "Serlahkan arahan reben yang aktif",
"prefs.persistent_ribbon_pressed_help": "Serlahkan arahan reben selagi kesannya dihidupkan. Matikan untuk mengekalkan rupa neutral dan bantuan arahan yang terdahulu.",
"prefs.sketch_construction_lines": "Alat garis binaan lanjutan",
"prefs.sketch_open_look_at": "Putar menghadap lakaran apabila dibuka",
"prefs.sketch_open_look_at_note": "Mati: mencipta atau menyunting lakaran membiarkan pandangan seperti sedia ada. Pandang Tepat menghadapkan pandangan ke lakaran apabila anda mahu.",
"recovery.discard_all": "Buang semua",
"recovery.discard_all_detail": "Tindakan ini tidak boleh dibuat asal.",
"recovery.discard_all_title": "Buang {count} simpanan automatik?",
"recovery.discard_all_title_one": "Buang 1 simpanan automatik?",
"ui.construction.angle_hint": "Garis binaan: klik satu titik, kemudian taip sudut atau pilih arah",
"ui.construction.bisector_hint": "Pembahagi dua sudut: pilih dua garis lurus yang bersilang, kemudian penyelesaian yang dikehendaki",
"ui.construction.common_hint": "Tangen sepunya: pilih dua bulatan/lengkok, kemudian penyelesaian yang dikehendaki",
"ui.construction.contact_hint": "Tangen: pilih bulatan/lengkok atau splin/lengkung kon terbuka, kemudian titik sentuh (lengkung bentuk bebas: titik hujung)",
"ui.construction.external_hint": "Tangen: pilih bulatan atau lengkok, satu titik luar, kemudian penyelesaian yang dikehendaki",
"ui.construction.free_hint": "Garis binaan: klik dua titik; klik kanan untuk mula semula",
"ui.construction.point_hint": "Garis binaan: klik titik yang akan dilalui",
"ui.construction.reference_hint": "Garis binaan: pilih garis lurus, kemudian satu titik; klik kanan untuk menukar rujukan"
}
}
@@ -1,33 +0,0 @@
{
"nb": {
"browser.calibrate_click_a": "Klikk på bildet for punkt A, eller skriv inn koordinatene.",
"browser.calibrate_click_b": "Klikk på bildet for punkt B, eller skriv inn koordinatene.",
"help.sketch.construction_line": "Opprett en uendelig hjelpelinje gjennom to punkter. Bruk den til å legge opp en skisse uten å dele opp profilene.",
"help.sketch.construction_line.angle": "Opprett en uendelig hjelpelinje i en vinkel fra skissens X-akse. Velg punktet og skriv inn vinkelen, eller velg retningen.",
"help.sketch.construction_line.bisector": "Velg to rette skisselinjer som krysser hverandre, og velg deretter en av vinkelhalveringslinjene. Resultatet følger kildelinjene sine.",
"help.sketch.construction_line.horizontal": "Opprett en uendelig vannrett hjelpelinje gjennom et punkt. Den vannrette bindingen følger med ved senere endringer.",
"help.sketch.construction_line.parallel": "Velg en rett skisselinje, og plasser deretter en parallell uendelig hjelpelinje. Høyreklikk for å velge en annen referanse.",
"help.sketch.construction_line.perpendicular": "Velg en rett skisselinje, og plasser deretter en vinkelrett uendelig hjelpelinje. Høyreklikk for å velge en annen referanse.",
"help.sketch.construction_line.tangent_at": "Opprett en tangent i et punkt på en sirkel eller sirkelbue, eller i endepunktet på en åpen spline eller kjeglesnittkurve. Velg kurven, og deretter berøringspunktet.",
"help.sketch.construction_line.tangent_external": "Velg en sirkel eller sirkelbue, deretter et eksternt punkt og en tangentløsning. Forhåndsvisningene viser bare berøringspunkter på den tegnede buen.",
"help.sketch.construction_line.tangent_two": "Velg to sirkler eller sirkelbuer, og velg deretter en felles tangent i forhåndsvisningen. Berøringspunktene må ligge på de tegnede kurvene.",
"help.sketch.construction_line.vertical": "Opprett en uendelig loddrett hjelpelinje gjennom et punkt. Den loddrette bindingen følger med ved senere endringer.",
"prefs.persistent_ribbon_pressed": "Fremhev aktive kommandoer på båndet",
"prefs.persistent_ribbon_pressed_help": "Fremhev kommandoer på båndet mens effektene deres er slått på. Slå av for å beholde det forrige nøytrale utseendet og den forrige kommandohjelpen.",
"prefs.sketch_construction_lines": "Utvidede hjelpelinjeverktøy",
"prefs.sketch_open_look_at": "Orienter mot skissen når den åpnes",
"prefs.sketch_open_look_at_note": "Av: å opprette eller redigere en skisse lar visningen stå som den er. Orienter mot vender visningen mot skissen når du vil.",
"recovery.discard_all": "Forkast alle",
"recovery.discard_all_detail": "Dette kan ikke angres.",
"recovery.discard_all_title": "Forkast {count} automatiske lagringer?",
"recovery.discard_all_title_one": "Forkast 1 automatisk lagring?",
"ui.construction.angle_hint": "Hjelpelinje: klikk på et punkt, og skriv deretter inn en vinkel eller velg en retning",
"ui.construction.bisector_hint": "Vinkelhalveringslinje: velg to rette linjer som krysser hverandre, og deretter ønsket løsning",
"ui.construction.common_hint": "Felles tangent: velg to sirkler/buer, og deretter ønsket løsning",
"ui.construction.contact_hint": "Tangent: velg en sirkel/bue eller åpen spline/kjeglesnittkurve, og deretter berøringspunktet (frie kurver: endepunkter)",
"ui.construction.external_hint": "Tangent: velg en sirkel eller bue, et eksternt punkt, og deretter ønsket løsning",
"ui.construction.free_hint": "Hjelpelinje: klikk på to punkter; høyreklikk for å starte på nytt",
"ui.construction.point_hint": "Hjelpelinje: klikk på punktet linjen skal gå gjennom",
"ui.construction.reference_hint": "Hjelpelinje: velg en rett linje, og deretter et punkt; høyreklikk for å bytte referanse"
}
}
@@ -1,33 +0,0 @@
{
"zh-TW": {
"browser.calibrate_click_a": "按一下影像以指定點 A,或輸入其座標。",
"browser.calibrate_click_b": "按一下影像以指定點 B,或輸入其座標。",
"help.sketch.construction_line": "建立通過兩點的無限長建構直線。可用來規劃草圖佈局,而不會分割輪廓。",
"help.sketch.construction_line.angle": "建立與草圖 X 軸夾指定角度的無限長建構直線。請選取點並輸入角度,或選取其方向。",
"help.sketch.construction_line.bisector": "選取兩條相交的草圖直線,再選擇其中一條角平分線。結果會跟隨其來源直線。",
"help.sketch.construction_line.horizontal": "建立通過某一點的水平無限長建構直線。其水平拘束會在後續編輯中持續維持。",
"help.sketch.construction_line.parallel": "選取一條草圖直線,再放置與其平行的無限長建構直線。按右鍵可選擇其他參考。",
"help.sketch.construction_line.perpendicular": "選取一條草圖直線,再放置與其垂直的無限長建構直線。按右鍵可選擇其他參考。",
"help.sketch.construction_line.tangent_at": "在圓或圓弧上的某一點,或在開放雲形線或圓錐曲線的端點建立切線。請先選取曲線,再選取其切點。",
"help.sketch.construction_line.tangent_external": "選取圓或圓弧,再選取外部點與一個切線解。預覽只會顯示位於所繪圓弧上的切點。",
"help.sketch.construction_line.tangent_two": "選取兩個圓或圓弧,再於預覽中選擇一條公切線。切點必須位於所繪曲線上。",
"help.sketch.construction_line.vertical": "建立通過某一點的鉛直無限長建構直線。其鉛直拘束會在後續編輯中持續維持。",
"prefs.persistent_ribbon_pressed": "醒目顯示作用中的功能區命令",
"prefs.persistent_ribbon_pressed_help": "在功能區命令的效果開啟期間醒目顯示這些命令。關閉可維持先前的中性外觀與命令說明。",
"prefs.sketch_construction_lines": "延伸建構直線工具",
"prefs.sketch_open_look_at": "開啟草圖時轉向正對草圖",
"prefs.sketch_open_look_at_note": "關閉:建立或編輯草圖時維持目前的檢視。需要時可用「注視」正對草圖。",
"recovery.discard_all": "全部捨棄",
"recovery.discard_all_detail": "此操作無法復原。",
"recovery.discard_all_title": "捨棄 {count} 個自動儲存檔?",
"recovery.discard_all_title_one": "捨棄 1 個自動儲存檔?",
"ui.construction.angle_hint": "建構直線:按一下一點,再輸入角度或選取方向",
"ui.construction.bisector_hint": "角平分線:選取兩條相交的直線,再選取所需的解",
"ui.construction.common_hint": "公切線:選取兩個圓/圓弧,再選取所需的解",
"ui.construction.contact_hint": "切線:選取圓/圓弧或開放雲形線/圓錐曲線,再選取切點(自由曲線:端點)",
"ui.construction.external_hint": "切線:選取圓或圓弧、一個外部點,再選取所需的解",
"ui.construction.free_hint": "建構直線:按一下兩點;按右鍵可重新開始",
"ui.construction.point_hint": "建構直線:按一下要通過的點",
"ui.construction.reference_hint": "建構直線:選取一條直線,再選取一點;按右鍵可變更參考"
}
}
@@ -1,33 +0,0 @@
{
"tr": {
"browser.calibrate_click_a": "A Noktası için görüntüye tıklayın veya koordinatlarını yazın.",
"browser.calibrate_click_b": "B Noktası için görüntüye tıklayın veya koordinatlarını yazın.",
"help.sketch.construction_line": "İki noktadan geçen sonsuz bir yardımcı doğru oluşturun. Profilleri bölmeden bir eskizi kurgulamak için kullanın.",
"help.sketch.construction_line.angle": "Eskizin X ekseninden belirli bir açıyla sonsuz bir yardımcı doğru oluşturun. Noktayı seçip açıyı yazın veya yönünü seçin.",
"help.sketch.construction_line.bisector": "Kesişen iki düz eskiz çizgisini seçin, ardından iki açıortaydan birini seçin. Sonuç, kaynak çizgilerini izler.",
"help.sketch.construction_line.horizontal": "Bir noktadan geçen sonsuz yatay bir yardımcı doğru oluşturun. Yatay kısıtlaması sonraki düzenlemelerde de korunur.",
"help.sketch.construction_line.parallel": "Düz bir eskiz çizgisi seçin, ardından paralel bir sonsuz yardımcı doğru yerleştirin. Başka bir referans seçmek için sağ tıklayın.",
"help.sketch.construction_line.perpendicular": "Düz bir eskiz çizgisi seçin, ardından dik bir sonsuz yardımcı doğru yerleştirin. Başka bir referans seçmek için sağ tıklayın.",
"help.sketch.construction_line.tangent_at": "Bir daire veya dairesel yay üzerindeki bir noktada ya da açık bir spline veya konik eğrinin uç noktasında teğet oluşturun. Önce eğriyi, sonra değme noktasını seçin.",
"help.sketch.construction_line.tangent_external": "Bir daire veya dairesel yay seçin, ardından bir dış nokta ve bir teğet çözümü seçin. Önizlemeler yalnızca çizilen yay üzerindeki değme noktalarını gösterir.",
"help.sketch.construction_line.tangent_two": "İki daire veya dairesel yay seçin, ardından önizlemede ortak bir teğet seçin. Değme noktaları çizilen eğriler üzerinde olmalıdır.",
"help.sketch.construction_line.vertical": "Bir noktadan geçen sonsuz dikey bir yardımcı doğru oluşturun. Dikey kısıtlaması sonraki düzenlemelerde de korunur.",
"prefs.persistent_ribbon_pressed": "Etkin şerit komutlarını vurgula",
"prefs.persistent_ribbon_pressed_help": "Şerit komutlarını, etkileri açık olduğu sürece vurgula. Önceki nötr görünümü ve komut yardımını korumak için kapatın.",
"prefs.sketch_construction_lines": "Genişletilmiş yardımcı doğru araçları",
"prefs.sketch_open_look_at": "Eskiz açıldığında görünümü ona doğru döndür",
"prefs.sketch_open_look_at_note": "Kapalı: eskiz oluşturmak veya düzenlemek görünümü olduğu gibi bırakır. Bak komutu, istediğinizde görünümü eskize çevirir.",
"recovery.discard_all": "Tümünü at",
"recovery.discard_all_detail": "Bu işlem geri alınamaz.",
"recovery.discard_all_title": "{count} otomatik kayıt atılsın mı?",
"recovery.discard_all_title_one": "1 otomatik kayıt atılsın mı?",
"ui.construction.angle_hint": "Yardımcı doğru: bir noktaya tıklayın, ardından bir açı yazın veya bir yön seçin",
"ui.construction.bisector_hint": "Açıortay: kesişen iki düz çizgiyi, ardından istenen çözümü seçin",
"ui.construction.common_hint": "Ortak teğet: iki daire/yay, ardından istenen çözümü seçin",
"ui.construction.contact_hint": "Teğet: bir daire/yay veya açık spline/konik eğri, ardından değme noktasını seçin (serbest biçimli eğriler: uç noktalar)",
"ui.construction.external_hint": "Teğet: bir daire veya yay, bir dış nokta, ardından istenen çözümü seçin",
"ui.construction.free_hint": "Yardımcı doğru: iki noktaya tıklayın; yeniden başlamak için sağ tıklayın",
"ui.construction.point_hint": "Yardımcı doğru: geçeceği noktaya tıklayın",
"ui.construction.reference_hint": "Yardımcı doğru: düz bir çizgi, ardından bir nokta seçin; referansı değiştirmek için sağ tıklayın"
}
}
-21
View File
@@ -709,16 +709,6 @@
"cmd.sheet_refold": "Zegnij ponownie",
"cmd.sheet_rules": "Lista reguł blach",
"cmd.sheet_unfold": "Rozegnij",
"cmd.sketch.construction_line": "Prosta konstrukcyjna",
"cmd.sketch.construction_line.angle": "Prosta konstrukcyjna pod kątem",
"cmd.sketch.construction_line.bisector": "Dwusieczna kąta",
"cmd.sketch.construction_line.horizontal": "Pozioma prosta konstrukcyjna",
"cmd.sketch.construction_line.parallel": "Równoległa prosta konstrukcyjna",
"cmd.sketch.construction_line.perpendicular": "Prostopadła prosta konstrukcyjna",
"cmd.sketch.construction_line.tangent_at": "Styczna w punkcie krzywej",
"cmd.sketch.construction_line.tangent_external": "Styczna przez punkt zewnętrzny",
"cmd.sketch.construction_line.tangent_two": "Wspólna styczna",
"cmd.sketch.construction_line.vertical": "Pionowa prosta konstrukcyjna",
"cmd.sketch_arc_center_point": "Łuk ze środka",
"cmd.sketch_arc_tangent": "Łuk styczny",
"cmd.sketch_arc_three_point": "Łuk przez 3 punkty",
@@ -1310,10 +1300,6 @@
"shortcut.pin": "Przypnij na górze pola S",
"shortcut.unpin": "Odepnij",
"sketch.degrees_of_freedom": "Stopnie swobody: {count}",
"sketch.dimension_added_driven": "Szkic już określa ten wymiar, więc dodano go jako wymiar sterowany (referencyjny)",
"sketch.dimension_applied": "Wymiar zastosowany",
"sketch.dimension_applied_defined": "Wymiar zastosowany; zdefiniowano parametr `{name}`",
"sketch.dimension_applied_renamed": "Wymiar zastosowany; parametr nazywa się teraz `{name}`",
"sketch.dof_left": "Pozostałe stopnie swobody: {count}",
"sketch.dof_left_one": "Pozostał {count} stopień swobody",
"sketch.draw_curves": "Rysuj jako {linetype}",
@@ -1749,7 +1735,6 @@
"ui.constant": "Stały",
"ui.constraints_conflict": "Konflikt wiązań",
"ui.construction": "Konstrukcyjne",
"ui.construction.ribbon_label": "Linie pom.",
"ui.context_menu": "Menu kontekstowe",
"ui.continuity_g0": "G0 załamanie",
"ui.continuity_g1": "G1 styczność",
@@ -2045,7 +2030,6 @@
"ui.pan_zoom_orbit": "Przesuwanie, powiększanie, obracanie",
"ui.parallel": "Równoległość",
"ui.parameters": "Parametry",
"ui.part_size_needs_a_part": "Zaznacz wstawioną część znormalizowaną (śrubę, nakrętkę, podkładkę lub kołek), aby zmienić jej rozmiar. Aby powiększyć lub pomniejszyć bryłę, użyj polecenia Skala.",
"ui.part_size_shared": "Przebudowuje część, zastępując wszystkie dodane elementy. Wszystkie wystąpienia tego komponentu zostaną zaktualizowane.",
"ui.paste": "Wklej",
"ui.path": "Ścieżka",
@@ -2129,7 +2113,6 @@
"ui.select": "Zaznacz",
"ui.selectOther": "Wybierz inny…",
"ui.selectTangentChain": "Zaznacz łańcuch styczny",
"ui.select_all": "Zaznacz wszystko",
"ui.selection": "Zaznaczenie",
"ui.selection_modifiers": "Modyfikatory zaznaczania",
"ui.selection_shift_add_only": "Shift+kliknięcie tylko dodaje",
@@ -2191,10 +2174,6 @@
"ui.symmetric": "Symetrycznie",
"ui.symmetry": "Symetria",
"ui.system": "Systemowy",
"ui.tab_assemble": "Złożenie",
"ui.tab_manage": "Zarządzanie",
"ui.tab_sheet_metal": "Blacha",
"ui.tab_view": "Widok",
"ui.tangent": "Styczność",
"ui.taper_angle": "Kąt pochylenia",
"ui.tapped": "Gwintowany",
-17
View File
@@ -815,16 +815,6 @@
"cmd.sheet_refold": "Redobrar",
"cmd.sheet_rules": "Listar regras de chapa metálica",
"cmd.sheet_unfold": "Desdobrar",
"cmd.sketch.construction_line": "Reta de construção",
"cmd.sketch.construction_line.angle": "Reta de construção em ângulo",
"cmd.sketch.construction_line.bisector": "Bissetriz",
"cmd.sketch.construction_line.horizontal": "Reta de construção horizontal",
"cmd.sketch.construction_line.parallel": "Reta de construção paralela",
"cmd.sketch.construction_line.perpendicular": "Reta de construção perpendicular",
"cmd.sketch.construction_line.tangent_at": "Tangente em um ponto da curva",
"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_arc_center_point": "Arco por ponto central",
"cmd.sketch_arc_tangent": "Arco tangente",
"cmd.sketch_arc_three_point": "Arco por 3 pontos",
@@ -1874,7 +1864,6 @@
"ui.constant": "Constante",
"ui.constraints_conflict": "Restrições em conflito",
"ui.construction": "Construção",
"ui.construction.ribbon_label": "Linhas aux.",
"ui.context_menu": "Menu de contexto",
"ui.continuity_g0": "G0 vinco",
"ui.continuity_g1": "G1 tangente",
@@ -2172,7 +2161,6 @@
"ui.pan_zoom_orbit": "Deslocar, zoom, orbitar",
"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.",
"ui.part_size_shared": "Reconstrói a peça, substituindo quaisquer recursos adicionados. Todas as ocorrências deste componente são atualizadas.",
"ui.paste": "Colar",
"ui.path": "Caminho",
@@ -2255,7 +2243,6 @@
"ui.select": "Selecionar",
"ui.selectOther": "Selecionar outro…",
"ui.selectTangentChain": "Selecionar cadeia tangente",
"ui.select_all": "Selecionar tudo",
"ui.selection": "Seleção",
"ui.selection_modifiers": "Modificadores de seleção",
"ui.selection_shift_add_only": "Shift+clique adiciona sem remover",
@@ -2317,10 +2304,6 @@
"ui.symmetric": "Simétrico",
"ui.symmetry": "Simetria",
"ui.system": "Sistema",
"ui.tab_assemble": "Montar",
"ui.tab_manage": "Gerenciar",
"ui.tab_sheet_metal": "Chapa Metálica",
"ui.tab_view": "Vista",
"ui.tangent": "Tangente",
"ui.taper_angle": "Ângulo de inclinação",
"ui.tapped": "Roscado",
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -7,7 +7,7 @@ pub const DEFAULT_MATERIAL: &str = "Default";
pub const DEFAULT_DENSITY: f64 = 1.29;
/// Physical materials: name and density (g/cm³).
pub const MATERIALS: &[(&str, f64)] = &[
pub const MATERIALS: [(&str, f64); 14] = [
(DEFAULT_MATERIAL, DEFAULT_DENSITY),
("Steel", 7.85),
("Stainless Steel", 8.0),
-43
View File
@@ -18,8 +18,6 @@ struct U {
depth: vec4<f32>, // x = 1: reversed depth (1 near, 0 far); y, z: the faces' push (`FACE_BIAS`)
tint: vec4<f32>, // xyz added to a whole hovered body's colour before lighting
sel: vec4<f32>, // xyz a whole selected body's colour before lighting
product_lights_meta: vec4<f32>, // explicit preview flag and bounded count
product_lights: array<vec4<f32>,84>, // position/kind, radiance, axis/cone, attenuation
};
fn reversed() -> bool {
@@ -473,36 +471,6 @@ fn shade(i: TOut) -> vec4<f32> {
return lit(i, 1.0);
}
fn product_light_unit(v: vec3<f32>) -> vec3<f32> {
let scale=max(max(abs(v.x),abs(v.y)),abs(v.z));
if scale == 0.0 { return vec3<f32>(0.0,0.0,1.0); }
return normalize(v/scale);
}
// Direction and incident radiance for an unshadowed analytic preview sample.
fn product_light_sample(k: u32, p: vec3<f32>) -> mat2x3<f32> {
let source=u.product_lights[k*4u];
let colour=u.product_lights[k*4u+1u];
let axis=u.product_lights[k*4u+2u];
let falloff=u.product_lights[k*4u+3u];
var direction=product_light_unit(source.xyz);
var weight=1.0;
if source.w > 0.5 {
let delta=source.xyz-p;
let distance=max(length(delta),falloff.y);
direction=product_light_unit(delta);
weight=falloff.x/max(distance*distance,0.000001);
if source.w == 2.0 {
let cosine=dot(product_light_unit(axis.xyz),-direction);
var cone=select(0.0,1.0,cosine>=colour.w);
if axis.w-colour.w>0.000001 {cone=smoothstep(colour.w,axis.w,cosine);}
weight *= cone;
}
if source.w == 3.0 {weight *= max(dot(product_light_unit(axis.xyz),-direction),0.0);}
}
return mat2x3<f32>(direction,colour.xyz*weight);
}
fn lit(i: TOut, visibility: f32) -> vec4<f32> {
return lit_color(i, visibility, i.c);
}
@@ -517,17 +485,6 @@ fn lit_color(i: TOut, visibility: f32, base: vec4<f32>) -> vec4<f32> {
let v = normalize(u.back.xyz);
var n = normalize(i.n);
if (dot(n, v) < 0.0) { n = -n; }
if u.product_lights_meta.x>0.0 {
var radiance=vec3<f32>(0.0);
for (var k=0u;k<min(u32(u.product_lights_meta.y),21u);k+=1u) {
if u.product_lights[k*4u].w == 4.0 {radiance+=to_linear(base.rgb)*u.product_lights[k*4u+1u].xyz/3.141592653589793;continue;}
let sample=product_light_sample(k,i.wp);
radiance+=to_linear(base.rgb)*sample[1]*(max(dot(n,sample[0]),0.0)/3.141592653589793);
}
let mapped=radiance/(vec3<f32>(1.0)+radiance);
let encoded=select(mapped*12.92,1.055*pow(mapped,vec3<f32>(1.0/2.4))-vec3<f32>(0.055),mapped>vec3<f32>(0.0031308));
return out_color(vec4<f32>(encoded,base.a));
}
let key = normalize(v * 0.8 + vec3<f32>(-0.3, 0.2, 0.6));
let diff = max(dot(n, key), 0.0);
let fill = max(dot(n, v), 0.0);
-12
View File
@@ -175,8 +175,6 @@ impl Tokens {
body: Color32::from_rgb(176, 186, 198),
body_edge: Color32::from_rgb(40, 44, 52),
manipulator: Color32::from_rgb(40, 110, 220),
joint_manipulator: Color32::from_rgb(235, 157, 0),
joint_axis: Color32::from_rgb(0, 95, 110),
preview_add: Color32::from_rgb(112, 160, 226),
preview_new: Color32::from_rgb(240, 225, 105),
preview_sketch: Color32::from_rgb(32, 190, 96),
@@ -195,8 +193,6 @@ impl Tokens {
sketch_halo: Color32::from_rgb(240, 243, 247),
sketch_point: Color32::BLACK,
sketch_locked: Color32::from_rgb(0, 140, 60),
// The error red (`error`).
sketch_conflict: Color32::from_rgb(214, 54, 54),
// Sketch dimensions in a plum of their own, apart from the blue and black curves for
// every colour vision mode (#7861).
dimension: Color32::from_rgb(130, 42, 110),
@@ -347,14 +343,12 @@ impl Tokens {
t.selected_bg = Color32::from_rgb(42, 70, 110);
t.construction_geom = icon_primary(crate::icon_svg::CONSTRUCTION_PRIMARY[1]);
t.error = Color32::from_rgb(240, 100, 96);
t.sketch_conflict = t.error;
t.warning = Color32::from_rgb(236, 170, 70);
t.icon = Color32::from_rgb(208, 214, 226);
t.timeline = Color32::from_rgb(33, 37, 45);
t.hover = Color32::from_rgb(54, 61, 74);
t.hover_edge_halo = Color32::from_rgb(203, 203, 203);
t.origin_point = Color32::from_rgb(214, 215, 218);
t.joint_axis = Color32::from_rgb(110, 240, 250);
t.viewport_top = Color32::from_rgb(46, 52, 64);
t.viewport_bottom = Color32::from_rgb(46, 52, 64);
t.grid = Color32::from_rgb(59, 65, 76);
@@ -419,9 +413,6 @@ impl Tokens {
}
t.construction_geom = icon_primary(crate::icon_svg::CONSTRUCTION_RED_GREEN[dark as usize]);
t.glyph_text = icon_primary(crate::icon_svg::CONSTRAINT_RED_GREEN[dark as usize]);
// A deeper red keeps conflicting sketch geometry (#7244) apart from the orange
// construction and centerline lines and the crimson lost links for a red-green loss.
t.sketch_conflict = Color32::from_rgb(195, 35, 30);
t.surface_accent = if dark { Color32::from_rgb(200, 135, 55) } else { Color32::from_rgb(164, 80, 0) };
t.mesh_accent = if dark { Color32::from_rgb(190, 175, 70) } else { Color32::from_rgb(130, 103, 0) };
t.form_accent = if dark { Color32::from_rgb(165, 135, 220) } else { Color32::from_rgb(115, 73, 205) };
@@ -452,9 +443,6 @@ impl Tokens {
t.preview_sketch = Color32::from_rgb(125, 180, 105);
t.glyph_text = icon_primary(crate::icon_svg::CONSTRAINT_BLUE_YELLOW[dark as usize]);
t.construction_geom = icon_primary(crate::icon_svg::CONSTRUCTION_BLUE_YELLOW[dark as usize]);
// Conflicting sketch geometry (#7244) apart from the lost links and the construction and
// centerline lines for a blue-yellow loss: darker on the light view, lighter on the dark.
t.sketch_conflict = if dark { Color32::from_rgb(255, 170, 160) } else { Color32::from_rgb(165, 15, 30) };
if dark {
t.sketch_locked = Color32::from_rgb(140, 225, 110);
t.box_crossing = Color32::from_rgb(240, 110, 170);
-5
View File
@@ -1,6 +1,4 @@
{
"order": 76,
"provenance": "Original black-and-white palette",
"base": "dark",
"colors": {
"accent": "#ffffff",
@@ -93,8 +91,6 @@
"icons.highlight": "#000000",
"icons.marker_halo": "#000000",
"interference": "#ffffff",
"joint_axis": "#ffffff",
"joint_manipulator": "#ffffff",
"logo": [
"#ffffff",
"#ffffff",
@@ -146,7 +142,6 @@
"sketch": "#ffffff",
"sketch_accent": "#ffffff",
"sketch_centerline": "#ffffff",
"sketch_conflict": "#ffffff",
"sketch_construction": "#ffffff",
"sketch_fixed": "#ffffff",
"sketch_halo": "#000000",
-5
View File
@@ -1,6 +1,4 @@
{
"order": 75,
"provenance": "Original black-and-white palette",
"base": "light",
"colors": {
"accent": "#000000",
@@ -93,8 +91,6 @@
"icons.highlight": "#ffffff",
"icons.marker_halo": "#ffffff",
"interference": "#000000",
"joint_axis": "#000000",
"joint_manipulator": "#000000",
"logo": [
"#000000",
"#000000",
@@ -146,7 +142,6 @@
"sketch": "#000000",
"sketch_accent": "#000000",
"sketch_centerline": "#000000",
"sketch_conflict": "#000000",
"sketch_construction": "#000000",
"sketch_fixed": "#000000",
"sketch_halo": "#ffffff",
-2
View File
@@ -1,6 +1,4 @@
{
"order": 220,
"provenance": "Maps the Okibi design system",
"base": "light",
"colors": {
"accent": "#c63a00",
+2 -4
View File
@@ -1,6 +1,4 @@
{
"order": 110,
"provenance": "Original SolidCraft theme",
"base": "dark",
"colors": {
"accent": "#ffbc48",
@@ -57,7 +55,7 @@
"error": "#fff0ca",
"field": "#100b04",
"form_accent": "#ca892b",
"form_dim": "#ad7a2c",
"form_dim": "#9b6922",
"form_error": "#fff0ca",
"form_error_fill": "#46300f",
"form_fill": "#e19e45",
@@ -180,7 +178,7 @@
"surface_soft": "#2a1e0b",
"tab_on_fill_dark": "#170d03",
"text": "#f3ca87",
"text_dim": "#ad7a2c",
"text_dim": "#9b6922",
"timeline": "#090602",
"timeline_item": "#1d1406",
"timeline_item_error": "#46300f",
-2
View File
@@ -1,6 +1,4 @@
{
"order": 120,
"provenance": "Original SolidCraft theme",
"base": "dark",
"colors": {
"accent": "#66ddff",
@@ -1,6 +1,4 @@
{
"order": 200,
"provenance": "Original SolidCraft mapping of Catppuccin (MIT palette)",
"base": "dark",
"colors": {
"accent": "#cba6f7",
-5
View File
@@ -1,6 +1,4 @@
{
"order": 250,
"provenance": "Original mapping of the IBM Color Graphics Adapter palette",
"base": "dark",
"colors": {
"accent": "#55ffff",
@@ -93,8 +91,6 @@
"icons.highlight": "#ffffff",
"icons.marker_halo": "#000000cc",
"interference": "#ff5555",
"joint_axis": "#aaaaaa",
"joint_manipulator": "#ffff55",
"logo": [
"#ffffff",
"#55ffff",
@@ -146,7 +142,6 @@
"sketch": "#55ffff",
"sketch_accent": "#ff55ff",
"sketch_centerline": "#ffff55",
"sketch_conflict": "#ff5555",
"sketch_construction": "#aaaaaa",
"sketch_fixed": "#ffffff",
"sketch_halo": "#000000",
-2
View File
@@ -1,6 +1,4 @@
{
"order": 240,
"provenance": "Original warm paper and charcoal palette",
"base": "dark",
"colors": {
"accent": "#e8845e",
-2
View File
@@ -1,6 +1,4 @@
{
"order": 230,
"provenance": "Original warm paper and charcoal palette",
"base": "light",
"colors": {
"accent": "#bf5634",
-2
View File
@@ -1,6 +1,4 @@
{
"order": 90,
"provenance": "Original SolidCraft theme",
"base": "light",
"colors": {
"accent": "#007aff",
-2
View File
@@ -1,6 +1,4 @@
{
"order": 180,
"provenance": "Original SolidCraft theme",
"base": "dark",
"colors": {
"accent": "#4aa3d8",
@@ -1,6 +1,4 @@
{
"order": 100,
"provenance": "Original SolidCraft theme",
"base": "dark",
"colors": {
"accent": "#4dff79",
@@ -1,6 +1,4 @@
{
"order": 20,
"provenance": "Original SolidCraft mapping of Gruvbox (MIT palette)",
"format": "solidcraft-theme/1",
"name": "Gruvbox Dark Hard",
"base": "dark",
@@ -1,6 +1,4 @@
{
"order": 30,
"provenance": "Original SolidCraft mapping of Gruvbox (MIT palette)",
"format": "solidcraft-theme/1",
"name": "Gruvbox Dark Soft",
"base": "dark",
@@ -113,7 +111,7 @@
"form_dim": "#bdae93",
"form_primary": "#83a598",
"form_error": "#fb4934",
"form_error_fill": "#5f2320",
"form_error_fill": "#702b28",
"form_success": "#b8bb26",
"form_success_fill": "#343a28",
"dialog_body": "#32302f",
@@ -1,6 +1,4 @@
{
"order": 10,
"provenance": "Original SolidCraft mapping of Gruvbox (MIT palette)",
"format": "solidcraft-theme/1",
"name": "Gruvbox Dark",
"base": "dark",
@@ -1,6 +1,4 @@
{
"order": 50,
"provenance": "Original SolidCraft mapping of Gruvbox (MIT palette)",
"format": "solidcraft-theme/1",
"name": "Gruvbox Light Hard",
"base": "light",
@@ -1,6 +1,4 @@
{
"order": 60,
"provenance": "Original SolidCraft mapping of Gruvbox (MIT palette)",
"format": "solidcraft-theme/1",
"name": "Gruvbox Light Soft",
"base": "light",

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