Compare commits

..

48 Commits

Author SHA1 Message Date
ff64367729 Rebased and refixed 2024-12-12 10:43:09 -05:00
c440bbc0fe Reuse electron window; difficult task 2024-12-12 10:19:26 -05:00
c2bb81ad1f fixup 2024-12-12 10:18:22 -05:00
82ec52b317 Port jess's projects.spec tests 2024-12-12 10:18:22 -05:00
f5a14166a1 Skip another code pane flake 2024-12-12 10:18:22 -05:00
6ac8cef180 One more fixme to settings 2024-12-12 10:18:22 -05:00
f0c8dbd5a2 Fixmes, fixmes everywhere 2024-12-12 10:18:22 -05:00
c20ce60c9a Hopefully help CI flake 2024-12-12 10:18:13 -05:00
f2b8e66952 Fix flake in double click editor 2024-12-12 10:18:13 -05:00
cdd73e952a Stop snapshots of exports (already test in e2e) 2024-12-12 10:18:13 -05:00
edbff28296 Try CI again 2024-12-12 10:18:13 -05:00
006fcd7490 Add an f-ton of shit because playwright doesnt want S P R E A D 2024-12-12 10:18:13 -05:00
4795de789d Remove to-electron script 2024-12-12 10:18:13 -05:00
1a04a4dcfb Correct all tsc errors 2024-12-12 10:18:12 -05:00
119cacf6a8 Fix a ton of syntax changes and deflake 2 more tests (pain) 2024-12-12 10:17:04 -05:00
12b00aca34 Pass segment-overlays (minor ache) and ability to switch to web if needed :) 2024-12-12 10:17:02 -05:00
5c56f94fbb Pass text-to-cad tests 2024-12-12 10:16:00 -05:00
329e60dda8 Pass app header tests 2024-12-12 10:16:00 -05:00
2844f4c4d6 Pass samples loading tests 2024-12-12 10:16:00 -05:00
0c48006793 Pass perspective-toggle, interesting note 2024-12-12 10:16:00 -05:00
534d1ddecc Pass another painful spec suite: testing-settings 2024-12-12 10:16:00 -05:00
4f5766d423 Merge main (tests changed x_x) and pass all constraints.spec tests (pain) 2024-12-12 10:15:58 -05:00
253556d6c7 Extreme time eaten by gizmo test fixes. All passing now. 2024-12-12 10:15:31 -05:00
10019a180d Pass camera-movement.spec tests 2024-12-12 10:07:03 -05:00
728314ccda Pass network and connection tests 2024-12-12 10:07:03 -05:00
7e229099a0 Pass regresion-tests.spec tests 2024-12-12 10:07:02 -05:00
da217b6c1a Pass projects, fought hard with filechooser 2024-12-12 10:06:36 -05:00
ff4e1a6c73 Pass machine.spec tests 2024-12-12 10:06:36 -05:00
a7c2548645 Painfully fix hardcoded coordinates in point-click.spec 2024-12-12 10:06:36 -05:00
ccfc592b62 Corrected a fixme in file-tree.spec! 2024-12-12 10:06:36 -05:00
b3cc43ae2f Pass onboarding tests 2024-12-12 10:06:36 -05:00
f061a9a15f Pass file tree tests 2024-12-12 10:06:36 -05:00
2b92f00d3c Pass editor tests 2024-12-12 10:06:35 -05:00
4b0823dbbf Pass desktop export tests 2024-12-12 10:05:22 -05:00
08a4016fda Pass debug pane tests 2024-12-12 10:05:22 -05:00
cb56fc7555 Completely fix code mirror text navigating for tests 2024-12-12 10:05:22 -05:00
d7d822cc11 fmt 2024-12-12 10:05:22 -05:00
8e450378c3 Pass command bar tests 2024-12-12 10:05:21 -05:00
fd39fcdb25 Pass can-sketch-on-all-planes... with ease 2024-12-12 10:04:26 -05:00
24011dd100 Pass various.spec.ts, by far the hardest one 2024-12-12 10:04:26 -05:00
a9b78fb2a4 Go back to fix up sketch-tests test 2024-12-12 10:04:25 -05:00
765e27c02b Pass testing-selections.spec.ts 2024-12-12 09:59:33 -05:00
05baf9884d Got testing-segment-overlays passing 2024-12-12 09:54:51 -05:00
1ced492deb Try out 4 workers 2024-12-12 09:50:04 -05:00
804124b07f Get sketch-tests.spec.ts passing in electron 2024-12-12 09:50:03 -05:00
b3112025b9 Add shebang to script and add macos-14-large as a target 2024-12-12 09:49:28 -05:00
898b4ed016 Pass the correct param to playwright-electron.sh 2024-12-12 09:49:28 -05:00
4b21a5b667 Move all tests over to electron 2024-12-12 09:49:27 -05:00
1431 changed files with 165597 additions and 401979 deletions

View File

@ -1,3 +1,3 @@
[codespell] [codespell]
ignore-words-list: crate,everytime,inout,co-ordinate,ot,nwo,atleast,ue,afterall,ser ignore-words-list: crate,everytime,inout,co-ordinate,ot,nwo,absolutey,atleast,ue,afterall
skip: **/target,node_modules,build,dist,./out,**/Cargo.lock,./docs/kcl/*.md,.yarn.lock,**/yarn.lock,./openapi/*.json,./packages/codemirror-lang-kcl/test/all.test.ts,tsconfig.tsbuildinfo skip: **/target,node_modules,build,**/Cargo.lock,./docs/kcl/*.md,.yarn.lock,**/yarn.lock,./openapi/*.json,./src/lib/machine-api.d.ts

View File

@ -2,8 +2,8 @@ NODE_ENV=development
DEV=true DEV=true
VITE_KC_API_WS_MODELING_URL=wss://api.dev.zoo.dev/ws/modeling/commands VITE_KC_API_WS_MODELING_URL=wss://api.dev.zoo.dev/ws/modeling/commands
VITE_KC_API_BASE_URL=https://api.dev.zoo.dev VITE_KC_API_BASE_URL=https://api.dev.zoo.dev
BASE_URL=https://api.dev.zoo.dev
VITE_KC_SITE_BASE_URL=https://dev.zoo.dev VITE_KC_SITE_BASE_URL=https://dev.zoo.dev
VITE_KC_SITE_APP_URL=https://app.dev.zoo.dev
VITE_KC_SKIP_AUTH=false VITE_KC_SKIP_AUTH=false
VITE_KC_CONNECTION_TIMEOUT_MS=5000 VITE_KC_CONNECTION_TIMEOUT_MS=5000
# ONLY add your token in .env.development.local if you want to skip auth, otherwise this token takes precedence! # ONLY add your token in .env.development.local if you want to skip auth, otherwise this token takes precedence!

View File

@ -1,8 +1,5 @@
NODE_ENV=production
DEV=false
VITE_KC_API_WS_MODELING_URL=wss://api.zoo.dev/ws/modeling/commands VITE_KC_API_WS_MODELING_URL=wss://api.zoo.dev/ws/modeling/commands
VITE_KC_API_BASE_URL=https://api.zoo.dev VITE_KC_API_BASE_URL=https://api.zoo.dev
VITE_KC_SITE_BASE_URL=https://zoo.dev VITE_KC_SITE_BASE_URL=https://zoo.dev
VITE_KC_SITE_APP_URL=https://app.zoo.dev
VITE_KC_SKIP_AUTH=false VITE_KC_SKIP_AUTH=false
VITE_KC_CONNECTION_TIMEOUT_MS=15000 VITE_KC_CONNECTION_TIMEOUT_MS=15000

View File

@ -5,39 +5,16 @@
}, },
"plugins": [ "plugins": [
"css-modules", "css-modules",
"jest",
"jsx-a11y",
"react",
"react-hooks",
"suggest-no-throw", "suggest-no-throw",
"testing-library",
"@typescript-eslint"
], ],
"extends": [ "extends": [
"plugin:css-modules/recommended", "react-app",
"plugin:jsx-a11y/recommended", "react-app/jest",
"plugin:react-hooks/recommended" "plugin:css-modules/recommended"
], ],
"rules": { "rules": {
"@typescript-eslint/no-floating-promises": "error", "@typescript-eslint/no-floating-promises": "error",
"@typescript-eslint/no-misused-promises": "error", "@typescript-eslint/no-misused-promises": "error",
"jsx-a11y/click-events-have-key-events": "off",
"jsx-a11y/no-autofocus": "off",
"jsx-a11y/no-noninteractive-element-interactions": "off",
"no-restricted-globals": [
"error",
{
"name": "isNaN",
"message": "Use Number.isNaN() instead."
},
],
"no-restricted-syntax": [
"error",
{
"selector": "CallExpression[callee.object.name='Array'][callee.property.name='isArray']",
"message": "Use isArray() in lib/utils.ts instead of Array.isArray()."
}
],
"semi": [ "semi": [
"error", "error",
"never" "never"
@ -48,9 +25,6 @@
"overrides": [ "overrides": [
{ {
"files": ["e2e/**/*.ts"], // Update the pattern based on your file structure "files": ["e2e/**/*.ts"], // Update the pattern based on your file structure
"extends": [
"plugin:testing-library/react"
],
"rules": { "rules": {
"suggest-no-throw/suggest-no-throw": "off", "suggest-no-throw/suggest-no-throw": "off",
"testing-library/prefer-screen-queries": "off", "testing-library/prefer-screen-queries": "off",
@ -59,9 +33,6 @@
}, },
{ {
"files": ["src/**/*.test.ts"], "files": ["src/**/*.test.ts"],
"extends": [
"plugin:testing-library/react"
],
"rules": { "rules": {
"suggest-no-throw/suggest-no-throw": "off", "suggest-no-throw/suggest-no-throw": "off",
} }

View File

@ -6,11 +6,11 @@ set -euo pipefail
if [[ ! -f "test-results/.last-run.json" ]]; then if [[ ! -f "test-results/.last-run.json" ]]; then
# if no last run artifact, than run plawright normally # if no last run artifact, than run plawright normally
echo "run playwright normally" echo "run playwright normally"
if [[ "$3" == *ubuntu* ]]; then if [[ "$3" == ubuntu-latest* ]]; then
xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- yarn test:playwright:electron:ubuntu -- --shard=$1/$2 || true xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- yarn test:playwright:electron:ubuntu -- --shard=$1/$2 || true
elif [[ "$3" == *windows* ]]; then elif [[ "$3" == windows-latest* ]]; then
yarn test:playwright:electron:windows -- --shard=$1/$2 || true yarn test:playwright:electron:windows -- --shard=$1/$2 || true
elif [[ "$3" == *macos* ]]; then elif [[ "$3" == macos-14* ]]; then
yarn test:playwright:electron:macos -- --shard=$1/$2 || true yarn test:playwright:electron:macos -- --shard=$1/$2 || true
else else
echo "Do not run playwright. Unable to detect os runtime." echo "Do not run playwright. Unable to detect os runtime."
@ -21,7 +21,7 @@ if [[ ! -f "test-results/.last-run.json" ]]; then
fi fi
retry=1 retry=1
max_retrys=5 max_retrys=4
# retry failed tests, doing our own retries because using inbuilt playwright retries causes connection issues # retry failed tests, doing our own retries because using inbuilt playwright retries causes connection issues
while [[ $retry -le $max_retrys ]]; do while [[ $retry -le $max_retrys ]]; do
@ -30,11 +30,11 @@ while [[ $retry -le $max_retrys ]]; do
if [[ $failed_tests -gt 0 ]]; then if [[ $failed_tests -gt 0 ]]; then
echo "retried=true" >>$GITHUB_OUTPUT echo "retried=true" >>$GITHUB_OUTPUT
echo "run playwright with last failed tests and retry $retry" echo "run playwright with last failed tests and retry $retry"
if [[ "$3" == *ubuntu* ]]; then if [[ "$3" == ubuntu-latest* ]]; then
xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- yarn test:playwright:electron:ubuntu -- --last-failed || true xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- yarn test:playwright:electron:ubuntu -- --last-failed || true
elif [[ "$3" == *windows* ]]; then elif [[ "$3" == windows-latest* ]]; then
yarn test:playwright:electron:windows -- --last-failed || true yarn test:playwright:electron:windows -- --last-failed || true
elif [[ "$3" == *macos* ]]; then elif [[ "$3" == macos-14* ]]; then
yarn test:playwright:electron:macos -- --last-failed || true yarn test:playwright:electron:macos -- --last-failed || true
else else
echo "Do not run playwright. Unable to detect os runtime." echo "Do not run playwright. Unable to detect os runtime."

View File

@ -5,37 +5,24 @@
version: 2 version: 2
updates: updates:
- package-ecosystem: 'npm' # See documentation for possible values - package-ecosystem: 'npm' # See documentation for possible values
directories: directory: '/' # Location of package manifests
- '/' schedule:
- '/packages/codemirror-lang-kcl/' interval: 'weekly'
- '/packages/codemirror-lsp-client/' reviewers:
schedule: - franknoirot
interval: weekly - irev-dev
day: monday - package-ecosystem: 'github-actions' # See documentation for possible values
reviewers: directory: '/' # Location of package manifests
- franknoirot schedule:
- irev-dev interval: 'weekly'
- package-ecosystem: 'github-actions' # See documentation for possible values reviewers:
directory: '/' # Location of package manifests - adamchalmers
schedule: - jessfraz
interval: weekly - package-ecosystem: 'cargo' # See documentation for possible values
day: monday directory: '/src/wasm-lib/' # Location of package manifests
reviewers: schedule:
- adamchalmers interval: 'weekly'
- jessfraz reviewers:
- package-ecosystem: 'cargo' # See documentation for possible values - adamchalmers
directory: '/src/wasm-lib/' # Location of package manifests - jessfraz
schedule:
interval: weekly
day: monday
reviewers:
- adamchalmers
- jessfraz
groups:
serde-dependencies:
patterns:
- "serde*"
wasm-bindgen-deps:
patterns:
- "wasm-bindgen*"

View File

@ -27,7 +27,7 @@ jobs:
# Upload the WASM bundle as an artifact # Upload the WASM bundle as an artifact
- uses: actions/upload-artifact@v4 - uses: actions/upload-artifact@v3
with: with:
name: wasm-bundle name: wasm-bundle
path: src/wasm-lib/pkg path: src/wasm-lib/pkg

View File

@ -126,13 +126,9 @@ jobs:
node-version-file: '.nvmrc' node-version-file: '.nvmrc'
cache: 'yarn' # Set this to npm, yarn or pnpm. cache: 'yarn' # Set this to npm, yarn or pnpm.
- name: yarn install - run: yarn install
# Windows is picky sometimes and fails on fetch. Step takes about ~30s
uses: nick-fields/retry@v3.0.0 - run: yarn tronb:vite
with:
timeout_minutes: 2
max_attempts: 3
command: yarn install
- name: Prepare certificate and variables (Windows only) - name: Prepare certificate and variables (Windows only)
if: ${{ (env.IS_RELEASE == 'true' || env.IS_NIGHTLY == 'true') && matrix.os == 'windows-2022' }} if: ${{ (env.IS_RELEASE == 'true' || env.IS_NIGHTLY == 'true') && matrix.os == 'windows-2022' }}
@ -163,8 +159,8 @@ jobs:
- name: Build the app (debug) - name: Build the app (debug)
if: ${{ env.IS_RELEASE == 'false' && env.IS_NIGHTLY == 'false' }} if: ${{ env.IS_RELEASE == 'false' && env.IS_NIGHTLY == 'false' }}
# electron-builder doesn't have a concept of release vs debug, # electron-builder doesn't have a concept of release vs debug,
# this is just not doing any codesign or release yml generation, and points to dev infra # this is just not doing any codesign or release yml generation
run: yarn tronb:package:dev run: yarn electron-builder --config
- name: Build the app (release) - name: Build the app (release)
if: ${{ env.IS_RELEASE == 'true' || env.IS_NIGHTLY == 'true' }} if: ${{ env.IS_RELEASE == 'true' || env.IS_NIGHTLY == 'true' }}
@ -177,13 +173,7 @@ jobs:
CSC_KEY_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} CSC_KEY_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
CSC_KEYCHAIN: ${{ secrets.APPLE_SIGNING_IDENTITY }} CSC_KEYCHAIN: ${{ secrets.APPLE_SIGNING_IDENTITY }}
WINDOWS_CERTIFICATE_THUMBPRINT: ${{ secrets.WINDOWS_CERTIFICATE_THUMBPRINT }} WINDOWS_CERTIFICATE_THUMBPRINT: ${{ secrets.WINDOWS_CERTIFICATE_THUMBPRINT }}
DEBUG: "electron-notarize*" run: yarn electron-builder --config --publish always
# TODO: Fix electron-notarize flakes. The logs above should help gather more data on failures
uses: nick-fields/retry@v3.0.0
with:
timeout_minutes: 10
max_attempts: 3
command: yarn tronb:package:prod
- name: List artifacts in out/ - name: List artifacts in out/
run: ls -R out run: ls -R out
@ -238,13 +228,7 @@ jobs:
CSC_KEY_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} CSC_KEY_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
CSC_KEYCHAIN: ${{ secrets.APPLE_SIGNING_IDENTITY }} CSC_KEYCHAIN: ${{ secrets.APPLE_SIGNING_IDENTITY }}
WINDOWS_CERTIFICATE_THUMBPRINT: ${{ secrets.WINDOWS_CERTIFICATE_THUMBPRINT }} WINDOWS_CERTIFICATE_THUMBPRINT: ${{ secrets.WINDOWS_CERTIFICATE_THUMBPRINT }}
DEBUG: "electron-notarize*" run: yarn electron-builder --config --publish always
# TODO: Fix electron-notarize flakes. The logs above should help gather more data on failures
uses: nick-fields/retry@v3.0.0
with:
timeout_minutes: 10
max_attempts: 3
command: yarn tronb:package:prod
- uses: actions/upload-artifact@v4 - uses: actions/upload-artifact@v4
if: ${{ env.IS_RELEASE == 'true' }} if: ${{ env.IS_RELEASE == 'true' }}
@ -388,19 +372,19 @@ jobs:
- name: Authenticate to Google Cloud - name: Authenticate to Google Cloud
if: ${{ env.IS_NIGHTLY == 'true' }} if: ${{ env.IS_NIGHTLY == 'true' }}
uses: 'google-github-actions/auth@v2.1.8' uses: 'google-github-actions/auth@v2.1.7'
with: with:
credentials_json: '${{ secrets.GOOGLE_CLOUD_DL_SA }}' credentials_json: '${{ secrets.GOOGLE_CLOUD_DL_SA }}'
- name: Set up Google Cloud SDK - name: Set up Google Cloud SDK
if: ${{ env.IS_NIGHTLY == 'true' }} if: ${{ env.IS_NIGHTLY == 'true' }}
uses: google-github-actions/setup-gcloud@v2.1.4 uses: google-github-actions/setup-gcloud@v2.1.2
with: with:
project_id: ${{ env.GOOGLE_CLOUD_PROJECT_ID }} project_id: ${{ env.GOOGLE_CLOUD_PROJECT_ID }}
- name: Upload nightly files to public bucket - name: Upload nightly files to public bucket
if: ${{ env.IS_NIGHTLY == 'true' }} if: ${{ env.IS_NIGHTLY == 'true' }}
uses: google-github-actions/upload-cloud-storage@v2.2.2 uses: google-github-actions/upload-cloud-storage@v2.2.1
with: with:
path: out path: out
glob: '*' glob: '*'

44
.github/workflows/cargo-bench.yml vendored Normal file
View File

@ -0,0 +1,44 @@
on:
push:
branches:
- main
paths:
- '**.rs'
- '**/Cargo.toml'
- '**/Cargo.lock'
- '**/rust-toolchain.toml'
- .github/workflows/cargo-bench.yml
pull_request:
paths:
- '**.rs'
- '**/Cargo.toml'
- '**/Cargo.lock'
- '**/rust-toolchain.toml'
- .github/workflows/cargo-bench.yml
workflow_dispatch:
permissions: read-all
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
name: cargo bench
jobs:
cargo-bench:
name: Benchmark with iai
runs-on: ubuntu-latest-8-cores
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- name: Install dependencies
run: |
cargo install cargo-criterion
sudo apt update
sudo apt install -y valgrind
- name: Rust Cache
uses: Swatinem/rust-cache@v2.6.1
- name: Benchmark kcl library
shell: bash
run: |-
cd src/wasm-lib/kcl; cargo bench --all-features -- iai
env:
KITTYCAD_API_TOKEN: ${{secrets.KITTYCAD_API_TOKEN}}

View File

@ -2,8 +2,28 @@ on:
push: push:
branches: branches:
- main - main
paths:
- 'src/wasm-lib/**.rs'
- 'src/wasm-lib/**.hbs'
- 'src/wasm-lib/**.gen'
- 'src/wasm-lib/**.snap'
- '**/Cargo.toml'
- '**/Cargo.lock'
- '**/rust-toolchain.toml'
- 'src/wasm-lib/**.kcl'
- .github/workflows/cargo-test.yml
pull_request: pull_request:
paths:
- 'src/wasm-lib/**.rs'
- 'src/wasm-lib/**.hbs'
- 'src/wasm-lib/**.gen'
- 'src/wasm-lib/**.snap'
- '**/Cargo.toml'
- '**/Cargo.lock'
- '**/rust-toolchain.toml'
- 'src/wasm-lib/**.kcl'
- .github/workflows/cargo-test.yml
workflow_dispatch: workflow_dispatch:
permissions: read-all permissions: read-all
concurrency: concurrency:
@ -51,7 +71,7 @@ jobs:
KITTYCAD_API_TOKEN: ${{secrets.KITTYCAD_API_TOKEN}} KITTYCAD_API_TOKEN: ${{secrets.KITTYCAD_API_TOKEN}}
RUST_MIN_STACK: 10485760000 RUST_MIN_STACK: 10485760000
- name: Upload to codecov.io - name: Upload to codecov.io
uses: codecov/codecov-action@v5 uses: codecov/codecov-action@v4
with: with:
token: ${{secrets.CODECOV_TOKEN}} token: ${{secrets.CODECOV_TOKEN}}
fail_ci_if_error: true fail_ci_if_error: true

View File

@ -1,32 +0,0 @@
name: CodeMirror Lang KCL
on:
pull_request:
push:
branches:
- main
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
yarn-unit-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'yarn'
- run: yarn install
working-directory: packages/codemirror-lang-kcl
- run: yarn tsc
working-directory: packages/codemirror-lang-kcl
- name: run unit tests
run: yarn test
working-directory: packages/codemirror-lang-kcl

View File

@ -1,145 +0,0 @@
name: E2E Snapshot Tests
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
permissions:
contents: write
pull-requests: write
actions: read
jobs:
check-rust-changes:
runs-on: ubuntu-latest
outputs:
rust-changed: ${{ steps.filter.outputs.rust }}
steps:
- uses: actions/checkout@v4
- id: filter
name: Check for Rust changes
uses: dorny/paths-filter@v3
with:
filters: |
rust:
- 'src/wasm-lib/**'
snapshot-tests:
runs-on: ubuntu-22.04
needs: check-rust-changes
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'yarn'
- name: Install dependencies
run: yarn
- name: Cache Playwright Browsers
uses: actions/cache@v4
with:
path: |
~/.cache/ms-playwright/
key: ${{ runner.os }}-playwright-${{ hashFiles('yarn.lock') }}
- name: Install Playwright Browsers
run: yarn playwright install --with-deps
- name: Download Wasm Cache
id: download-wasm
if: needs.check-rust-changes.outputs.rust-changed == 'false'
uses: dawidd6/action-download-artifact@v7
continue-on-error: true
with:
github_token: ${{secrets.GITHUB_TOKEN}}
name: wasm-bundle
workflow: build-and-store-wasm.yml
branch: main
path: src/wasm-lib/pkg
- name: copy wasm blob
if: needs.check-rust-changes.outputs.rust-changed == 'false'
run: cp src/wasm-lib/pkg/wasm_lib_bg.wasm public
continue-on-error: true
- name: Setup Rust
if: needs.check-rust-changes.outputs.rust-changed == 'true'
uses: dtolnay/rust-toolchain@stable
- name: Cache Wasm (because rust diff)
if: needs.check-rust-changes.outputs.rust-changed == 'true'
uses: Swatinem/rust-cache@v2
with:
workspaces: './src/wasm-lib'
- name: OR Cache Wasm (because wasm cache failed)
if: steps.download-wasm.outcome == 'failure'
uses: Swatinem/rust-cache@v2
with:
workspaces: './src/wasm-lib'
- name: Build Wasm (because rust diff)
if: needs.check-rust-changes.outputs.rust-changed == 'true'
run: yarn build:wasm
- name: OR Build Wasm (because wasm cache failed)
if: steps.download-wasm.outcome == 'failure'
run: yarn build:wasm
- name: build web
run: yarn tronb:vite:dev
- name: Run chrome snapshots
run: |
PLATFORM=web yarn playwright test --config=playwright.config.ts --retries="3" --update-snapshots --grep=@snapshot
env:
CI: true
NODE_ENV: development
VITE_KC_DEV_TOKEN: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
VITE_KC_SKIP_AUTH: true
token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
snapshottoken: ${{ secrets.KITTYCAD_API_TOKEN }}
- name: check for changes
id: git-check
run: |
{
echo 'changes<<EOF'
git diff --name-only e2e/playwright/snapshot-tests.spec.ts-snapshots
echo EOF
} >> "$GITHUB_OUTPUT"
# only upload artifacts if there's actually changes
- name: Upload changes, if any
if: steps.git-check.outputs.changes != ''
uses: actions/upload-artifact@v4
with:
name: playwright-snapshots-${{ runner.os }}-${{ github.sha }}
path: ${{ steps.git-check.outputs.changes }}
- name: Upload report, if any
uses: actions/upload-artifact@v4
if: steps.git-check.outputs.changes != ''
with:
name: playwright-report-${{ runner.os }}-${{ github.sha }}
path: playwright-report/
include-hidden-files: true
retention-days: 30
- name: Fail the run if we have snapshot updates
if: steps.git-check.outputs.changes != ''
run: exit 1
# TODO: check if we could comment on the PR as well

View File

@ -1,4 +1,4 @@
name: E2E Flow Tests name: E2E Tests
on: on:
push: push:
branches: [ main ] branches: [ main ]
@ -33,43 +33,38 @@ jobs:
rust: rust:
- 'src/wasm-lib/**' - 'src/wasm-lib/**'
flow-tests: electron:
timeout-minutes: 60 timeout-minutes: ${{ matrix.os == 'macos-14' && 60 || 50 }}
name: playwright:electron:${{ matrix.os }} ${{ matrix.shardIndex }} ${{ matrix.shardTotal }} name: playwright:electron:${{ matrix.os }} ${{ matrix.shardIndex }} ${{ matrix.shardTotal }}
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
# TODO: enable self-hosted-windows-8-cores once available os: [ubuntu-latest-8-cores, windows-latest-8-cores, macos-14-large]
os: [namespace-profile-ubuntu-8-cores, namespace-profile-macos-8-cores, windows-16-cores]
shardIndex: [1, 2, 3, 4] shardIndex: [1, 2, 3, 4]
shardTotal: [4] shardTotal: [4]
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
needs: check-rust-changes needs: check-rust-changes
steps: steps:
- name: Tune GitHub-hosted runner network
uses: smorimoto/tune-github-hosted-runner-network@v1
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: actions/setup-node@v4 - uses: actions/setup-node@v4
with: with:
node-version-file: '.nvmrc' node-version-file: '.nvmrc'
cache: 'yarn' cache: 'yarn'
- uses: KittyCAD/action-install-cli@main - uses: KittyCAD/action-install-cli@main
- name: Install dependencies - name: Install dependencies
shell: bash shell: bash
run: yarn run: yarn
- name: Cache Playwright Browsers - name: Cache Playwright Browsers
uses: actions/cache@v4 uses: actions/cache@v4
with: with:
path: | path: |
~/.cache/ms-playwright/ ~/.cache/ms-playwright/
key: ${{ runner.os }}-playwright-${{ hashFiles('yarn.lock') }} key: ${{ runner.os }}-playwright-${{ hashFiles('yarn.lock') }}
- name: Install Playwright Browsers - name: Install Playwright Browsers
shell: bash shell: bash
run: yarn playwright install --with-deps run: yarn playwright install --with-deps
- name: Download Wasm Cache - name: Download Wasm Cache
id: download-wasm id: download-wasm
if: needs.check-rust-changes.outputs.rust-changed == 'false' if: needs.check-rust-changes.outputs.rust-changed == 'false'
@ -81,39 +76,32 @@ jobs:
workflow: build-and-store-wasm.yml workflow: build-and-store-wasm.yml
branch: main branch: main
path: src/wasm-lib/pkg path: src/wasm-lib/pkg
- name: copy wasm blob - name: copy wasm blob
if: needs.check-rust-changes.outputs.rust-changed == 'false' if: needs.check-rust-changes.outputs.rust-changed == 'false'
shell: bash shell: bash
run: cp src/wasm-lib/pkg/wasm_lib_bg.wasm public run: cp src/wasm-lib/pkg/wasm_lib_bg.wasm public
continue-on-error: true continue-on-error: true
- name: Setup Rust - name: Setup Rust
uses: dtolnay/rust-toolchain@stable uses: dtolnay/rust-toolchain@stable
- name: Cache Wasm (because rust diff) - name: Cache Wasm (because rust diff)
if: needs.check-rust-changes.outputs.rust-changed == 'true' if: needs.check-rust-changes.outputs.rust-changed == 'true'
uses: Swatinem/rust-cache@v2 uses: Swatinem/rust-cache@v2
with: with:
workspaces: './src/wasm-lib' workspaces: './src/wasm-lib'
- name: OR Cache Wasm (because wasm cache failed) - name: OR Cache Wasm (because wasm cache failed)
if: steps.download-wasm.outcome == 'failure' if: steps.download-wasm.outcome == 'failure'
uses: Swatinem/rust-cache@v2 uses: Swatinem/rust-cache@v2
with: with:
workspaces: './src/wasm-lib' workspaces: './src/wasm-lib'
- name: install good sed - name: install good sed
if: ${{ startsWith(matrix.os, 'macos') }} if: ${{ startsWith(matrix.os, 'macos') }}
shell: bash shell: bash
run: | run: |
brew install gnu-sed brew install gnu-sed
echo "/opt/homebrew/opt/gnu-sed/libexec/gnubin" >> $GITHUB_PATH echo "/opt/homebrew/opt/gnu-sed/libexec/gnubin" >> $GITHUB_PATH
- name: Install vector - name: Install vector
shell: bash shell: bash
# TODO: figure out what to do with this, it's failing if: ${{ !startsWith(matrix.os, 'windows') }}
if: false
run: | run: |
curl --proto '=https' --tlsv1.2 -sSfL https://sh.vector.dev > /tmp/vector.sh curl --proto '=https' --tlsv1.2 -sSfL https://sh.vector.dev > /tmp/vector.sh
chmod +x /tmp/vector.sh chmod +x /tmp/vector.sh
@ -127,33 +115,77 @@ jobs:
sed -i "s#GH_ACTIONS_AXIOM_TOKEN#${{secrets.GH_ACTIONS_AXIOM_TOKEN}}#g" /tmp/vector.toml sed -i "s#GH_ACTIONS_AXIOM_TOKEN#${{secrets.GH_ACTIONS_AXIOM_TOKEN}}#g" /tmp/vector.toml
cat /tmp/vector.toml cat /tmp/vector.toml
${HOME}/.vector/bin/vector --config /tmp/vector.toml & ${HOME}/.vector/bin/vector --config /tmp/vector.toml &
- name: Build Wasm (because rust diff) - name: Build Wasm (because rust diff)
if: needs.check-rust-changes.outputs.rust-changed == 'true' if: needs.check-rust-changes.outputs.rust-changed == 'true'
shell: bash shell: bash
run: yarn build:wasm run: yarn build:wasm
- name: OR Build Wasm (because wasm cache failed) - name: OR Build Wasm (because wasm cache failed)
if: steps.download-wasm.outcome == 'failure' if: steps.download-wasm.outcome == 'failure'
shell: bash shell: bash
run: yarn build:wasm run: yarn build:wasm
- name: build electron
- name: build web
shell: bash shell: bash
run: yarn tronb:vite:dev run: yarn tron:package
- name: Run ubuntu/chrome snapshots
shell: bash
run: |
PLATFORM=web yarn playwright test --config=playwright.config.ts --retries="3" --update-snapshots --grep=@snapshot --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
env:
CI: true
NODE_ENV: development
VITE_KC_DEV_TOKEN: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
VITE_KC_SKIP_AUTH: true
token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
snapshottoken: ${{ secrets.KITTYCAD_API_TOKEN }}
- uses: actions/upload-artifact@v4
if: ${{ !cancelled() && (success() || failure()) }}
with:
name: playwright-report-${{ matrix.os }}-snapshot-${{ matrix.shardIndex }}-${{ github.sha }}
path: playwright-report/
include-hidden-files: true
retention-days: 30
overwrite: true
- name: Clean up test-results - name: Clean up test-results
if: ${{ !cancelled() && (success() || failure()) }} if: ${{ !cancelled() && (success() || failure()) }}
continue-on-error: true continue-on-error: true
run: rm -r test-results run: rm -r test-results
- name: check for changes
shell: bash
id: git-check
run: |
git add .
if git status | grep -q "Changes to be committed"
then echo "modified=true" >> $GITHUB_OUTPUT
else echo "modified=false" >> $GITHUB_OUTPUT
fi
- name: Commit changes, if any
if: steps.git-check.outputs.modified == 'true'
shell: bash
run: |
git add .
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
git remote set-url origin https://${{ github.actor }}:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.git
git fetch origin
echo ${{ github.head_ref }}
git checkout ${{ github.head_ref }}
git commit -am "A snapshot a day keeps the bugs away! 📷🐛 (OS: ${{matrix.os}})" || true
git push
git push origin ${{ github.head_ref }}
# only upload artifacts if there's actually changes
- uses: actions/upload-artifact@v4
if: steps.git-check.outputs.modified == 'true'
with:
name: playwright-report-${{ matrix.os }}-${{ matrix.shardIndex }}-${{ github.sha }}
path: playwright-report/
include-hidden-files: true
retention-days: 30
- uses: actions/download-artifact@v4 - uses: actions/download-artifact@v4
if: ${{ !cancelled() && (success() || failure()) }} if: ${{ !cancelled() && (success() || failure()) }}
continue-on-error: true continue-on-error: true
with: with:
name: test-results-${{ matrix.os }}-${{ matrix.shardIndex }}-${{ github.sha }} name: test-results-${{ matrix.os }}-${{ matrix.shardIndex }}-${{ github.sha }}
path: test-results/ path: test-results/
- name: Run playwright/electron flow (with retries) - name: Run playwright/electron flow (with retries)
id: retry id: retry
if: ${{ !cancelled() && (success() || failure()) }} if: ${{ !cancelled() && (success() || failure()) }}
@ -167,7 +199,6 @@ jobs:
VITE_KC_DEV_TOKEN: ${{ secrets.KITTYCAD_API_TOKEN_DEV }} VITE_KC_DEV_TOKEN: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
VITE_KC_SKIP_AUTH: true VITE_KC_SKIP_AUTH: true
token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }} token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
- uses: actions/upload-artifact@v4 - uses: actions/upload-artifact@v4
if: always() if: always()
with: with:
@ -176,7 +207,6 @@ jobs:
include-hidden-files: true include-hidden-files: true
retention-days: 30 retention-days: 30
overwrite: true overwrite: true
- uses: actions/upload-artifact@v4 - uses: actions/upload-artifact@v4
if: always() if: always()
with: with:
@ -185,3 +215,4 @@ jobs:
include-hidden-files: true include-hidden-files: true
retention-days: 30 retention-days: 30
overwrite: true overwrite: true

View File

@ -108,17 +108,17 @@ jobs:
run: yarn files:set-notes run: yarn files:set-notes
- name: Authenticate to Google Cloud - name: Authenticate to Google Cloud
uses: 'google-github-actions/auth@v2.1.8' uses: 'google-github-actions/auth@v2.1.7'
with: with:
credentials_json: '${{ secrets.GOOGLE_CLOUD_DL_SA }}' credentials_json: '${{ secrets.GOOGLE_CLOUD_DL_SA }}'
- name: Set up Google Cloud SDK - name: Set up Google Cloud SDK
uses: google-github-actions/setup-gcloud@v2.1.4 uses: google-github-actions/setup-gcloud@v2.1.2
with: with:
project_id: ${{ env.GOOGLE_CLOUD_PROJECT_ID }} project_id: ${{ env.GOOGLE_CLOUD_PROJECT_ID }}
- name: Upload release files to public bucket - name: Upload release files to public bucket
uses: google-github-actions/upload-cloud-storage@v2.2.2 uses: google-github-actions/upload-cloud-storage@v2.2.1
with: with:
path: out path: out
glob: '*' glob: '*'

3
.gitignore vendored
View File

@ -25,7 +25,6 @@ yarn-error.log*
.idea .idea
.vscode .vscode
.helix
src/wasm-lib/.idea src/wasm-lib/.idea
src/wasm-lib/.vscode src/wasm-lib/.vscode
@ -45,7 +44,7 @@ e2e/playwright/temp3.png
e2e/playwright/export-snapshots/* e2e/playwright/export-snapshots/*
!e2e/playwright/export-snapshots/*.png !e2e/playwright/export-snapshots/*.png
/kcl-samples
/test-results/ /test-results/
/playwright-report/ /playwright-report/
/blob-report/ /blob-report/

View File

@ -1,2 +0,0 @@
[editor]
auto-format = true

View File

@ -1,10 +0,0 @@
[language-server.eslint]
args = ["--stdio"]
command = "vscode-eslint-language-server"
[[language]]
name = "typescript"
auto-format = true
formatter = { command = "node_modules/.bin/prettier", args = ["--parser", "typescript"] }
language-servers = [ { name = "eslint", only-features = [ "diagnostics" ] }, "typescript-language-server" ]

View File

@ -101,7 +101,7 @@ This will start the application and hot-reload on changes.
Devtools can be opened with the usual Cmd-Opt-I (Mac) or Ctrl-Shift-I (Linux and Windows). Devtools can be opened with the usual Cmd-Opt-I (Mac) or Ctrl-Shift-I (Linux and Windows).
To build with electron-builder, run `yarn tronb:package:dev` (or `yarn tronb:package:prod` to point to the .env.production variables) To build, run `yarn tron:package`.
## Checking out commits / Bisecting ## Checking out commits / Bisecting
@ -337,47 +337,13 @@ For individual testing:
yarn test abstractSyntaxTree -t "unexpected closed curly brace" --silent=false yarn test abstractSyntaxTree -t "unexpected closed curly brace" --silent=false
``` ```
Which will run our suite of [Vitest unit](https://vitest.dev/) and [React Testing Library E2E](https://testing-library.com/docs/react-testing-library/intro) tests, in interactive mode by default. Which will run our suite of [Vitest unit](https://vitest.dev/) and [React Testing Library E2E](https://testing-library.com/docs/react-testing-library/intro/) tests, in interactive mode by default.
### Rust tests ### Rust tests
**Dependencies**
- `KITTYCAD_API_TOKEN`
- `cargo-nextest`
- `just`
#### Setting KITTYCAD_API_TOKEN
Use the production zoo.dev token, set this environment variable before running the tests
#### Installing cargonextest
```
cd src/wasm-lib
cargo search cargo-nextest
cargo install cargo-nextest
```
#### just
install [`just`](https://github.com/casey/just?tab=readme-ov-file#pre-built-binaries)
#### Running the tests
```bash ```bash
# With just
# Make sure KITTYCAD_API_TOKEN=<prod zoo.dev token> is set
# Make sure you installed cargo-nextest
# Make sure you installed just
cd src/wasm-lib cd src/wasm-lib
just test KITTYCAD_API_TOKEN=XXX cargo test -- --test-threads=1
```
```bash
# Without just
# Make sure KITTYCAD_API_TOKEN=<prod zoo.dev token> is set
# Make sure you installed cargo-nextest
cd src/wasm-lib
export RUST_BRACKTRACE="full" && cargo nextest run --workspace --test-threads=1
``` ```
Where `XXX` is an API token from the production engine (NOT the dev environment). Where `XXX` is an API token from the production engine (NOT the dev environment).

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -36,12 +36,12 @@ filletRadius = 2
mountingPlateSketch = startSketchOn("XY") mountingPlateSketch = startSketchOn("XY")
|> startProfileAt([-width / 2, -length / 2], %) |> startProfileAt([-width / 2, -length / 2], %)
|> line(endAbsolute = [width / 2, -length / 2], tag = $edge1) |> lineTo([width / 2, -length / 2], %, $edge1)
|> line(endAbsolute = [width / 2, length / 2], tag = $edge2) |> lineTo([width / 2, length / 2], %, $edge2)
|> line(endAbsolute = [-width / 2, length / 2], tag = $edge3) |> lineTo([-width / 2, length / 2], %, $edge3)
|> close(tag = $edge4) |> close(%, $edge4)
mountingPlate = extrude(mountingPlateSketch, length = thickness) mountingPlate = extrude(thickness, mountingPlateSketch)
|> fillet({ |> fillet({
radius = filletRadius, radius = filletRadius,
tags = [ tags = [
@ -63,12 +63,12 @@ filletRadius = 1
mountingPlateSketch = startSketchOn("XY") mountingPlateSketch = startSketchOn("XY")
|> startProfileAt([-width / 2, -length / 2], %) |> startProfileAt([-width / 2, -length / 2], %)
|> line(endAbsolute = [width / 2, -length / 2], tag = $edge1) |> lineTo([width / 2, -length / 2], %, $edge1)
|> line(endAbsolute = [width / 2, length / 2], tag = $edge2) |> lineTo([width / 2, length / 2], %, $edge2)
|> line(endAbsolute = [-width / 2, length / 2], tag = $edge3) |> lineTo([-width / 2, length / 2], %, $edge3)
|> close(tag = $edge4) |> close(%, $edge4)
mountingPlate = extrude(mountingPlateSketch, length = thickness) mountingPlate = extrude(thickness, mountingPlateSketch)
|> fillet({ |> fillet({
radius = filletRadius, radius = filletRadius,
tolerance = 0.000001, tolerance = 0.000001,

File diff suppressed because one or more lines are too long

View File

@ -29,14 +29,14 @@ getNextAdjacentEdge(tag: TagIdentifier) -> Uuid
```js ```js
exampleSketch = startSketchOn('XZ') exampleSketch = startSketchOn('XZ')
|> startProfileAt([0, 0], %) |> startProfileAt([0, 0], %)
|> line(end = [10, 0]) |> line([10, 0], %)
|> angledLine({ angle = 60, length = 10 }, %) |> angledLine({ angle = 60, length = 10 }, %)
|> angledLine({ angle = 120, length = 10 }, %) |> angledLine({ angle = 120, length = 10 }, %)
|> line(end = [-10, 0]) |> line([-10, 0], %)
|> angledLine({ angle = 240, length = 10 }, %, $referenceEdge) |> angledLine({ angle = 240, length = 10 }, %, $referenceEdge)
|> close() |> close(%)
example = extrude(exampleSketch, length = 5) example = extrude(5, exampleSketch)
|> fillet({ |> fillet({
radius = 3, radius = 3,
tags = [getNextAdjacentEdge(referenceEdge)] tags = [getNextAdjacentEdge(referenceEdge)]

View File

@ -29,14 +29,14 @@ getOppositeEdge(tag: TagIdentifier) -> Uuid
```js ```js
exampleSketch = startSketchOn('XZ') exampleSketch = startSketchOn('XZ')
|> startProfileAt([0, 0], %) |> startProfileAt([0, 0], %)
|> line(end = [10, 0]) |> line([10, 0], %)
|> angledLine({ angle = 60, length = 10 }, %) |> angledLine({ angle = 60, length = 10 }, %)
|> angledLine({ angle = 120, length = 10 }, %) |> angledLine({ angle = 120, length = 10 }, %)
|> line(end = [-10, 0]) |> line([-10, 0], %)
|> angledLine({ angle = 240, length = 10 }, %, $referenceEdge) |> angledLine({ angle = 240, length = 10 }, %, $referenceEdge)
|> close() |> close(%)
example = extrude(exampleSketch, length = 5) example = extrude(5, exampleSketch)
|> fillet({ |> fillet({
radius = 3, radius = 3,
tags = [getOppositeEdge(referenceEdge)] tags = [getOppositeEdge(referenceEdge)]

View File

@ -29,14 +29,14 @@ getPreviousAdjacentEdge(tag: TagIdentifier) -> Uuid
```js ```js
exampleSketch = startSketchOn('XZ') exampleSketch = startSketchOn('XZ')
|> startProfileAt([0, 0], %) |> startProfileAt([0, 0], %)
|> line(end = [10, 0]) |> line([10, 0], %)
|> angledLine({ angle = 60, length = 10 }, %) |> angledLine({ angle = 60, length = 10 }, %)
|> angledLine({ angle = 120, length = 10 }, %) |> angledLine({ angle = 120, length = 10 }, %)
|> line(end = [-10, 0]) |> line([-10, 0], %)
|> angledLine({ angle = 240, length = 10 }, %, $referenceEdge) |> angledLine({ angle = 240, length = 10 }, %, $referenceEdge)
|> close() |> close(%)
example = extrude(exampleSketch, length = 5) example = extrude(5, exampleSketch)
|> fillet({ |> fillet({
radius = 3, radius = 3,
tags = [getPreviousAdjacentEdge(referenceEdge)] tags = [getPreviousAdjacentEdge(referenceEdge)]

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -31,11 +31,11 @@ hollow(thickness: number, solid: Solid) -> Solid
// Hollow a basic sketch. // Hollow a basic sketch.
firstSketch = startSketchOn('XY') firstSketch = startSketchOn('XY')
|> startProfileAt([-12, 12], %) |> startProfileAt([-12, 12], %)
|> line(end = [24, 0]) |> line([24, 0], %)
|> line(end = [0, -24]) |> line([0, -24], %)
|> line(end = [-24, 0]) |> line([-24, 0], %)
|> close() |> close(%)
|> extrude(length = 6) |> extrude(6, %)
|> hollow(0.25, %) |> hollow(0.25, %)
``` ```
@ -45,11 +45,11 @@ firstSketch = startSketchOn('XY')
// Hollow a basic sketch. // Hollow a basic sketch.
firstSketch = startSketchOn('-XZ') firstSketch = startSketchOn('-XZ')
|> startProfileAt([-12, 12], %) |> startProfileAt([-12, 12], %)
|> line(end = [24, 0]) |> line([24, 0], %)
|> line(end = [0, -24]) |> line([0, -24], %)
|> line(end = [-24, 0]) |> line([-24, 0], %)
|> close() |> close(%)
|> extrude(length = 6) |> extrude(6, %)
|> hollow(0.5, %) |> hollow(0.5, %)
``` ```
@ -60,25 +60,25 @@ firstSketch = startSketchOn('-XZ')
size = 100 size = 100
case = startSketchOn('-XZ') case = startSketchOn('-XZ')
|> startProfileAt([-size, -size], %) |> startProfileAt([-size, -size], %)
|> line(end = [2 * size, 0]) |> line([2 * size, 0], %)
|> line(end = [0, 2 * size]) |> line([0, 2 * size], %)
|> tangentialArcTo([-size, size], %) |> tangentialArcTo([-size, size], %)
|> close() |> close(%)
|> extrude(length = 65) |> extrude(65, %)
thing1 = startSketchOn(case, 'end') thing1 = startSketchOn(case, 'end')
|> circle({ |> circle({
center = [-size / 2, -size / 2], center = [-size / 2, -size / 2],
radius = 25 radius = 25
}, %) }, %)
|> extrude(length = 50) |> extrude(50, %)
thing2 = startSketchOn(case, 'end') thing2 = startSketchOn(case, 'end')
|> circle({ |> circle({
center = [size / 2, -size / 2], center = [size / 2, -size / 2],
radius = 25 radius = 25
}, %) }, %)
|> extrude(length = 50) |> extrude(50, %)
hollow(0.5, case) hollow(0.5, case)
``` ```

View File

@ -4,16 +4,14 @@ excerpt: "Import a CAD file."
layout: manual layout: manual
--- ---
**WARNING:** This function is deprecated.
Import a CAD file. Import a CAD file.
**DEPRECATED** Prefer to use import statements.
For formats lacking unit data (such as STL, OBJ, or PLY files), the default unit of measurement is millimeters. Alternatively you may specify the unit by passing your desired measurement unit in the options parameter. When importing a GLTF file, the bin file will be imported as well. Import paths are relative to the current project directory. For formats lacking unit data (such as STL, OBJ, or PLY files), the default unit of measurement is millimeters. Alternatively you may specify the unit by passing your desired measurement unit in the options parameter. When importing a GLTF file, the bin file will be imported as well. Import paths are relative to the current project directory.
Note: The import command currently only works when using the native Modeling App. Note: The import command currently only works when using the native Modeling App.
For importing KCL functions using the `import` statement, see the docs on [KCL modules](/docs/kcl/modules).
```js ```js
import(file_path: String, options?: ImportFormat) -> ImportedGeometry import(file_path: String, options?: ImportFormat) -> ImportedGeometry
``` ```

View File

@ -30,12 +30,10 @@ layout: manual
* [`assertLessThan`](kcl/assertLessThan) * [`assertLessThan`](kcl/assertLessThan)
* [`assertLessThanOrEq`](kcl/assertLessThanOrEq) * [`assertLessThanOrEq`](kcl/assertLessThanOrEq)
* [`atan`](kcl/atan) * [`atan`](kcl/atan)
* [`atan2`](kcl/atan2)
* [`bezierCurve`](kcl/bezierCurve) * [`bezierCurve`](kcl/bezierCurve)
* [`ceil`](kcl/ceil) * [`ceil`](kcl/ceil)
* [`chamfer`](kcl/chamfer) * [`chamfer`](kcl/chamfer)
* [`circle`](kcl/circle) * [`circle`](kcl/circle)
* [`circleThreePoint`](kcl/circleThreePoint)
* [`close`](kcl/close) * [`close`](kcl/close)
* [`cm`](kcl/cm) * [`cm`](kcl/cm)
* [`cos`](kcl/cos) * [`cos`](kcl/cos)
@ -48,16 +46,18 @@ layout: manual
* [`getOppositeEdge`](kcl/getOppositeEdge) * [`getOppositeEdge`](kcl/getOppositeEdge)
* [`getPreviousAdjacentEdge`](kcl/getPreviousAdjacentEdge) * [`getPreviousAdjacentEdge`](kcl/getPreviousAdjacentEdge)
* [`helix`](kcl/helix) * [`helix`](kcl/helix)
* [`helixRevolutions`](kcl/helixRevolutions)
* [`hole`](kcl/hole) * [`hole`](kcl/hole)
* [`hollow`](kcl/hollow) * [`hollow`](kcl/hollow)
* [`import`](kcl/import)
* [`inch`](kcl/inch) * [`inch`](kcl/inch)
* [`int`](kcl/int)
* [`lastSegX`](kcl/lastSegX) * [`lastSegX`](kcl/lastSegX)
* [`lastSegY`](kcl/lastSegY) * [`lastSegY`](kcl/lastSegY)
* [`legAngX`](kcl/legAngX) * [`legAngX`](kcl/legAngX)
* [`legAngY`](kcl/legAngY) * [`legAngY`](kcl/legAngY)
* [`legLen`](kcl/legLen) * [`legLen`](kcl/legLen)
* [`line`](kcl/line) * [`line`](kcl/line)
* [`lineTo`](kcl/lineTo)
* [`ln`](kcl/ln) * [`ln`](kcl/ln)
* [`loft`](kcl/loft) * [`loft`](kcl/loft)
* [`log`](kcl/log) * [`log`](kcl/log)
@ -79,7 +79,6 @@ layout: manual
* [`pi`](kcl/pi) * [`pi`](kcl/pi)
* [`polar`](kcl/polar) * [`polar`](kcl/polar)
* [`polygon`](kcl/polygon) * [`polygon`](kcl/polygon)
* [`pop`](kcl/pop)
* [`pow`](kcl/pow) * [`pow`](kcl/pow)
* [`profileStart`](kcl/profileStart) * [`profileStart`](kcl/profileStart)
* [`profileStartX`](kcl/profileStartX) * [`profileStartX`](kcl/profileStartX)
@ -101,8 +100,8 @@ layout: manual
* [`sin`](kcl/sin) * [`sin`](kcl/sin)
* [`sqrt`](kcl/sqrt) * [`sqrt`](kcl/sqrt)
* [`startProfileAt`](kcl/startProfileAt) * [`startProfileAt`](kcl/startProfileAt)
* [`startSketchAt`](kcl/startSketchAt)
* [`startSketchOn`](kcl/startSketchOn) * [`startSketchOn`](kcl/startSketchOn)
* [`sweep`](kcl/sweep)
* [`tan`](kcl/tan) * [`tan`](kcl/tan)
* [`tangentToEnd`](kcl/tangentToEnd) * [`tangentToEnd`](kcl/tangentToEnd)
* [`tangentialArc`](kcl/tangentialArc) * [`tangentialArc`](kcl/tangentialArc)

View File

@ -4,8 +4,6 @@ excerpt: "Convert a number to an integer."
layout: manual layout: manual
--- ---
**WARNING:** This function is deprecated.
Convert a number to an integer. Convert a number to an integer.
DEPRECATED use floor(), ceil(), or round(). DEPRECATED use floor(), ceil(), or round().
@ -38,7 +36,7 @@ assertEqual(n, 3, 0.0001, "5/2 = 2.5, rounded up makes 3")
// Draw n cylinders. // Draw n cylinders.
startSketchOn('XZ') startSketchOn('XZ')
|> circle({ center = [0, 0], radius = 2 }, %) |> circle({ center = [0, 0], radius = 2 }, %)
|> extrude(length = 5) |> extrude(5, %)
|> patternTransform(n, fn(id) { |> patternTransform(n, fn(id) {
return { translate = [4 * id, 0, 0] } return { translate = [4 * id, 0, 0] }
}, %) }, %)

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -31,7 +31,7 @@ patternCircular3d(data: CircularPattern3dData, solid_set: SolidSet) -> [Solid]
exampleSketch = startSketchOn('XZ') exampleSketch = startSketchOn('XZ')
|> circle({ center = [0, 0], radius = 1 }, %) |> circle({ center = [0, 0], radius = 1 }, %)
example = extrude(exampleSketch, length = -5) example = extrude(-5, exampleSketch)
|> patternCircular3d({ |> patternCircular3d({
axis = [1, -1, 0], axis = [1, -1, 0],
center = [10, -20, 0], center = [10, -20, 0],

File diff suppressed because one or more lines are too long

View File

@ -30,12 +30,12 @@ patternLinear3d(data: LinearPattern3dData, solid_set: SolidSet) -> [Solid]
```js ```js
exampleSketch = startSketchOn('XZ') exampleSketch = startSketchOn('XZ')
|> startProfileAt([0, 0], %) |> startProfileAt([0, 0], %)
|> line(end = [0, 2]) |> line([0, 2], %)
|> line(end = [3, 1]) |> line([3, 1], %)
|> line(end = [0, -4]) |> line([0, -4], %)
|> close() |> close(%)
example = extrude(exampleSketch, length = 1) example = extrude(1, exampleSketch)
|> patternLinear3d({ |> patternLinear3d({
axis = [1, 0, 1], axis = [1, 0, 1],
instances = 7, instances = 7,

View File

@ -35,7 +35,7 @@ The transform function returns a transform object. All properties of the object
- `rotation.origin` (either "local" i.e. rotate around its own center, "global" i.e. rotate around the scene's center, or a 3D point, defaults to "local") - `rotation.origin` (either "local" i.e. rotate around its own center, "global" i.e. rotate around the scene's center, or a 3D point, defaults to "local")
```js ```js
patternTransform(total_instances: integer, transform_function: FunctionParam, solid_set: SolidSet) -> [Solid] patternTransform(total_instances: u32, transform_function: FunctionParam, solid_set: SolidSet) -> [Solid]
``` ```
@ -43,7 +43,7 @@ patternTransform(total_instances: integer, transform_function: FunctionParam, so
| Name | Type | Description | Required | | Name | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `total_instances` | `integer` | | Yes | | `total_instances` | `u32` | | Yes |
| `transform_function` | `FunctionParam` | | Yes | | `transform_function` | `FunctionParam` | | Yes |
| `solid_set` | [`SolidSet`](/docs/kcl/types/SolidSet) | A solid or a group of solids. | Yes | | `solid_set` | [`SolidSet`](/docs/kcl/types/SolidSet) | A solid or a group of solids. | Yes |
@ -63,7 +63,7 @@ fn transform(id) {
// Sketch 4 cylinders. // Sketch 4 cylinders.
sketch001 = startSketchOn('XZ') sketch001 = startSketchOn('XZ')
|> circle({ center = [0, 0], radius = 2 }, %) |> circle({ center = [0, 0], radius = 2 }, %)
|> extrude(length = 5) |> extrude(5, %)
|> patternTransform(4, transform, %) |> patternTransform(4, transform, %)
``` ```
@ -79,7 +79,7 @@ fn transform(id) {
sketch001 = startSketchOn('XZ') sketch001 = startSketchOn('XZ')
|> circle({ center = [0, 0], radius = 2 }, %) |> circle({ center = [0, 0], radius = 2 }, %)
|> extrude(length = 5) |> extrude(5, %)
|> patternTransform(4, transform, %) |> patternTransform(4, transform, %)
``` ```
@ -95,14 +95,13 @@ fn cube(length, center) {
p2 = [l + x, l + y] p2 = [l + x, l + y]
p3 = [l + x, -l + y] p3 = [l + x, -l + y]
return startSketchOn('XY') return startSketchAt(p0)
|> startProfileAt(p0, %) |> lineTo(p1, %)
|> line(endAbsolute = p1) |> lineTo(p2, %)
|> line(endAbsolute = p2) |> lineTo(p3, %)
|> line(endAbsolute = p3) |> lineTo(p0, %)
|> line(endAbsolute = p0) |> close(%)
|> close() |> extrude(length, %)
|> extrude(length = length)
} }
width = 20 width = 20
@ -133,14 +132,13 @@ fn cube(length, center) {
p2 = [l + x, l + y] p2 = [l + x, l + y]
p3 = [l + x, -l + y] p3 = [l + x, -l + y]
return startSketchOn('XY') return startSketchAt(p0)
|> startProfileAt(p0, %) |> lineTo(p1, %)
|> line(endAbsolute = p1) |> lineTo(p2, %)
|> line(endAbsolute = p2) |> lineTo(p3, %)
|> line(endAbsolute = p3) |> lineTo(p0, %)
|> line(endAbsolute = p0) |> close(%)
|> close() |> extrude(length, %)
|> extrude(length = length)
} }
width = 20 width = 20
@ -179,7 +177,7 @@ fn layer() {
return startSketchOn("XY") return startSketchOn("XY")
// or some other plane idk // or some other plane idk
|> circle({ center = [0, 0], radius = 1 }, %, $tag1) |> circle({ center = [0, 0], radius = 1 }, %, $tag1)
|> extrude(length = h) |> extrude(h, %)
} }
// The vase is 100 layers tall. // The vase is 100 layers tall.
// The 100 layers are replica of each other, with a slight transformation applied to each. // The 100 layers are replica of each other, with a slight transformation applied to each.
@ -197,15 +195,14 @@ fn transform(i) {
{ rotation = { angle = 45 * i } } { rotation = { angle = 45 * i } }
] ]
} }
startSketchOn('XY') startSketchAt([0, 0])
|> startProfileAt([0, 0], %)
|> polygon({ |> polygon({
radius = 10, radius = 10,
numSides = 4, numSides = 4,
center = [0, 0], center = [0, 0],
inscribed = false inscribed = false
}, %) }, %)
|> extrude(length = 4) |> extrude(4, %)
|> patternTransform(3, transform, %) |> patternTransform(3, transform, %)
``` ```

View File

@ -9,7 +9,7 @@ Just like patternTransform, but works on 2D sketches not 3D solids.
```js ```js
patternTransform2d(total_instances: integer, transform_function: FunctionParam, solid_set: SketchSet) -> [Sketch] patternTransform2d(total_instances: u32, transform_function: FunctionParam, solid_set: SketchSet) -> [Sketch]
``` ```
@ -17,7 +17,7 @@ patternTransform2d(total_instances: integer, transform_function: FunctionParam,
| Name | Type | Description | Required | | Name | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `total_instances` | `integer` | | Yes | | `total_instances` | `u32` | | Yes |
| `transform_function` | `FunctionParam` | | Yes | | `transform_function` | `FunctionParam` | | Yes |
| `solid_set` | [`SketchSet`](/docs/kcl/types/SketchSet) | A sketch or a group of sketches. | Yes | | `solid_set` | [`SketchSet`](/docs/kcl/types/SketchSet) | A sketch or a group of sketches. | Yes |

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -28,23 +28,21 @@ segEnd(tag: TagIdentifier) -> [number]
```js ```js
w = 15 w = 15
cube = startSketchOn('XY') cube = startSketchAt([0, 0])
|> startProfileAt([0, 0], %) |> line([w, 0], %, $line1)
|> line(end = [w, 0], tag = $line1) |> line([0, w], %, $line2)
|> line(end = [0, w], tag = $line2) |> line([-w, 0], %, $line3)
|> line(end = [-w, 0], tag = $line3) |> line([0, -w], %, $line4)
|> line(end = [0, -w], tag = $line4) |> close(%)
|> close() |> extrude(5, %)
|> extrude(length = 5)
fn cylinder(radius, tag) { fn cylinder(radius, tag) {
return startSketchOn('XY') return startSketchAt([0, 0])
|> startProfileAt([0, 0], %)
|> circle({ |> circle({
radius = radius, radius = radius,
center = segEnd(tag) center = segEnd(tag)
}, %) }, %)
|> extrude(length = radius) |> extrude(radius, %)
} }
cylinder(1, line1) cylinder(1, line1)

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -28,23 +28,21 @@ segStart(tag: TagIdentifier) -> [number]
```js ```js
w = 15 w = 15
cube = startSketchOn('XY') cube = startSketchAt([0, 0])
|> startProfileAt([0, 0], %) |> line([w, 0], %, $line1)
|> line(end = [w, 0], tag = $line1) |> line([0, w], %, $line2)
|> line(end = [0, w], tag = $line2) |> line([-w, 0], %, $line3)
|> line(end = [-w, 0], tag = $line3) |> line([0, -w], %, $line4)
|> line(end = [0, -w], tag = $line4) |> close(%)
|> close() |> extrude(5, %)
|> extrude(length = 5)
fn cylinder(radius, tag) { fn cylinder(radius, tag) {
return startSketchOn('XY') return startSketchAt([0, 0])
|> startProfileAt([0, 0], %)
|> circle({ |> circle({
radius = radius, radius = radius,
center = segStart(tag) center = segStart(tag)
}, %) }, %)
|> extrude(length = radius) |> extrude(radius, %)
} }
cylinder(1, line1) cylinder(1, line1)

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -31,11 +31,11 @@ shell(data: ShellData, solid_set: SolidSet) -> SolidSet
// Remove the end face for the extrusion. // Remove the end face for the extrusion.
firstSketch = startSketchOn('XY') firstSketch = startSketchOn('XY')
|> startProfileAt([-12, 12], %) |> startProfileAt([-12, 12], %)
|> line(end = [24, 0]) |> line([24, 0], %)
|> line(end = [0, -24]) |> line([0, -24], %)
|> line(end = [-24, 0]) |> line([-24, 0], %)
|> close() |> close(%)
|> extrude(length = 6) |> extrude(6, %)
// Remove the end face for the extrusion. // Remove the end face for the extrusion.
shell({ faces = ['end'], thickness = 0.25 }, firstSketch) shell({ faces = ['end'], thickness = 0.25 }, firstSketch)
@ -47,11 +47,11 @@ shell({ faces = ['end'], thickness = 0.25 }, firstSketch)
// Remove the start face for the extrusion. // Remove the start face for the extrusion.
firstSketch = startSketchOn('-XZ') firstSketch = startSketchOn('-XZ')
|> startProfileAt([-12, 12], %) |> startProfileAt([-12, 12], %)
|> line(end = [24, 0]) |> line([24, 0], %)
|> line(end = [0, -24]) |> line([0, -24], %)
|> line(end = [-24, 0]) |> line([-24, 0], %)
|> close() |> close(%)
|> extrude(length = 6) |> extrude(6, %)
// Remove the start face for the extrusion. // Remove the start face for the extrusion.
shell({ faces = ['start'], thickness = 0.25 }, firstSketch) shell({ faces = ['start'], thickness = 0.25 }, firstSketch)
@ -63,11 +63,11 @@ shell({ faces = ['start'], thickness = 0.25 }, firstSketch)
// Remove a tagged face and the end face for the extrusion. // Remove a tagged face and the end face for the extrusion.
firstSketch = startSketchOn('XY') firstSketch = startSketchOn('XY')
|> startProfileAt([-12, 12], %) |> startProfileAt([-12, 12], %)
|> line(end = [24, 0]) |> line([24, 0], %)
|> line(end = [0, -24]) |> line([0, -24], %)
|> line(end = [-24, 0], tag = $myTag) |> line([-24, 0], %, $myTag)
|> close() |> close(%)
|> extrude(length = 6) |> extrude(6, %)
// Remove a tagged face for the extrusion. // Remove a tagged face for the extrusion.
shell({ faces = [myTag], thickness = 0.25 }, firstSketch) shell({ faces = [myTag], thickness = 0.25 }, firstSketch)
@ -79,11 +79,11 @@ shell({ faces = [myTag], thickness = 0.25 }, firstSketch)
// Remove multiple faces at once. // Remove multiple faces at once.
firstSketch = startSketchOn('XY') firstSketch = startSketchOn('XY')
|> startProfileAt([-12, 12], %) |> startProfileAt([-12, 12], %)
|> line(end = [24, 0]) |> line([24, 0], %)
|> line(end = [0, -24]) |> line([0, -24], %)
|> line(end = [-24, 0], tag = $myTag) |> line([-24, 0], %, $myTag)
|> close() |> close(%)
|> extrude(length = 6) |> extrude(6, %)
// Remove a tagged face and the end face for the extrusion. // Remove a tagged face and the end face for the extrusion.
shell({ shell({
@ -99,25 +99,25 @@ shell({
size = 100 size = 100
case = startSketchOn('-XZ') case = startSketchOn('-XZ')
|> startProfileAt([-size, -size], %) |> startProfileAt([-size, -size], %)
|> line(end = [2 * size, 0]) |> line([2 * size, 0], %)
|> line(end = [0, 2 * size]) |> line([0, 2 * size], %)
|> tangentialArcTo([-size, size], %) |> tangentialArcTo([-size, size], %)
|> close() |> close(%)
|> extrude(length = 65) |> extrude(65, %)
thing1 = startSketchOn(case, 'end') thing1 = startSketchOn(case, 'end')
|> circle({ |> circle({
center = [-size / 2, -size / 2], center = [-size / 2, -size / 2],
radius = 25 radius = 25
}, %) }, %)
|> extrude(length = 50) |> extrude(50, %)
thing2 = startSketchOn(case, 'end') thing2 = startSketchOn(case, 'end')
|> circle({ |> circle({
center = [size / 2, -size / 2], center = [size / 2, -size / 2],
radius = 25 radius = 25
}, %) }, %)
|> extrude(length = 50) |> extrude(50, %)
// We put "case" in the shell function to shell the entire object. // We put "case" in the shell function to shell the entire object.
shell({ faces = ['start'], thickness = 5 }, case) shell({ faces = ['start'], thickness = 5 }, case)
@ -130,25 +130,25 @@ shell({ faces = ['start'], thickness = 5 }, case)
size = 100 size = 100
case = startSketchOn('XY') case = startSketchOn('XY')
|> startProfileAt([-size, -size], %) |> startProfileAt([-size, -size], %)
|> line(end = [2 * size, 0]) |> line([2 * size, 0], %)
|> line(end = [0, 2 * size]) |> line([0, 2 * size], %)
|> tangentialArcTo([-size, size], %) |> tangentialArcTo([-size, size], %)
|> close() |> close(%)
|> extrude(length = 65) |> extrude(65, %)
thing1 = startSketchOn(case, 'end') thing1 = startSketchOn(case, 'end')
|> circle({ |> circle({
center = [-size / 2, -size / 2], center = [-size / 2, -size / 2],
radius = 25 radius = 25
}, %) }, %)
|> extrude(length = 50) |> extrude(50, %)
thing2 = startSketchOn(case, 'end') thing2 = startSketchOn(case, 'end')
|> circle({ |> circle({
center = [size / 2, -size / 2], center = [size / 2, -size / 2],
radius = 25 radius = 25
}, %) }, %)
|> extrude(length = 50) |> extrude(50, %)
// We put "thing1" in the shell function to shell the end face of the object. // We put "thing1" in the shell function to shell the end face of the object.
shell({ faces = ['end'], thickness = 5 }, thing1) shell({ faces = ['end'], thickness = 5 }, thing1)
@ -164,25 +164,25 @@ shell({ faces = ['end'], thickness = 5 }, thing1)
size = 100 size = 100
case = startSketchOn('XY') case = startSketchOn('XY')
|> startProfileAt([-size, -size], %) |> startProfileAt([-size, -size], %)
|> line(end = [2 * size, 0]) |> line([2 * size, 0], %)
|> line(end = [0, 2 * size]) |> line([0, 2 * size], %)
|> tangentialArcTo([-size, size], %) |> tangentialArcTo([-size, size], %)
|> close() |> close(%)
|> extrude(length = 65) |> extrude(65, %)
thing1 = startSketchOn(case, 'end') thing1 = startSketchOn(case, 'end')
|> circle({ |> circle({
center = [-size / 2, -size / 2], center = [-size / 2, -size / 2],
radius = 25 radius = 25
}, %) }, %)
|> extrude(length = 50) |> extrude(50, %)
thing2 = startSketchOn(case, 'end') thing2 = startSketchOn(case, 'end')
|> circle({ |> circle({
center = [size / 2, -size / 2], center = [size / 2, -size / 2],
radius = 25 radius = 25
}, %) }, %)
|> extrude(length = 50) |> extrude(50, %)
// We put "thing1" and "thing2" in the shell function to shell the end face of the object. // We put "thing1" and "thing2" in the shell function to shell the end face of the object.
shell({ faces = ['end'], thickness = 5 }, [thing1, thing2]) shell({ faces = ['end'], thickness = 5 }, [thing1, thing2])

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

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