Compare commits

...

99 Commits

Author SHA1 Message Date
274631024e Add test snapshots on two tests 2025-03-28 14:41:39 -04:00
29ab4679c4 Merge branch 'main' into pierremtb/issue5504-Add-edit-flow-for-Revolve 2025-03-28 13:51:30 -04:00
42123383bb Add path argument error to console error whitelist (#6046)
* Add path argument error to console error whitelist

* Lint
2025-03-28 13:50:54 -04:00
f7501e3cef Fix edit insert order 2025-03-28 13:18:27 -04:00
ef4c606ed1 Update sweep-related icons to be less detailed, show result (#6047)
* WIP trying out various icons

* Update to use outcome bodies for icons
2025-03-28 16:42:31 +00:00
1ebb73b935 Fix 'originalCode' undefined in a test (#6027) 2025-03-28 12:36:54 -04:00
8fbdac439b Merge branch 'main' into pierremtb/issue5504-Add-edit-flow-for-Revolve 2025-03-28 12:25:23 -04:00
b57d31c0e7 Fix build:wasm:dev for --dev builds (#6038)
This is useful since it preserves Rust backtraces in WASM.
2025-03-28 08:40:21 -04:00
05add6b038 Lint 2025-03-28 07:34:41 -04:00
678ebbc310 Make Helix available in numbered releases (#6024)
* Helix release outside of dev and nightly

* Make length non required on edge mode so we get the edge length by default
2025-03-28 11:25:32 +00:00
7364877539 Add edit flow for Revolve
Fixes #5504
2025-03-28 07:03:57 -04:00
cc2efd316c Add more TS lints and fix types (#6037)
* Add as const lint

* Add lint for no implied eval

* Fix incorrect type and add lints

* Add more type lints

* Remove redundant type assertions and add lint

* Fix to turn off incorrect base rules

* Fix yarn lint workflow to wait for build:wasm

* Change so that we don't build:wasm more than once in the workflow
2025-03-28 04:24:24 +00:00
d1f811f91d Boolean create UI (#5906)
* first steps, add to cmd bar etc

* cmdbar working well enough

* mvp

* lint

* fix after rebase

* intersect and union mvps

* add test

* some clean up

* further fix up

* Update src/lang/modifyAst/boolean.ts

Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>

* Update src/lang/modifyAst/boolean.ts

Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>

* pierre's comments

* tsc

* add comment

---------

Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>
2025-03-28 03:56:48 +00:00
7ca3afff9f Add CSG operations to the Feature Tree (#6028)
* Add operation tracking for CSG boolean functions

* Add CSG operations to the Feature Tree

* Add just command

* Add union sim test

* Update output with new sim test

* Add CSG subtract test

* Update output from subtract test

* Add intersect sim test

* Update output for intersect test
2025-03-28 09:48:55 +11:00
71b9e40bd9 Fix to not use cursed empty object type and add lint (#6033) 2025-03-27 22:08:57 +00:00
4f35197a96 Add a loading state to CommandBarKclInput while calculating (#6025)
* Add a loading state to CommandBarKclInput while calculating

This is so that we can more reliably await for the calculation to be
completed before advancing the command bar in Playwright E2E tests.

* Make sure the spinner shows on first frame, before `isExecuting` is set too
2025-03-27 16:22:04 -04:00
40b0cf5fd3 Create a new commit to preserve history from main (#6019) 2025-03-27 15:49:38 +00:00
355e6acf0d Make tests fail when there are console errors (#6015)
* Add a test to confirm console errors fail tests

* Check for console errors on all browsers

* Ignore error impacting lots of tests

* Add more detected errors to the allowlist for now
2025-03-27 15:41:25 +00:00
4ff38e7f44 Add dual-sink and makeup mirror to KCL samples (#6023)
* add makeup mirror

* m -> M

* add metal sink unit

* Update kcl-samples simulation test output

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-03-27 10:57:01 -04:00
1dcd3b84b7 Populate all environment variables from files (#6014) 2025-03-27 10:38:24 -04:00
2957216bd3 Fix kitt kcl-sample expected output (#6022) 2025-03-27 14:31:12 +00:00
11160f0b40 Point-and-click Helix from cylinders (#5979) 2025-03-26 17:57:30 -04:00
327bd31a84 Add edit flow for Revolve
Fixes #5504
2025-03-26 07:59:46 -04:00
4292ba84f0 A snapshot a day keeps the bugs away! 📷🐛 2025-03-25 19:37:32 +00:00
848f7ec074 Fix third test 2025-03-25 15:27:36 -04:00
a61f4def7c Update from main, add proper error returns 2025-03-25 07:26:17 -04:00
afb3517446 Lint 2025-03-24 17:22:22 -04:00
483a390e9e A snapshot a day keeps the bugs away! 📷🐛 2025-03-24 20:55:23 +00:00
8abd2481dc A snapshot a day keeps the bugs away! 📷🐛 2025-03-24 20:45:42 +00:00
e8bf7f63a3 A snapshot a day keeps the bugs away! 📷🐛 2025-03-24 20:36:00 +00:00
2aba760f88 A snapshot a day keeps the bugs away! 📷🐛 2025-03-24 20:26:36 +00:00
08283391aa Update from main 2025-03-24 16:12:02 -04:00
bae2a717ad A snapshot a day keeps the bugs away! 📷🐛 2025-03-24 18:13:40 +00:00
6c07e506d3 Clean up 2025-03-24 14:03:28 -04:00
6405b7f12c A snapshot a day keeps the bugs away! 📷🐛 2025-03-24 17:59:54 +00:00
79c7478e8e Merge branch 'pierremtb/issue5504-Add-edit-flow-for-Revolve' of https://github.com/KittyCAD/modeling-app into pierremtb/issue5504-Add-edit-flow-for-Revolve 2025-03-24 13:50:14 -04:00
b11df628a6 Move to fromPromise actor, fix test 2025-03-24 13:50:12 -04:00
c974e87d24 A snapshot a day keeps the bugs away! 📷🐛 2025-03-24 17:41:55 +00:00
71d450249e A snapshot a day keeps the bugs away! 📷🐛 2025-03-24 17:31:05 +00:00
3d6ca78e15 A snapshot a day keeps the bugs away! 📷🐛 2025-03-24 17:21:07 +00:00
4d7d4aa8e0 A snapshot a day keeps the bugs away! 📷🐛 2025-03-24 17:11:40 +00:00
e24a608c82 A snapshot a day keeps the bugs away! 📷🐛 2025-03-24 17:01:50 +00:00
dff3a9f1b8 Merge branch 'pierremtb/issue5393-Add-edge-and-segment-selection-in-point-and-click-Helix-flow' into pierremtb/issue5504-Add-edit-flow-for-Revolve 2025-03-24 12:51:33 -04:00
657d99209a Merge branch 'pierremtb/adhoc/update-helix-snaps' into pierremtb/issue5393-Add-edge-and-segment-selection-in-point-and-click-Helix-flow 2025-03-24 12:51:12 -04:00
acf56c5f2b Another one :djkhaled: 2025-03-24 12:46:19 -04:00
3029c40641 A snapshot a day keeps the bugs away! 📷🐛 2025-03-24 16:44:11 +00:00
3255606221 Merge branch 'pierremtb/issue5393-Add-edge-and-segment-selection-in-point-and-click-Helix-flow' into pierremtb/issue5504-Add-edit-flow-for-Revolve 2025-03-24 12:34:03 -04:00
714ea0f0d0 A snapshot a day keeps the bugs away! 📷🐛 2025-03-24 16:26:18 +00:00
b11054d16e A snapshot a day keeps the bugs away! 📷🐛 2025-03-24 16:23:28 +00:00
1de8fb4c21 A snapshot a day keeps the bugs away! 📷🐛 2025-03-24 16:16:46 +00:00
2538f87861 Update 2020 snapshots after helix change 2025-03-24 12:10:04 -04:00
fc7f74249d Update 2020 snapshots after helix change 2025-03-24 12:09:06 -04:00
2475ef784a Remove uneeded return 2025-03-24 12:07:02 -04:00
9e1963a78c Rebase on helix branch 2025-03-24 11:36:00 -04:00
20b52f9d6a Merge branch 'main' into pierremtb/issue5504-Add-edit-flow-for-Revolve 2025-03-24 11:04:57 -04:00
0ee1de43f9 Fix tsc 2025-03-24 10:58:31 -04:00
1ec7e0540b Use displayName: 'CounterClockWise' cause ccw not cutting it 2025-03-24 10:17:45 -04:00
e5e243ef1e Fix up tests after ccw change 2025-03-24 10:13:12 -04:00
0ea2f6f63b Update from main 2025-03-24 10:05:08 -04:00
30df930006 Clean up, add edit steps to three e2e tests 2025-03-23 07:50:16 -04:00
f17760522b A snapshot a day keeps the bugs away! 📷🐛 2025-03-23 11:19:14 +00:00
acd26dbfb6 WIP: Add edit flow for Revolve
Fixes #5504
2025-03-23 07:10:06 -04:00
149f920901 Clean up snapshots 2025-03-20 18:39:09 -04:00
0df9e676b4 Add edge and segment selection in point-and-click Helix flow
Fixes #5393
2025-03-20 18:38:13 -04:00
e2d12321db A snapshot a day keeps the bugs away! 📷🐛 2025-03-20 00:11:47 +00:00
3b58e97644 A snapshot a day keeps the bugs away! 📷🐛 2025-03-20 00:02:10 +00:00
35a1a14ac3 Lint 2025-03-19 19:52:32 -04:00
8f95414700 Update from main 2025-03-19 19:51:55 -04:00
907a6f1dfa Merge branch 'main' into pierremtb/issue5393-Add-edge-and-segment-selection-in-point-and-click-Helix-flow 2025-03-19 17:21:54 -04:00
343e2d591d Add support for sweepEdge and tests 2025-03-19 17:12:49 -04:00
50a648881f A snapshot a day keeps the bugs away! 📷🐛 2025-03-19 17:51:35 +00:00
fb7cbd1fbd Add skip: true for edge helix to be consistent with axis as options 2025-03-19 13:36:57 -04:00
c50c6ef325 A snapshot a day keeps the bugs away! 📷🐛 2025-03-19 17:35:12 +00:00
1ecaba1ace Use updateModelingState in codemod 2025-03-19 13:24:30 -04:00
6f6656fa49 A snapshot a day keeps the bugs away! 📷🐛 2025-03-19 17:18:07 +00:00
7cbc1dd988 Add edge and segment selection in point-and-click Helix flow
Fixes #5393
2025-03-19 13:07:57 -04:00
e9148ca50a A snapshot a day keeps the bugs away! 📷🐛 2025-03-19 15:15:58 +00:00
a8f6263a1c A snapshot a day keeps the bugs away! 📷🐛 2025-03-19 15:05:43 +00:00
5a9762a456 A snapshot a day keeps the bugs away! 📷🐛 2025-03-19 14:55:58 +00:00
262e799a91 A snapshot a day keeps the bugs away! 📷🐛 2025-03-19 14:46:17 +00:00
487e33c000 A snapshot a day keeps the bugs away! 📷🐛 2025-03-19 14:36:03 +00:00
a065bee335 Merge branch 'pierremtb/issue5393-Add-edge-and-segment-selection-in-point-and-click-Helix-flow' of https://github.com/KittyCAD/modeling-app into pierremtb/issue5393-Add-edge-and-segment-selection-in-point-and-click-Helix-flow 2025-03-19 10:25:54 -04:00
d2f784e50a Add utility function for shared code between revolve and helix 2025-03-19 10:25:49 -04:00
dd33bf8ced A snapshot a day keeps the bugs away! 📷🐛 2025-03-19 14:22:45 +00:00
f490b91923 A snapshot a day keeps the bugs away! 📷🐛 2025-03-19 14:11:28 +00:00
dd4923282a A snapshot a day keeps the bugs away! 📷🐛 2025-03-19 14:01:42 +00:00
bb85781c42 A snapshot a day keeps the bugs away! 📷🐛 2025-03-19 13:51:25 +00:00
4df74e87ab A snapshot a day keeps the bugs away! 📷🐛 2025-03-19 13:41:39 +00:00
e77e3e064a A snapshot a day keeps the bugs away! 📷🐛 2025-03-19 13:22:35 +00:00
ea7608ad67 Add edge and segment selection in point-and-click Helix flow
Fixes #5393
2025-03-19 09:13:02 -04:00
195b72e899 A snapshot a day keeps the bugs away! 📷🐛 2025-03-18 18:29:54 +00:00
b675809424 A snapshot a day keeps the bugs away! 📷🐛 2025-03-18 18:10:55 +00:00
75a68efde6 A snapshot a day keeps the bugs away! 📷🐛 2025-03-18 18:01:03 +00:00
968e90f507 A snapshot a day keeps the bugs away! 📷🐛 2025-03-18 17:51:45 +00:00
32b088f9bc Working edge based helix edit 2025-03-18 13:42:29 -04:00
8c5d8fc4cf A snapshot a day keeps the bugs away! 📷🐛 2025-03-18 17:38:37 +00:00
bf5837c249 A snapshot a day keeps the bugs away! 📷🐛 2025-03-18 17:29:16 +00:00
1a97eaa8f5 A snapshot a day keeps the bugs away! 📷🐛 2025-03-18 17:19:39 +00:00
03e4de6099 WIP: Add edge and segment selection in point-and-click Helix flow
Fixes #5393
2025-03-18 13:10:00 -04:00
115 changed files with 51737 additions and 2174 deletions

View File

@ -1,5 +1,6 @@
NODE_ENV=development
DEV=true
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_SITE_BASE_URL=https://dev.zoo.dev
@ -8,3 +9,5 @@ VITE_KC_SKIP_AUTH=false
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!
#VITE_KC_DEV_TOKEN="your token from dev.zoo.dev should go in .env.development.local"
FAIL_ON_CONSOLE_ERRORS=true

10
.envrc
View File

@ -1,3 +1,13 @@
# Load optional shared environment variables
source_up_if_exists
# Load default development environment variables
dotenv .env.development
# Load optional environment variables overrides
dotenv_if_exists .env.development.local
# Load optional testing environment variables
dotenv_if_exists e2e/playwright/playwright-secrets.env
use flake .

View File

@ -20,8 +20,20 @@
"plugin:react-hooks/recommended"
],
"rules": {
"no-array-constructor": "off", // This is wrong; use the @typescript-eslint one instead.
"@typescript-eslint/no-array-constructor": "error",
"@typescript-eslint/no-array-delete": "error",
"@typescript-eslint/no-duplicate-enum-values": "error",
"@typescript-eslint/no-duplicate-type-constituents": "error",
"@typescript-eslint/no-empty-object-type": "error",
"@typescript-eslint/no-floating-promises": "error",
"no-implied-eval": "off", // This is wrong; use the @typescript-eslint one instead.
"@typescript-eslint/no-implied-eval": "error",
"@typescript-eslint/no-misused-promises": "error",
"@typescript-eslint/no-namespace": "error",
"@typescript-eslint/no-unnecessary-type-assertion": "error",
"@typescript-eslint/no-unnecessary-type-constraint": "error",
"no-unused-vars": "off", // This is wrong; use the @typescript-eslint one instead.
"@typescript-eslint/no-unused-vars": ["error", {
"varsIgnorePattern": "^_",
"argsIgnorePattern": "^_",
@ -29,6 +41,7 @@
"vars": "all",
"args": "none"
}],
"@typescript-eslint/prefer-as-const": "warn",
"jsx-a11y/click-events-have-key-events": "off",
"jsx-a11y/no-autofocus": "off",
"jsx-a11y/no-noninteractive-element-interactions": "off",

View File

@ -28,43 +28,57 @@ jobs:
- run: yarn fmt-check
yarn-build-wasm:
runs-on: ubuntu-22.04
# Build the wasm blob once on the fastest runner.
runs-on: runs-on=${{ github.run_id }}/family=i7ie.2xlarge/image=ubuntu22-full-x64
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'yarn'
- run: yarn install
- name: Install dependencies
run: yarn install
- name: Use correct Rust toolchain
shell: bash
run: |
[ -e rust-toolchain.toml ] || cp rust/rust-toolchain.toml ./
- name: Install rust
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
cache: false # Configured below.
- uses: taiki-e/install-action@37bdc826eaedac215f638a96472df572feab0f9b
with:
tool: wasm-pack
- run: yarn build:wasm
yarn-tsc:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'yarn'
- run: yarn install
- run: yarn --cwd ./rust/kcl-language-server --modules-folder node_modules install
- uses: Swatinem/rust-cache@v2
- name: Rust Cache
uses: Swatinem/rust-cache@v2
with:
workspaces: './rust'
- uses: taiki-e/install-action@37bdc826eaedac215f638a96472df572feab0f9b
with:
tool: wasm-pack
- run: yarn build:wasm
- run: yarn tsc
- name: Build Wasm
shell: bash
run: yarn build:wasm
yarn-lint:
runs-on: ubuntu-22.04
- uses: actions/upload-artifact@v4
with:
name: prepared-wasm
path: |
rust/kcl-wasm-lib/pkg/kcl_wasm_lib*
- uses: actions/upload-artifact@v4
with:
name: prepared-ts-rs-bindings
path: |
rust/kcl-lib/bindings/*
yarn-tsc:
runs-on: ubuntu-latest
needs: yarn-build-wasm
steps:
- uses: actions/checkout@v4
@ -73,7 +87,53 @@ jobs:
node-version-file: '.nvmrc'
cache: 'yarn'
- run: yarn install
- run: yarn --cwd ./rust/kcl-language-server --modules-folder node_modules install
- name: Download all artifacts
uses: actions/download-artifact@v4
- name: Copy prepared wasm
run: |
ls -R prepared-wasm
cp prepared-wasm/kcl_wasm_lib_bg.wasm public
mkdir rust/kcl-wasm-lib/pkg
cp prepared-wasm/kcl_wasm_lib* rust/kcl-wasm-lib/pkg
- name: Copy prepared ts-rs bindings
run: |
ls -R prepared-ts-rs-bindings
mkdir rust/kcl-lib/bindings
cp -r prepared-ts-rs-bindings/* rust/kcl-lib/bindings/
- run: yarn tsc
yarn-lint:
runs-on: ubuntu-latest
needs: yarn-build-wasm
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'yarn'
- run: yarn install
- name: Download all artifacts
uses: actions/download-artifact@v4
- name: Copy prepared wasm
run: |
ls -R prepared-wasm
cp prepared-wasm/kcl_wasm_lib_bg.wasm public
mkdir rust/kcl-wasm-lib/pkg
cp prepared-wasm/kcl_wasm_lib* rust/kcl-wasm-lib/pkg
- name: Copy prepared ts-rs bindings
run: |
ls -R prepared-ts-rs-bindings
mkdir rust/kcl-lib/bindings
cp -r prepared-ts-rs-bindings/* rust/kcl-lib/bindings/
- run: yarn lint
python-codespell:
@ -91,6 +151,7 @@ jobs:
yarn-unit-test-kcl-samples:
runs-on: ubuntu-latest
needs: yarn-build-wasm
steps:
- uses: actions/checkout@v4
@ -103,7 +164,22 @@ jobs:
- uses: taiki-e/install-action@37bdc826eaedac215f638a96472df572feab0f9b
with:
tool: wasm-pack
- run: yarn build:wasm
- name: Download all artifacts
uses: actions/download-artifact@v4
- name: Copy prepared wasm
run: |
ls -R prepared-wasm
cp prepared-wasm/kcl_wasm_lib_bg.wasm public
mkdir rust/kcl-wasm-lib/pkg
cp prepared-wasm/kcl_wasm_lib* rust/kcl-wasm-lib/pkg
- name: Copy prepared ts-rs bindings
run: |
ls -R prepared-ts-rs-bindings
mkdir rust/kcl-lib/bindings
cp -r prepared-ts-rs-bindings/* rust/kcl-lib/bindings/
- run: yarn simpleserver:bg
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}
@ -120,6 +196,7 @@ jobs:
yarn-unit-test:
runs-on: ubuntu-latest
needs: yarn-build-wasm
steps:
- uses: actions/checkout@v4
@ -132,7 +209,22 @@ jobs:
- uses: taiki-e/install-action@37bdc826eaedac215f638a96472df572feab0f9b
with:
tool: wasm-pack
- run: yarn build:wasm
- name: Download all artifacts
uses: actions/download-artifact@v4
- name: Copy prepared wasm
run: |
ls -R prepared-wasm
cp prepared-wasm/kcl_wasm_lib_bg.wasm public
mkdir rust/kcl-wasm-lib/pkg
cp prepared-wasm/kcl_wasm_lib* rust/kcl-wasm-lib/pkg
- name: Copy prepared ts-rs bindings
run: |
ls -R prepared-ts-rs-bindings
mkdir rust/kcl-lib/bindings
cp -r prepared-ts-rs-bindings/* rust/kcl-lib/bindings/
- run: yarn simpleserver:bg
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}

View File

@ -38,7 +38,7 @@ jobs:
# Get a new SHA to prevent overwriting the commit status on main
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
git commit --amend --message="[all-e2e] $(git log --max-count=1 --pretty=%B)"
git commit --allow-empty --message="[all-e2e] $(git log --max-count=1 --pretty=%B)"
# Overwrite the branch
git remote set-url origin https://x-access-token:${{ steps.app-token.outputs.token }}@github.com/${{ github.repository }}.git

View File

@ -37,7 +37,7 @@ build-web: public/kcl_wasm_lib_bg.wasm build/index.html
build-desktop: public/kcl_wasm_lib_bg.wasm .vite/build/main.js
public/kcl_wasm_lib_bg.wasm: $(CARGO_SOURCES)$(RUST_SOURCES)
yarn build:wasm
yarn build:wasm:dev
build/index.html: $(REACT_SOURCES) $(TYPESCRIPT_SOURCES) $(VITE_SOURCES)
yarn build:local
@ -99,7 +99,7 @@ test-e2e-web: install build-web ## Run the web e2e tests
.PHONY: test-e2e-desktop
test-e2e-desktop: install build-desktop ## Run the desktop e2e tests
yarn test:playwright:electron --workers=$(E2E_WORKERS) --max-failures=$(E2E_FAILURES) --grep=$(E2E_GREP)
yarn test:playwright:electron --workers=$(E2E_WORKERS) --max-failures=$(E2E_FAILURES) --grep="$(E2E_GREP)"
###############################################################################
# CLEAN

View File

@ -0,0 +1,117 @@
import { test, expect } from './zoo-test'
import fs from 'node:fs/promises'
import path from 'node:path'
test.describe('Point and click for boolean workflows', () => {
// Boolean operations to test
const booleanOperations = [
{
name: 'union',
code: 'union([extrude001, extrude006])',
},
{
name: 'subtract',
code: 'subtract([extrude001], tools = [extrude006])',
},
{
name: 'intersect',
code: 'intersect([extrude001, extrude006])',
},
] as const
for (let i = 0; i < booleanOperations.length; i++) {
const operation = booleanOperations[i]
const operationName = operation.name
const commandName = `Boolean ${
operationName.charAt(0).toUpperCase() + operationName.slice(1)
}`
test(`Create boolean operation -- ${operationName}`, async ({
context,
homePage,
cmdBar,
editor,
toolbar,
scene,
page,
}) => {
const file = await fs.readFile(
path.resolve(
__dirname,
'../../',
'./rust/kcl-lib/e2e/executor/inputs/boolean-setup-with'
),
'utf-8'
)
await context.addInitScript((file) => {
localStorage.setItem('persistCode', file)
}, file)
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
// Test coordinates for selection - these might need adjustment based on actual scene layout
const cylinderPoint = { x: 592, y: 174 }
const secondObjectPoint = { x: 683, y: 273 }
// Create mouse helpers for selecting objects
const [clickFirstObject] = scene.makeMouseHelpers(
cylinderPoint.x,
cylinderPoint.y,
{ steps: 10 }
)
const [clickSecondObject] = scene.makeMouseHelpers(
secondObjectPoint.x,
secondObjectPoint.y,
{ steps: 10 }
)
await test.step(`Test ${operationName} operation`, async () => {
// Click the boolean operation button in the toolbar
await toolbar.selectBoolean(operationName)
// Verify command bar is showing the right command
await expect(cmdBar.page.getByTestId('command-name')).toContainText(
commandName
)
// Select first object in the scene, expect there to be a pixel diff from the selection color change
await clickFirstObject({ pixelDiff: 50 })
// For subtract, we need to proceed to the next step before selecting the second object
if (operationName !== 'subtract') {
// should down shift key to select multiple objects
await page.keyboard.down('Shift')
}
// Select second object
await clickSecondObject({ pixelDiff: 50 })
// Confirm the operation in the command bar
await cmdBar.progressCmdBar()
if (operationName === 'union' || operationName === 'intersect') {
await cmdBar.expectState({
stage: 'review',
headerArguments: {
Solids: '2 paths',
},
commandName,
})
} else if (operationName === 'subtract') {
await cmdBar.expectState({
stage: 'review',
headerArguments: {
Tool: '1 path',
Target: '1 path',
},
commandName,
})
}
await cmdBar.submit()
await editor.expectEditor.toContain(operation.code)
})
})
}
})

View File

@ -181,6 +181,14 @@ export class ToolbarFixture {
).toBeVisible()
await this.page.getByTestId('dropdown-center-rectangle').click()
}
selectBoolean = async (operation: 'union' | 'subtract' | 'intersect') => {
await this.page
.getByRole('button', { name: 'caret down Union: open menu' })
.click()
const operationTestId = `dropdown-boolean-${operation}`
await expect(this.page.getByTestId(operationTestId)).toBeVisible()
await this.page.getByTestId(operationTestId).click()
}
selectCircleThreePoint = async () => {
await this.page

View File

@ -257,6 +257,45 @@ export const isErrorWhitelisted = (exception: Error) => {
project: 'Google Chrome',
foundInSpec: 'e2e/playwright/testing-settings.spec.ts',
},
// TODO: fix this error in the code
{
name: 'TypeError',
message: "Cannot read properties of undefined (reading 'length')",
stack: '',
project: 'Google Chrome',
foundInSpec: '', // many tests are impacted by this error
},
// TODO: fix this error in the code
{
name: 'ReferenceError',
message: '_testUtils is not defined',
stack: '',
project: 'Google Chrome',
foundInSpec: 'e2e/playwright/snapshot-tests.spec.ts',
},
{
name: 'TypeError',
message: 'Failed to fetch',
stack: '',
project: 'Google Chrome',
foundInSpec: 'e2e/playwright/snapshot-tests.spec.ts',
},
// TODO: fix this error in the code
{
name: 'ReferenceError',
message: 'createNewVariableCheckbox is not defined',
stack: '',
project: 'Google Chrome',
foundInSpec: 'e2e/playwright/testing-constraints.spec.ts',
},
{
name: 'Error',
message: 'The "path" argument must be of type string. Received undefined',
stack:
'Error: The "path" argument must be of type string. Received undefined',
project: 'Google Chrome',
foundInSpec: '', // many tests are impacted by this error
},
]
const cleanString = (str: string) => str.replace(/[`"]/g, '')

View File

@ -230,9 +230,9 @@ test.describe('Onboarding tests', () => {
// Override beforeEach test setup
await context.addInitScript(
async ({ settingsKey, settings }) => {
async ({ settingsKey, settings, code }) => {
// Give some initial code, so we can test that it's cleared
localStorage.setItem('persistCode', originalCode)
localStorage.setItem('persistCode', code)
localStorage.setItem(settingsKey, settings)
},
{
@ -240,6 +240,7 @@ test.describe('Onboarding tests', () => {
settings: settingsToToml({
settings: TEST_SETTINGS_ONBOARDING_EXPORT,
}),
code: originalCode,
}
)

View File

@ -1082,8 +1082,8 @@ openSketch = startSketchOn(XY)
}) => {
// One dumb hardcoded screen pixel value
const testPoint = { x: 620, y: 257 }
const expectedOutput = `helix001 = helix( revolutions = 1, angleStart = 360, ccw = false, radius = 5, axis = 'X', length = 5,)`
const expectedLine = `revolutions=1,`
const expectedOutput = `helix001 = helix( axis = 'X', radius = 5, length = 5, revolutions = 1, angleStart = 360, ccw = false,)`
const expectedLine = `axis='X',`
await homePage.goToModelingScene()
@ -1091,17 +1091,16 @@ openSketch = startSketchOn(XY)
await toolbar.helixButton.click()
await cmdBar.expectState({
stage: 'arguments',
currentArgKey: 'axisOrEdge',
currentArgKey: 'mode',
currentArgValue: '',
headerArguments: {
Mode: '',
AngleStart: '',
AxisOrEdge: '',
CounterClockWise: '',
Length: '',
Radius: '',
Revolutions: '',
Radius: '',
CounterClockWise: '',
},
highlightedHeaderArg: 'axisOrEdge',
highlightedHeaderArg: 'mode',
commandName: 'Helix',
})
await cmdBar.progressCmdBar()
@ -1110,7 +1109,19 @@ openSketch = startSketchOn(XY)
await cmdBar.progressCmdBar()
await cmdBar.progressCmdBar()
await cmdBar.progressCmdBar()
await cmdBar.progressCmdBar()
await cmdBar.expectState({
stage: 'review',
headerArguments: {
Mode: 'Axis',
Axis: 'X',
AngleStart: '360',
Revolutions: '1',
Length: '5',
Radius: '5',
CounterClockWise: '',
},
commandName: 'Helix',
})
await cmdBar.progressCmdBar()
})
@ -1134,30 +1145,31 @@ openSketch = startSketchOn(XY)
await cmdBar.expectState({
commandName: 'Helix',
stage: 'arguments',
currentArgKey: 'length',
currentArgValue: initialInput,
currentArgKey: 'CounterClockWise',
currentArgValue: '',
headerArguments: {
AngleStart: '360',
Axis: 'X',
CounterClockWise: '',
Length: initialInput,
Radius: '5',
AngleStart: '360',
Revolutions: '1',
Radius: '5',
Length: initialInput,
CounterClockWise: '',
},
highlightedHeaderArg: 'length',
highlightedHeaderArg: 'CounterClockWise',
})
await page.keyboard.press('Shift+Backspace')
await expect(cmdBar.currentArgumentInput).toBeVisible()
await cmdBar.currentArgumentInput.locator('.cm-content').fill(newInput)
await cmdBar.progressCmdBar()
await cmdBar.expectState({
stage: 'review',
headerArguments: {
AngleStart: '360',
Axis: 'X',
CounterClockWise: '',
Length: newInput,
Radius: '5',
AngleStart: '360',
Revolutions: '1',
Radius: '5',
Length: newInput,
CounterClockWise: '',
},
commandName: 'Helix',
})
@ -1181,14 +1193,14 @@ openSketch = startSketchOn(XY)
{
selectionType: 'segment',
testPoint: { x: 513, y: 221 },
expectedOutput: `helix001 = helix( revolutions = 20, angleStart = 0, ccw = true, radius = 1, axis = seg01, length = 100,)`,
expectedEditedOutput: `helix001 = helix( revolutions = 20, angleStart = 0, ccw = true, radius = 1, axis = seg01, length = 50,)`,
expectedOutput: `helix001 = helix( axis = seg01, radius = 1, revolutions = 20, angleStart = 0, ccw = false,)`,
expectedEditedOutput: `helix001 = helix( axis = seg01, radius = 5, revolutions = 20, angleStart = 0, ccw = false,)`,
},
{
selectionType: 'sweepEdge',
testPoint: { x: 564, y: 364 },
expectedOutput: `helix001 = helix( revolutions = 20, angleStart = 0, ccw = true, radius = 1, axis = getOppositeEdge(seg01), length = 100,)`,
expectedEditedOutput: `helix001 = helix( revolutions = 20, angleStart = 0, ccw = true, radius = 1, axis = getOppositeEdge(seg01), length = 50,)`,
expectedOutput: `helix001 = helix( axis = getOppositeEdge(seg01), radius = 1, revolutions = 20, angleStart = 0, ccw = false,)`,
expectedEditedOutput: `helix001 = helix( axis = getOppositeEdge(seg01), radius = 5, revolutions = 20, angleStart = 0, ccw = false,)`,
},
]
helixCases.map(
@ -1225,17 +1237,16 @@ openSketch = startSketchOn(XY)
await toolbar.helixButton.click()
await cmdBar.expectState({
stage: 'arguments',
currentArgKey: 'axisOrEdge',
currentArgKey: 'mode',
currentArgValue: '',
headerArguments: {
AngleStart: '',
AxisOrEdge: '',
Mode: '',
CounterClockWise: '',
Length: '',
Radius: '',
Revolutions: '',
},
highlightedHeaderArg: 'axisOrEdge',
highlightedHeaderArg: 'mode',
commandName: 'Helix',
})
await cmdBar.selectOption({ name: 'Edge' }).click()
@ -1246,21 +1257,17 @@ openSketch = startSketchOn(XY)
await cmdBar.progressCmdBar()
await page.keyboard.insertText('0')
await cmdBar.progressCmdBar()
await cmdBar.selectOption({ name: 'True' }).click()
await page.keyboard.insertText('1')
await cmdBar.progressCmdBar()
await page.keyboard.insertText('100')
await cmdBar.progressCmdBar()
await cmdBar.expectState({
stage: 'review',
headerArguments: {
AngleStart: '0',
AxisOrEdge: 'Edge',
Mode: 'Edge',
Edge: `1 ${selectionType}`,
CounterClockWise: '',
Length: '100',
Radius: '1',
AngleStart: '0',
Revolutions: '20',
Radius: '1',
CounterClockWise: '',
},
commandName: 'Helix',
})
@ -1280,22 +1287,24 @@ openSketch = startSketchOn(XY)
0
)
await operationButton.dblclick()
const initialInput = '100'
const newInput = '50'
const initialInput = '1'
const newInput = '5'
await cmdBar.expectState({
commandName: 'Helix',
stage: 'arguments',
currentArgKey: 'length',
currentArgValue: initialInput,
currentArgKey: 'CounterClockWise',
currentArgValue: '',
headerArguments: {
AngleStart: '0',
CounterClockWise: '',
Length: initialInput,
Radius: '1',
Revolutions: '20',
Radius: initialInput,
CounterClockWise: '',
},
highlightedHeaderArg: 'length',
highlightedHeaderArg: 'CounterClockWise',
})
await page
.getByRole('button', { name: 'radius', exact: false })
.click()
await expect(cmdBar.currentArgumentInput).toBeVisible()
await cmdBar.currentArgumentInput
.locator('.cm-content')
@ -1305,10 +1314,9 @@ openSketch = startSketchOn(XY)
stage: 'review',
headerArguments: {
AngleStart: '0',
CounterClockWise: '',
Length: newInput,
Radius: '1',
Revolutions: '20',
Radius: newInput,
CounterClockWise: '',
},
commandName: 'Helix',
})
@ -1336,6 +1344,140 @@ openSketch = startSketchOn(XY)
}
)
test('Helix point-and-click on cylinder', async ({
context,
page,
homePage,
scene,
editor,
toolbar,
cmdBar,
}) => {
const initialCode = `sketch001 = startSketchOn(XY)
profile001 = circle(
sketch001,
center = [0, 0],
radius = 100,
tag = $seg01,
)
extrude001 = extrude(profile001, length = 100)
`
await context.addInitScript((initialCode) => {
localStorage.setItem('persistCode', initialCode)
}, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
// One dumb hardcoded screen pixel value
const testPoint = { x: 620, y: 257 }
const [clickOnWall] = scene.makeMouseHelpers(testPoint.x, testPoint.y)
const expectedOutput = `helix001 = helix( cylinder = extrude001, revolutions = 1, angleStart = 360, ccw = false,)`
const expectedLine = `cylinder = extrude001,`
const expectedEditedOutput = `helix001 = helix( cylinder = extrude001, revolutions = 1, angleStart = 360, ccw = true,)`
await test.step(`Go through the command bar flow`, async () => {
await toolbar.helixButton.click()
await cmdBar.expectState({
stage: 'arguments',
currentArgKey: 'mode',
currentArgValue: '',
headerArguments: {
Mode: '',
AngleStart: '',
Revolutions: '',
Radius: '',
CounterClockWise: '',
},
highlightedHeaderArg: 'mode',
commandName: 'Helix',
})
await cmdBar.selectOption({ name: 'Cylinder' }).click()
await cmdBar.expectState({
stage: 'arguments',
currentArgKey: 'cylinder',
currentArgValue: '',
headerArguments: {
Mode: 'Cylinder',
Cylinder: '',
AngleStart: '',
Revolutions: '',
CounterClockWise: '',
},
highlightedHeaderArg: 'cylinder',
commandName: 'Helix',
})
await clickOnWall()
await cmdBar.progressCmdBar()
await cmdBar.progressCmdBar()
await cmdBar.progressCmdBar()
await cmdBar.expectState({
stage: 'review',
headerArguments: {
Mode: 'Cylinder',
Cylinder: '1 face',
AngleStart: '360',
Revolutions: '1',
CounterClockWise: '',
},
commandName: 'Helix',
})
await cmdBar.progressCmdBar()
})
await test.step(`Confirm code is added to the editor, scene has changed`, async () => {
await editor.expectEditor.toContain(expectedOutput)
await editor.expectState({
diagnostics: [],
activeLines: [expectedLine],
highlightedCode: '',
})
})
await test.step(`Edit helix through the feature tree`, async () => {
await editor.closePane()
const operationButton = await toolbar.getFeatureTreeOperation('Helix', 0)
await operationButton.dblclick()
await cmdBar.expectState({
commandName: 'Helix',
stage: 'arguments',
currentArgKey: 'CounterClockWise',
currentArgValue: '',
headerArguments: {
AngleStart: '360',
Revolutions: '1',
CounterClockWise: '',
},
highlightedHeaderArg: 'CounterClockWise',
})
await cmdBar.selectOption({ name: 'True' }).click()
await cmdBar.expectState({
stage: 'review',
headerArguments: {
AngleStart: '360',
Revolutions: '1',
CounterClockWise: 'true',
},
commandName: 'Helix',
})
await cmdBar.progressCmdBar()
await toolbar.closePane('feature-tree')
await toolbar.openPane('code')
await editor.expectEditor.toContain(expectedEditedOutput)
await editor.closePane()
})
await test.step('Delete helix via feature tree selection', async () => {
await toolbar.openPane('feature-tree')
const operationButton = await toolbar.getFeatureTreeOperation('Helix', 0)
await operationButton.click({ button: 'left' })
await page.keyboard.press('Delete')
await toolbar.closePane('feature-tree')
await toolbar.openPane('code')
await editor.expectEditor.not.toContain(expectedEditedOutput)
})
})
const loftPointAndClickCases = [
{ shouldPreselect: true },
{ shouldPreselect: false },
@ -3267,17 +3409,16 @@ sweep001 = sweep(sketch001, path = sketch002)
})
})
test.describe('Revolve point and click workflows', () => {
test('Base case workflow, auto spam continue in command bar', async ({
context,
page,
homePage,
scene,
editor,
toolbar,
cmdBar,
}) => {
const initialCode = `
test('Revolve point-and-click base case workflow with auto spam continue in command bar', async ({
context,
page,
homePage,
scene,
editor,
toolbar,
cmdBar,
}) => {
const initialCode = `
sketch001 = startSketchOn(XZ)
|> startProfileAt([-100.0, 100.0], %)
|> angledLine([0, 200.0], %, $rectangleSegmentA001)
@ -3304,13 +3445,14 @@ segAng(rectangleSegmentA002),
|> close()
`
await context.addInitScript((initialCode) => {
localStorage.setItem('persistCode', initialCode)
}, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await context.addInitScript((initialCode) => {
localStorage.setItem('persistCode', initialCode)
}, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await test.step('Add revolve through the command bar and code selection', async () => {
// select line of code
const codeToSelecton = `segAng(rectangleSegmentA002) - 90,`
// revolve
@ -3320,47 +3462,76 @@ segAng(rectangleSegmentA002),
await cmdBar.progressCmdBar()
await cmdBar.progressCmdBar()
await cmdBar.progressCmdBar()
const newCodeToFind = `revolve001 = revolve(sketch002, angle = 360, axis = 'X')`
expect(editor.expectEditor.toContain(newCodeToFind)).toBeTruthy()
await editor.snapshot({ name: 'revolve-base-add' })
})
test('revolve surface around edge from an extruded solid2d', async ({
context,
page,
homePage,
scene,
editor,
toolbar,
cmdBar,
}) => {
const initialCode = `
sketch001 = startSketchOn(XZ)
|> startProfileAt([-102.57, 101.72], %)
|> angledLine([0, 202.6], %, $rectangleSegmentA001)
|> angledLine([
segAng(rectangleSegmentA001) - 90,
202.6
], %, $rectangleSegmentB001)
|> angledLine([
segAng(rectangleSegmentA001),
-segLen(rectangleSegmentA001)
], %, $rectangleSegmentC001)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
await test.step('Edit flow', async () => {
const newAngle = '90'
await toolbar.openPane('feature-tree')
const operationButton = await toolbar.getFeatureTreeOperation(
'Revolve',
0
)
await operationButton.dblclick({ button: 'left' })
await cmdBar.expectState({
commandName: 'Revolve',
currentArgKey: 'angle',
currentArgValue: '360',
headerArguments: {
Angle: '360',
},
highlightedHeaderArg: 'angle',
stage: 'arguments',
})
await page.keyboard.insertText(newAngle)
await cmdBar.progressCmdBar()
await cmdBar.expectState({
stage: 'review',
headerArguments: {
Angle: newAngle,
},
commandName: 'Revolve',
})
await cmdBar.progressCmdBar()
await toolbar.closePane('feature-tree')
await editor.snapshot({ name: 'revolve-base-edit' })
})
})
test('Revolve point-and-click surface around edge from an extruded solid2d', async ({
context,
page,
homePage,
scene,
editor,
toolbar,
cmdBar,
}) => {
const initialCode = `sketch001 = startSketchOn(XZ)
|> startProfileAt([-102.57, 101.72], %)
|> angledLine([0, 202.6], %, $rectangleSegmentA001)
|> angledLine([
segAng(rectangleSegmentA001) - 90,
202.6
], %, $rectangleSegmentB001)
|> angledLine([
segAng(rectangleSegmentA001),
-segLen(rectangleSegmentA001)
], %, $rectangleSegmentC001)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
extrude001 = extrude(sketch001, length = 50)
sketch002 = startSketchOn(extrude001, rectangleSegmentA001)
|> circle(
center = [-11.34, 10.0],
radius = 8.69
)
|> circle(center = [-11.34, 10.0], radius = 8.69)
`
await context.addInitScript((initialCode) => {
localStorage.setItem('persistCode', initialCode)
}, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await context.addInitScript((initialCode) => {
localStorage.setItem('persistCode', initialCode)
}, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await test.step('Add through the command bar and code selection', async () => {
// select line of code
const codeToSelecton = `center = [-11.34, 10.0]`
// revolve
@ -3370,61 +3541,118 @@ radius = 8.69
const lineCodeToSelection = `|> angledLine([0, 202.6], %, $rectangleSegmentA001)`
await page.getByText(lineCodeToSelection).click()
await cmdBar.progressCmdBar()
const newCodeToFind = `revolve001 = revolve(sketch002, angle = 360, axis = getOppositeEdge(rectangleSegmentA001)) `
expect(editor.expectEditor.toContain(newCodeToFind)).toBeTruthy()
await cmdBar.progressCmdBar()
await cmdBar.progressCmdBar()
await editor.snapshot({ name: 'revolve-solid-edge-add' })
})
test('revolve sketch circle around line segment from startProfileAt sketch', async ({
context,
page,
homePage,
scene,
editor,
toolbar,
cmdBar,
}) => {
const initialCode = `
sketch002 = startSketchOn(XY)
|> startProfileAt([-2.02, 1.79], %)
|> xLine(length = 2.6)
sketch001 = startSketchOn('-XY')
|> startProfileAt([-0.48, 1.25], %)
|> angledLine([0, 2.38], %, $rectangleSegmentA001)
|> angledLine([segAng(rectangleSegmentA001) - 90, 2.4], %, $rectangleSegmentB001)
|> angledLine([
segAng(rectangleSegmentA001),
-segLen(rectangleSegmentA001)
], %, $rectangleSegmentC001)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
extrude001 = extrude(sketch001, length = 5)
sketch003 = startSketchOn(extrude001, 'START')
|> circle(
center = [-0.69, 0.56],
radius = 0.28
)
await test.step('Edit flow', async () => {
const newAngle = '180'
await toolbar.openPane('feature-tree')
const operationButton = await toolbar.getFeatureTreeOperation('Revolve', 0)
await operationButton.dblclick({ button: 'left' })
await cmdBar.expectState({
commandName: 'Revolve',
currentArgKey: 'angle',
currentArgValue: '360',
headerArguments: {
Angle: '360',
},
highlightedHeaderArg: 'angle',
stage: 'arguments',
})
await page.keyboard.insertText(newAngle)
await cmdBar.progressCmdBar()
await cmdBar.expectState({
stage: 'review',
headerArguments: {
Angle: newAngle,
},
commandName: 'Revolve',
})
await cmdBar.progressCmdBar()
await toolbar.closePane('feature-tree')
await editor.snapshot({ name: 'revolve-solid-edge-edit' })
})
})
test('Revolve point-and-click sketch circle around line segment from startProfileAt sketch', async ({
context,
page,
homePage,
scene,
editor,
toolbar,
cmdBar,
}) => {
const initialCode = `sketch002 = startSketchOn(XY)
|> startProfileAt([-2.02, 1.79], %)
|> xLine(length = 2.6)
sketch001 = startSketchOn(-XY)
|> startProfileAt([-0.48, 1.25], %)
|> angledLine([0, 2.38], %, $rectangleSegmentA001)
|> angledLine([segAng(rectangleSegmentA001) - 90, 2.4], %, $rectangleSegmentB001)
|> angledLine([
segAng(rectangleSegmentA001),
-segLen(rectangleSegmentA001)
], %, $rectangleSegmentC001)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
extrude001 = extrude(sketch001, length = 5)
sketch003 = startSketchOn(extrude001, 'START')
|> circle(center = [-0.69, 0.56], radius = 0.28)
`
await context.addInitScript((initialCode) => {
localStorage.setItem('persistCode', initialCode)
}, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await context.addInitScript((initialCode) => {
localStorage.setItem('persistCode', initialCode)
}, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
// select line of code
const codeToSelecton = `center = [-0.69, 0.56]`
// revolve
await page.getByText(codeToSelecton).click()
await toolbar.revolveButton.click()
await page.getByText('Edge', { exact: true }).click()
const lineCodeToSelection = `|> xLine(length = 2.6)`
await page.getByText(lineCodeToSelection).click()
await cmdBar.progressCmdBar()
// select line of code
const codeToSelecton = `center = [-0.69, 0.56]`
// revolve
await page.getByText(codeToSelecton).click()
await toolbar.revolveButton.click()
await page.getByText('Edge', { exact: true }).click()
const lineCodeToSelection = `|> xLine(length = 2.6)`
await page.getByText(lineCodeToSelection).click()
await cmdBar.progressCmdBar()
await cmdBar.progressCmdBar()
await cmdBar.progressCmdBar()
const newCodeToFind = `revolve001 = revolve(sketch003, angle = 360, axis = seg01)`
expect(editor.expectEditor.toContain(newCodeToFind)).toBeTruthy()
const newCodeToFind = `revolve001 = revolve(sketch003, angle = 360, axis = seg01)`
expect(editor.expectEditor.toContain(newCodeToFind)).toBeTruthy()
// Edit flow
const newAngle = '270'
await toolbar.openPane('feature-tree')
const operationButton = await toolbar.getFeatureTreeOperation('Revolve', 0)
await operationButton.dblclick({ button: 'left' })
await cmdBar.expectState({
commandName: 'Revolve',
currentArgKey: 'angle',
currentArgValue: '360',
headerArguments: {
Angle: '360',
},
highlightedHeaderArg: 'angle',
stage: 'arguments',
})
await page.keyboard.insertText(newAngle)
await cmdBar.progressCmdBar()
await cmdBar.expectState({
stage: 'review',
headerArguments: {
Angle: newAngle,
},
commandName: 'Revolve',
})
await cmdBar.progressCmdBar()
await toolbar.closePane('feature-tree')
await editor.expectEditor.toContain(
newCodeToFind.replace('angle = 360', 'angle = ' + newAngle)
)
})
test(`Set appearance`, async ({

View File

@ -0,0 +1 @@
sketch001 = startSketchOn(XZ) |> startProfileAt([-100.0, 100.0], %) |> angledLine([0, 200.0], %, $rectangleSegmentA001) |> angledLine([segAng(rectangleSegmentA001) - 90, 200], %, $rectangleSegmentB001) |> angledLine([ segAng(rectangleSegmentA001), -segLen(rectangleSegmentA001) ], %, $rectangleSegmentC001) |> line(endAbsolute = [profileStartX(%), profileStartY(%)]) |> close()extrude001 = extrude(sketch001, length = 200)sketch002 = startSketchOn(extrude001, rectangleSegmentA001) |> startProfileAt([-66.77, 84.81], %) |> angledLine([180, 27.08], %, $rectangleSegmentA002) |> angledLine([ segAng(rectangleSegmentA002) - 90, 27.8 ], %, $rectangleSegmentB002) |> angledLine([ segAng(rectangleSegmentA002), -segLen(rectangleSegmentA002) ], %, $rectangleSegmentC002) |> line(endAbsolute = [profileStartX(%), profileStartY(%)]) |> close()revolve001 = revolve(sketch002, angle = 360, axis = 'X')

View File

@ -0,0 +1 @@
sketch001 = startSketchOn(XZ) |> startProfileAt([-100.0, 100.0], %) |> angledLine([0, 200.0], %, $rectangleSegmentA001) |> angledLine([segAng(rectangleSegmentA001) - 90, 200], %, $rectangleSegmentB001) |> angledLine([ segAng(rectangleSegmentA001), -segLen(rectangleSegmentA001) ], %, $rectangleSegmentC001) |> line(endAbsolute = [profileStartX(%), profileStartY(%)]) |> close()extrude001 = extrude(sketch001, length = 200)sketch002 = startSketchOn(extrude001, rectangleSegmentA001) |> startProfileAt([-66.77, 84.81], %) |> angledLine([180, 27.08], %, $rectangleSegmentA002) |> angledLine([ segAng(rectangleSegmentA002) - 90, 27.8 ], %, $rectangleSegmentB002) |> angledLine([ segAng(rectangleSegmentA002), -segLen(rectangleSegmentA002) ], %, $rectangleSegmentC002) |> line(endAbsolute = [profileStartX(%), profileStartY(%)]) |> close()revolve001 = revolve(sketch002, angle = 360, axis = 'X')

View File

@ -0,0 +1 @@
sketch001 = startSketchOn(XZ) |> startProfileAt([-102.57, 101.72], %) |> angledLine([0, 202.6], %, $rectangleSegmentA001) |> angledLine([ segAng(rectangleSegmentA001) - 90, 202.6 ], %, $rectangleSegmentB001) |> angledLine([ segAng(rectangleSegmentA001), -segLen(rectangleSegmentA001) ], %, $rectangleSegmentC001) |> line(endAbsolute = [profileStartX(%), profileStartY(%)]) |> close()extrude001 = extrude(sketch001, length = 50)sketch002 = startSketchOn(extrude001, rectangleSegmentA001) |> circle(center = [-11.34, 10.0], radius = 8.69)revolve001 = revolve(sketch002, angle = 360, axis = rectangleSegmentA001)

View File

@ -0,0 +1 @@
sketch001 = startSketchOn(XZ) |> startProfileAt([-102.57, 101.72], %) |> angledLine([0, 202.6], %, $rectangleSegmentA001) |> angledLine([ segAng(rectangleSegmentA001) - 90, 202.6 ], %, $rectangleSegmentB001) |> angledLine([ segAng(rectangleSegmentA001), -segLen(rectangleSegmentA001) ], %, $rectangleSegmentC001) |> line(endAbsolute = [profileStartX(%), profileStartY(%)]) |> close()extrude001 = extrude(sketch001, length = 50)sketch002 = startSketchOn(extrude001, rectangleSegmentA001) |> circle(center = [-11.34, 10.0], radius = 8.69)revolve001 = revolve(sketch002, angle = 360, axis = rectangleSegmentA001)

View File

@ -473,6 +473,9 @@ test.describe('Can export from electron app', () => {
if (!tronApp) {
fail()
}
if (runningOnWindows()) {
test.fixme(orRunWhenFullSuiteEnabled())
}
await context.folderSetupFn(async (dir) => {
const bracketDir = path.join(dir, 'bracket')

View File

@ -778,6 +778,19 @@ plane002 = offsetPlane(XZ, offset = -2 * x)`
await editor.expectEditor.not.toContain(`plane002`)
})
})
test.fail(
'Console errors cause tests to fail',
async ({ page, homePage }) => {
const u = await getUtils(page)
await homePage.goToModelingScene()
await u.openAndClearDebugPanel()
await page.getByTestId('custom-cmd-input').fill('foobar')
await page.getByTestId('custom-cmd-send-button').scrollIntoViewIfNeeded()
await page.getByTestId('custom-cmd-send-button').click()
}
)
})
async function clickExportButton(page: Page) {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 72 KiB

View File

@ -935,47 +935,39 @@ export async function setup(
}
function failOnConsoleErrors(page: Page, testInfo?: TestInfo) {
// enabled for chrome for now
if (page.context().browser()?.browserType().name() === 'chromium') {
// No idea wtf exception is
page.on('pageerror', (exception: any) => {
if (isErrorWhitelisted(exception)) {
return
}
page.on('pageerror', (exception: any) => {
if (isErrorWhitelisted(exception)) {
return
}
// Only disable this environment variable if you want to collect console errors
if (process.env.FAIL_ON_CONSOLE_ERRORS !== 'false') {
// Use expect to prevent page from closing and not cleaning up
expect(`An error was detected in the console: \r\n message:${exception.message} \r\n name:${exception.name} \r\n stack:${exception.stack}
// only set this env var to false if you want to collect console errors
// This can be configured in the GH workflow. This should be set to true by default (we want tests to fail when
// unwhitelisted console errors are detected).
if (process.env.FAIL_ON_CONSOLE_ERRORS === 'true') {
// Fail when running on CI and FAIL_ON_CONSOLE_ERRORS is set
// use expect to prevent page from closing and not cleaning up
expect(`An error was detected in the console: \r\n message:${exception.message} \r\n name:${exception.name} \r\n stack:${exception.stack}
*Either fix the console error or add it to the whitelist defined in ./lib/console-error-whitelist.ts (if the error can be safely ignored)
`).toEqual('Console error detected')
} else {
// the (test-results/exceptions.txt) file will be uploaded as part of an upload artifact in GH
fsp
.appendFile(
'./test-results/exceptions.txt',
[
'~~~',
`triggered_by_test:${
testInfo?.file + ' ' + (testInfo?.title || ' ')
}`,
`name:${exception.name}`,
`message:${exception.message}`,
`stack:${exception.stack}`,
`project:${testInfo?.project.name}`,
'~~~',
].join('\n')
)
.catch((err) => {
console.error(err)
})
}
})
}
*Either fix the console error or add it to the whitelist defined in ./lib/console-error-whitelist.ts (if the error can be safely ignored)
`).toEqual('Console error detected')
} else {
// Add errors to `test-results/exceptions.txt` as a test artifact
fsp
.appendFile(
'./test-results/exceptions.txt',
[
'~~~',
`triggered_by_test:${
testInfo?.file + ' ' + (testInfo?.title || ' ')
}`,
`name:${exception.name}`,
`message:${exception.message}`,
`stack:${exception.stack}`,
`project:${testInfo?.project.name}`,
'~~~',
].join('\n')
)
.catch((err) => {
console.error(err)
})
}
})
}
export async function isOutOfViewInScrollContainer(
element: Locator,

View File

@ -94,9 +94,11 @@
"fetch:wasm": "./scripts/get-latest-wasm-bundle.sh",
"fetch:wasm:windows": "./scripts/get-latest-wasm-bundle.ps1",
"fetch:samples": "rm -rf public/kcl-samples* && curl -L -o public/kcl-samples.zip https://github.com/KittyCAD/kcl-samples/archive/refs/heads/achalmers/kw-args-xylineto.zip && unzip -o public/kcl-samples.zip -d public && mv public/kcl-samples-* public/kcl-samples",
"build:wasm-dev": "yarn wasm-prep && (cd rust && wasm-pack build kcl-wasm-lib --dev --target web --out-dir pkg && cargo test -p kcl-lib export_bindings) && yarn isomorphic-copy-wasm && yarn fmt:generated",
"build:wasm": "./scripts/build-wasm.sh",
"build:wasm:windows": "./scripts/build-wasm.ps1",
"build:wasm-dev": "yarn build:wasm:dev",
"build:wasm:dev": "./scripts/build-wasm-dev.sh",
"build:wasm:dev:windows": "./scripts/build-wasm-dev.ps1",
"remove-importmeta": "sed -i 's/import.meta.url/window.location.origin/g' \"./rust/kcl-wasm-lib/pkg/kcl_wasm_lib.js\"; sed -i '' 's/import.meta.url/window.location.origin/g' \"./rust/kcl-wasm-lib/pkg/kcl_wasm_lib.js\" || echo \"sed for both mac and linux\"",
"lint-fix": "eslint --fix --ext .ts --ext .tsx src e2e packages/codemirror-lsp-client/src rust/kcl-language-server/client/src",
"lint": "eslint --max-warnings 0 --ext .ts --ext .tsx src e2e packages/codemirror-lsp-client/src rust/kcl-language-server/client/src",

View File

@ -90,7 +90,7 @@ export default class StreamDemuxer extends Queue<Uint8Array> {
}
add(bytes: Uint8Array): void {
const message = Codec.decode(bytes) as vsrpc.Message
const message = Codec.decode<vsrpc.Message>(bytes)
if (this.trace) {
Tracer.server(message)
}

View File

@ -41,6 +41,8 @@ When you submit a PR to add or modify KCL samples, images and STEP files will be
[![cycloidal-gear](screenshots/cycloidal-gear.png)](cycloidal-gear/main.kcl)
#### [dodecahedron](dodecahedron/main.kcl) ([screenshot](screenshots/dodecahedron.png))
[![dodecahedron](screenshots/dodecahedron.png)](dodecahedron/main.kcl)
#### [dual-basin-utility-sink](dual-basin-utility-sink/main.kcl) ([screenshot](screenshots/dual-basin-utility-sink.png))
[![dual-basin-utility-sink](screenshots/dual-basin-utility-sink.png)](dual-basin-utility-sink/main.kcl)
#### [enclosure](enclosure/main.kcl) ([screenshot](screenshots/enclosure.png))
[![enclosure](screenshots/enclosure.png)](enclosure/main.kcl)
#### [exhaust-manifold](exhaust-manifold/main.kcl) ([screenshot](screenshots/exhaust-manifold.png))
@ -75,6 +77,8 @@ When you submit a PR to add or modify KCL samples, images and STEP files will be
[![kitt](screenshots/kitt.png)](kitt/main.kcl)
#### [lego](lego/main.kcl) ([screenshot](screenshots/lego.png))
[![lego](screenshots/lego.png)](lego/main.kcl)
#### [makeup-mirror](makeup-mirror/main.kcl) ([screenshot](screenshots/makeup-mirror.png))
[![makeup-mirror](screenshots/makeup-mirror.png)](makeup-mirror/main.kcl)
#### [mounting-plate](mounting-plate/main.kcl) ([screenshot](screenshots/mounting-plate.png))
[![mounting-plate](screenshots/mounting-plate.png)](mounting-plate/main.kcl)
#### [multi-axis-robot](multi-axis-robot/main.kcl) ([screenshot](screenshots/multi-axis-robot.png))

View File

@ -0,0 +1,200 @@
// Dual-Basin Utility Sink
// A stainless steel sink unit with dual rectangular basins and six under-counter storage compartments.
@settings(defaultLengthUnit = mm)
// globals
tableHeight = 850
tableWidth = 3400
tableDepth = 400
profileThickness = 13
metalThickness = 2
blockCount = 3
blockWidth = (tableWidth-profileThickness) / 3
blockHeight = tableHeight - metalThickness - 0.5
blockDepth = tableDepth - profileThickness
blockSubdivisionCount = 2
blockSubdivisionWidth = blockWidth / blockSubdivisionCount
// Geometry
floorPlane = startSketchOn(XY)
// legs
legHeight = blockHeight - profileThickness
legCount = blockCount + 1
legBody = startProfileAt([0, 0], floorPlane)
|> yLine(length=profileThickness)
|> xLine(length=profileThickness)
|> yLine(length=-profileThickness)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
|> patternLinear2d(axis = [1, 0], instances = legCount, distance = blockWidth)
|> patternLinear2d(axis = [0, 1], instances = 2, distance = blockDepth)
|> extrude(length = legHeight)
// lower belt
lowerBeltHeightAboveTheFloor = 150
lowerBeltLengthX = blockWidth - profileThickness
lowerBeltPlane = startSketchOn(offsetPlane(XY, offset = lowerBeltHeightAboveTheFloor))
lowerBeltBodyX = startProfileAt([profileThickness, 0], lowerBeltPlane)
|> yLine(length=profileThickness)
|> xLine(length=lowerBeltLengthX)
|> yLine(length=-profileThickness)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
|> patternLinear2d(axis = [1, 0], instances = blockCount, distance = blockWidth)
|> patternLinear2d(axis = [0, 1], instances = 2, distance = blockDepth)
|> extrude(length = profileThickness)
lowerBeltLengthY = blockDepth - profileThickness
lowerBeltBodyY = startProfileAt([0, profileThickness], lowerBeltPlane)
|> yLine(length=lowerBeltLengthY)
|> xLine(length=profileThickness)
|> yLine(length=-lowerBeltLengthY)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
|> patternLinear2d(axis = [1, 0], instances = 2, distance = tableWidth-profileThickness)
|> extrude(length = profileThickness)
// pillars
pillarHeightAboveTheFloor = lowerBeltHeightAboveTheFloor + profileThickness
pillarPlane = startSketchOn(offsetPlane(XY, offset = pillarHeightAboveTheFloor))
pillarTotalHeight = blockHeight - profileThickness - pillarHeightAboveTheFloor
pillarBody = startProfileAt([blockSubdivisionWidth, 0], pillarPlane)
|> yLine(length=profileThickness)
|> xLine(length=profileThickness)
|> yLine(length=-profileThickness)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
|> patternLinear2d(axis = [1, 0], instances = blockCount, distance = blockWidth)
|> patternLinear2d(axis = [0, 1], instances = 2, distance = blockDepth)
|> extrude(length = pillarTotalHeight)
// upper belt
upperBeltPlane = startSketchOn(offsetPlane(XY, offset = blockHeight))
upperBeltBodyX = startProfileAt([0, 0], upperBeltPlane)
|> yLine(length=profileThickness)
|> xLine(length=tableWidth)
|> yLine(length=-profileThickness)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
|> patternLinear2d(axis = [0, 1], instances = 2, distance = blockDepth)
|> extrude(length = -profileThickness)
upperBeltLengthY = blockDepth - profileThickness
upperBeltBodyY = startProfileAt([0, profileThickness], upperBeltPlane)
|> yLine(length=upperBeltLengthY)
|> xLine(length=profileThickness)
|> yLine(length=-upperBeltLengthY)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
|> patternLinear2d(axis = [1, 0], instances = 2, distance = tableWidth-profileThickness)
|> extrude(length = -profileThickness)
// sink
tableTopPlane = startSketchOn(offsetPlane(XY, offset = tableHeight))
tableTopBody = startProfileAt([0, 0], tableTopPlane)
|> yLine(length=tableDepth)
|> xLine(length=tableWidth)
|> yLine(length=-tableDepth)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
|> extrude(length = -metalThickness)
sinkCount = 2
sinkWidth = 1000
sinkLength = 250
sinkDepth = 200
sinkOffsetFront = 40
sinkOffsetLeft = 350
sinkSpacing = tableWidth - sinkWidth - sinkOffsetLeft*2
sinkPlaneOutside = startSketchOn(tableTopBody, 'START')
sinkBodyOutside = startProfileAt([-sinkOffsetLeft, sinkOffsetFront], sinkPlaneOutside)
|> yLine(length=sinkLength)
|> xLine(length=-sinkWidth)
|> yLine(length=-sinkLength)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
|> patternLinear2d(axis = [-1, 0], instances = sinkCount, distance = sinkSpacing)
|> extrude(length = sinkDepth)
sinkPlaneInside = startSketchOn(tableTopBody, 'END')
sinkBodyInside = startProfileAt([sinkOffsetLeft+metalThickness, sinkOffsetFront+metalThickness], sinkPlaneInside)
|> yLine(length=sinkLength-metalThickness*2)
|> xLine(length=sinkWidth-metalThickness*2)
|> yLine(length=-sinkLength+metalThickness*2)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
|> patternLinear2d(axis = [1, 0], instances = sinkCount, distance = sinkSpacing)
|> extrude(length = -sinkDepth)
// door panels
doorGap = 2
doorWidth = blockSubdivisionWidth - profileThickness - doorGap*2
doorStart = profileThickness+doorGap
doorHeightAboveTheFloor = pillarHeightAboveTheFloor + doorGap
doorHeight = blockHeight - doorHeightAboveTheFloor - profileThickness - doorGap
doorCount = blockCount * blockSubdivisionCount
doorPlane = startSketchOn(offsetPlane(XY, offset = doorHeightAboveTheFloor))
doorBody = startProfileAt([doorStart, 0], doorPlane)
|> yLine(length=profileThickness)
|> xLine(length=doorWidth)
|> yLine(length=-profileThickness)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
|> patternLinear2d(axis = [1, 0], instances = doorCount, distance = blockSubdivisionWidth)
|> extrude(length = doorHeight)
// side panels
panelWidth = blockDepth - profileThickness - doorGap*2
panelCount = doorCount + 1
panelSpacing = tableWidth - profileThickness
panelBody = startProfileAt([0, doorStart], doorPlane)
|> yLine(length=panelWidth)
|> xLine(length=profileThickness)
|> yLine(length=-panelWidth)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
|> patternLinear2d(axis = [1, 0], instances = 2, distance = panelSpacing)
|> extrude(length = doorHeight)
// handle
handleDepth = 40
handleWidth = 120
handleFillet = 20
handleHeightAboveTheFloor = 780
handleOffset = doorStart + doorWidth / 2 - (handleWidth / 2)
handleLengthSegmentA = handleDepth - handleFillet
handleLengthSegmentB = handleWidth - (handleFillet * 2)
handlePlane = startSketchOn(offsetPlane(XY, offset = handleHeightAboveTheFloor))
handleProfilePath = startProfileAt([0 + handleOffset, 0], handlePlane)
|> yLine(length=-handleLengthSegmentA)
|> tangentialArcTo([
handleFillet + handleOffset,
-handleDepth
], %)
|> xLine(length=handleLengthSegmentB)
|> tangentialArcTo([
handleOffset + handleWidth,
-handleLengthSegmentA
], %)
|> yLine(length=handleLengthSegmentA)
handleSectionPlane = startSketchOn(XZ)
handleProfileSection = circle(
handleSectionPlane,
center = [handleOffset, handleHeightAboveTheFloor],
radius = 2)
handleBody = sweep(handleProfileSection, path = handleProfilePath)
|> patternLinear3d(axis = [1, 0, 0], instances = doorCount, distance = blockSubdivisionWidth)

View File

@ -0,0 +1,75 @@
// Makeup Mirror
// A circular vanity mirror mounted on a swiveling arm with pivot joints, used for personal grooming.
// Settings
@settings(defaultLengthUnit = mm)
// hinge
hingeRadius = 8
hingeHeight = hingeRadius * 3
hingeGap = 0.5
// arm
armLength = 170
armRadius = 5
// mirror
mirrorRadius = 170 / 2
mirrorThickness = 10
archToMirrorGap = 5
archThickness = 1
archRadius = mirrorRadius + archToMirrorGap
// Geometry
// hinge
fn hingeFn(x, y, z) {
hingeBody = startSketchOn(offsetPlane(XY, offset = z))
|> circle(center = [x, y], radius = hingeRadius)
|> extrude(length = hingeHeight)
return hingeBody
}
hingePartA1 = hingeFn(0, 0, 0)
hingePartA2 = hingeFn(0, 0, hingeHeight + hingeGap)
hingePartA3 = hingeFn(0, 0, hingeHeight * 2 + hingeGap * 2)
hingePartB2 = hingeFn(armLength, 0, hingeHeight + hingeGap)
hingePartB3 = hingeFn(armLength, 0, hingeHeight * 2 + hingeGap * 2)
hingePartC2 = hingeFn(armLength, -armLength, hingeHeight * 2 + hingeGap * 2)
hingePartC3 = hingeFn(armLength, -armLength, hingeHeight * 3 + hingeGap * 3)
// arm
fn armFn(plane, offset, altitude) {
armBody = startSketchOn(plane)
|> circle(center = [offset, altitude], radius = armRadius)
|> extrude(length = armLength)
return armBody
}
armPartA = armFn(YZ, 0, hingeHeight * 1.5 + hingeGap)
armPartB = armFn(XZ, armLength, hingeHeight * 2.5 + hingeGap * 2)
// mirror
fn mirrorFn(plane, offsetX, offsetY, altitude, radius, tiefe, gestellR, gestellD) {
armPlane = startSketchOn(offsetPlane(plane, offset = offsetY - (tiefe / 2)))
armBody = circle(armPlane, center = [offsetX, altitude], radius = radius)
|> extrude(length = tiefe)
archBody = startProfileAt([offsetX-gestellR, altitude], armPlane)
|> xLine(length = gestellD)
|> arcTo({
interior = [offsetX, altitude-gestellR],
end = [offsetX+gestellR, altitude]
}, %)
|> xLine(length = gestellD)
|> arcTo({
interior = [offsetX, altitude-gestellR-gestellD],
end = [profileStartX(%), profileStartY(%)]
}, %)
|> close()
|> extrude(length = tiefe)
return armBody
}
mirror = mirrorFn(XZ, armLength, armLength, hingeHeight * 4 + hingeGap * 3 + mirrorRadius+archToMirrorGap+archThickness, mirrorRadius, mirrorThickness, archRadius, archThickness)

View File

@ -62,6 +62,13 @@
"title": "Hollow Dodecahedron",
"description": "A regular dodecahedron or pentagonal dodecahedron is a dodecahedron composed of regular pentagonal faces, three meeting at each vertex. This example shows constructing the individual faces of the dodecahedron and extruding inwards."
},
{
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "dual-basin-utility-sink/main.kcl",
"multipleFiles": false,
"title": "Dual-Basin Utility Sink",
"description": "A stainless steel sink unit with dual rectangular basins and six under-counter storage compartments."
},
{
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "enclosure/main.kcl",
@ -181,6 +188,13 @@
"title": "Lego Brick",
"description": "A standard Lego brick. This is a small, plastic construction block toy that can be interlocked with other blocks to build various structures, models, and figures. There are a lot of hacks used in this code."
},
{
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "makeup-mirror/main.kcl",
"multipleFiles": false,
"title": "Makeup Mirror",
"description": "A circular vanity mirror mounted on a swiveling arm with pivot joints, used for personal grooming."
},
{
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "mounting-plate/main.kcl",

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

View File

@ -43,6 +43,10 @@ overwrite-sim-test test_name:
EXPECTORATE=overwrite TWENTY_TWENTY=overwrite {{cita}} -p kcl-lib --no-quiet -- tests::{{test_name}}::kcl_test_execute
EXPECTORATE=overwrite {{cita}} -p kcl-lib --no-quiet -- simulation_tests::{{test_name}}::test_after_engine
# Regenerate all the simulation test output.
redo-sim-tests:
EXPECTORATE=overwrite TWENTY_TWENTY=overwrite {{cita}} -p kcl-lib --no-quiet -- simulation_tests
test:
export RUST_BRACKTRACE="full" && cargo nextest run --workspace --no-fail-fast

View File

@ -0,0 +1,77 @@
@settings(defaultLengthUnit = mm)
sketch001 = startSketchOn(XZ)
profile001 = circle(sketch001, center = [154.36, 113.92], radius = 41.09)
extrude001 = extrude(profile001, length = 200)
sketch002 = startSketchOn(XY)
profile002 = startProfileAt([72.24, -52.05], sketch002)
|> angledLine([0, 181.26], %, $rectangleSegmentA001)
|> angledLine([
segAng(rectangleSegmentA001) - 90,
21.54
], %)
|> angledLine([
segAng(rectangleSegmentA001),
-segLen(rectangleSegmentA001)
], %, $mySeg)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
extrude002 = extrude(profile002, length = 150)
|> chamfer(
%,
length = 15,
tags = [mySeg],
tag = $seg02,
)
sketch003 = startSketchOn(extrude002, mySeg)
profile003 = startProfileAt([207.36, 126.19], sketch003)
|> angledLine([0, 33.57], %, $rectangleSegmentA002)
|> angledLine([
segAng(rectangleSegmentA002) - 90,
99.11
], %)
|> angledLine([
segAng(rectangleSegmentA002),
-segLen(rectangleSegmentA002)
], %, $seg01)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
extrude003 = extrude(profile003, length = -20)
sketch004 = startSketchOn(extrude003, seg01)
profile004 = startProfileAt([-235.38, 66.16], sketch004)
|> angledLine([0, 24.21], %, $rectangleSegmentA003)
|> angledLine([
segAng(rectangleSegmentA003) - 90,
3.72
], %)
|> angledLine([
segAng(rectangleSegmentA003),
-segLen(rectangleSegmentA003)
], %)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
extrude004 = extrude(profile004, length = 30)
sketch005 = startSketchOn(extrude002, seg02)
profile005 = startProfileAt([-129.93, -59.19], sketch005)
|> xLine(length = 48.79)
|> line(end = [1.33, 11.03])
|> xLine(length = -60.56, tag = $seg03)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
extrude005 = extrude(profile005, length = -10)
sketch006 = startSketchOn(extrude005, seg03)
profile006 = startProfileAt([-95.86, 38.73], sketch006)
|> angledLine([0, 3.48], %, $rectangleSegmentA004)
|> angledLine([
segAng(rectangleSegmentA004) - 90,
3.36
], %)
|> angledLine([
segAng(rectangleSegmentA004),
-segLen(rectangleSegmentA004)
], %)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
extrude006 = extrude(profile006, length = 13)

View File

@ -2379,3 +2379,66 @@ mod rotate_after_fillet {
super::execute(TEST_NAME, true).await
}
}
mod union_cubes {
const TEST_NAME: &str = "union_cubes";
/// Test parsing KCL.
#[test]
fn parse() {
super::parse(TEST_NAME)
}
/// Test that parsing and unparsing KCL produces the original KCL input.
#[tokio::test(flavor = "multi_thread")]
async fn unparse() {
super::unparse(TEST_NAME).await
}
/// Test that KCL is executed correctly.
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_execute() {
super::execute(TEST_NAME, true).await
}
}
mod subtract_cylinder_from_cube {
const TEST_NAME: &str = "subtract_cylinder_from_cube";
/// Test parsing KCL.
#[test]
fn parse() {
super::parse(TEST_NAME)
}
/// Test that parsing and unparsing KCL produces the original KCL input.
#[tokio::test(flavor = "multi_thread")]
async fn unparse() {
super::unparse(TEST_NAME).await
}
/// Test that KCL is executed correctly.
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_execute() {
super::execute(TEST_NAME, true).await
}
}
mod intersect_cubes {
const TEST_NAME: &str = "intersect_cubes";
/// Test parsing KCL.
#[test]
fn parse() {
super::parse(TEST_NAME)
}
/// Test that parsing and unparsing KCL produces the original KCL input.
#[tokio::test(flavor = "multi_thread")]
async fn unparse() {
super::unparse(TEST_NAME).await
}
/// Test that KCL is executed correctly.
#[tokio::test(flavor = "multi_thread")]
async fn kcl_test_execute() {
super::execute(TEST_NAME, true).await
}
}

View File

@ -45,7 +45,7 @@ pub async fn union(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
/// ```
#[stdlib {
name = "union",
feature_tree_operation = false,
feature_tree_operation = true,
keywords = true,
unlabeled_first = true,
deprecated = true,
@ -107,7 +107,7 @@ pub async fn intersect(exec_state: &mut ExecState, args: Args) -> Result<KclValu
/// ```
#[stdlib {
name = "intersect",
feature_tree_operation = false,
feature_tree_operation = true,
keywords = true,
unlabeled_first = true,
deprecated = true,
@ -164,7 +164,7 @@ pub async fn subtract(exec_state: &mut ExecState, args: Args) -> Result<KclValue
/// ```
#[stdlib {
name = "subtract",
feature_tree_operation = false,
feature_tree_operation = true,
keywords = true,
unlabeled_first = true,
deprecated = true,

View File

@ -0,0 +1,554 @@
---
source: kcl-lib/src/simulation_tests.rs
description: Artifact commands intersect_cubes.kcl
---
[
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "edge_lines_visible",
"hidden": false
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "set_scene_units",
"unit": "mm"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "object_visible",
"object_id": "[uuid]",
"hidden": true
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "object_visible",
"object_id": "[uuid]",
"hidden": true
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "make_plane",
"origin": {
"x": 0.0,
"y": 0.0,
"z": 0.0
},
"x_axis": {
"x": 1.0,
"y": 0.0,
"z": 0.0
},
"y_axis": {
"x": 0.0,
"y": 1.0,
"z": 0.0
},
"size": 60.0,
"clobber": false,
"hide": true
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "enable_sketch_mode",
"entity_id": "[uuid]",
"ortho": false,
"animated": false,
"adjust_camera": false,
"planar_normal": {
"x": 0.0,
"y": 0.0,
"z": 1.0
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "start_path"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "move_path_pen",
"path": "[uuid]",
"to": {
"x": -10.0,
"y": -10.0,
"z": 0.0
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "sketch_mode_disable"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "extend_path",
"path": "[uuid]",
"segment": {
"type": "line",
"end": {
"x": 10.0,
"y": -10.0,
"z": 0.0
},
"relative": false
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "extend_path",
"path": "[uuid]",
"segment": {
"type": "line",
"end": {
"x": 10.0,
"y": 10.0,
"z": 0.0
},
"relative": false
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "extend_path",
"path": "[uuid]",
"segment": {
"type": "line",
"end": {
"x": -10.0,
"y": 10.0,
"z": 0.0
},
"relative": false
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "close_path",
"path_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "enable_sketch_mode",
"entity_id": "[uuid]",
"ortho": false,
"animated": false,
"adjust_camera": false,
"planar_normal": {
"x": 0.0,
"y": 0.0,
"z": 1.0
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "extrude",
"target": "[uuid]",
"distance": 10.0,
"faces": null
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "sketch_mode_disable"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "object_bring_to_front",
"object_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_extrusion_face_info",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "make_plane",
"origin": {
"x": 0.0,
"y": 0.0,
"z": 0.0
},
"x_axis": {
"x": 1.0,
"y": 0.0,
"z": 0.0
},
"y_axis": {
"x": 0.0,
"y": 1.0,
"z": 0.0
},
"size": 60.0,
"clobber": false,
"hide": true
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "enable_sketch_mode",
"entity_id": "[uuid]",
"ortho": false,
"animated": false,
"adjust_camera": false,
"planar_normal": {
"x": 0.0,
"y": 0.0,
"z": 1.0
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "start_path"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "move_path_pen",
"path": "[uuid]",
"to": {
"x": -2.0,
"y": -2.0,
"z": 0.0
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "sketch_mode_disable"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "extend_path",
"path": "[uuid]",
"segment": {
"type": "line",
"end": {
"x": 18.0,
"y": -2.0,
"z": 0.0
},
"relative": false
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "extend_path",
"path": "[uuid]",
"segment": {
"type": "line",
"end": {
"x": 18.0,
"y": 18.0,
"z": 0.0
},
"relative": false
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "extend_path",
"path": "[uuid]",
"segment": {
"type": "line",
"end": {
"x": -2.0,
"y": 18.0,
"z": 0.0
},
"relative": false
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "close_path",
"path_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "enable_sketch_mode",
"entity_id": "[uuid]",
"ortho": false,
"animated": false,
"adjust_camera": false,
"planar_normal": {
"x": 0.0,
"y": 0.0,
"z": 1.0
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "extrude",
"target": "[uuid]",
"distance": 10.0,
"faces": null
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "sketch_mode_disable"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "object_bring_to_front",
"object_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_extrusion_face_info",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
}
]

View File

@ -0,0 +1,6 @@
---
source: kcl-lib/src/simulation_tests.rs
description: Artifact graph flowchart intersect_cubes.kcl
extension: md
snapshot_kind: binary
---

View File

@ -0,0 +1,117 @@
```mermaid
flowchart LR
subgraph path2 [Path]
2["Path<br>[52, 103, 0]"]
3["Segment<br>[111, 163, 0]"]
4["Segment<br>[171, 223, 0]"]
5["Segment<br>[231, 283, 0]"]
6["Segment<br>[291, 298, 0]"]
7[Solid2d]
end
subgraph path24 [Path]
24["Path<br>[52, 103, 0]"]
25["Segment<br>[111, 163, 0]"]
26["Segment<br>[171, 223, 0]"]
27["Segment<br>[231, 283, 0]"]
28["Segment<br>[291, 298, 0]"]
29[Solid2d]
end
1["Plane<br>[27, 44, 0]"]
8["Sweep Extrusion<br>[306, 326, 0]"]
9[Wall]
10[Wall]
11[Wall]
12[Wall]
13["Cap Start"]
14["Cap End"]
15["SweepEdge Opposite"]
16["SweepEdge Adjacent"]
17["SweepEdge Opposite"]
18["SweepEdge Adjacent"]
19["SweepEdge Opposite"]
20["SweepEdge Adjacent"]
21["SweepEdge Opposite"]
22["SweepEdge Adjacent"]
23["Plane<br>[27, 44, 0]"]
30["Sweep Extrusion<br>[306, 326, 0]"]
31[Wall]
32[Wall]
33[Wall]
34[Wall]
35["Cap Start"]
36["Cap End"]
37["SweepEdge Opposite"]
38["SweepEdge Adjacent"]
39["SweepEdge Opposite"]
40["SweepEdge Adjacent"]
41["SweepEdge Opposite"]
42["SweepEdge Adjacent"]
43["SweepEdge Opposite"]
44["SweepEdge Adjacent"]
1 --- 2
2 --- 3
2 --- 4
2 --- 5
2 --- 6
2 ---- 8
2 --- 7
3 --- 9
3 --- 15
3 --- 16
4 --- 10
4 --- 17
4 --- 18
5 --- 11
5 --- 19
5 --- 20
6 --- 12
6 --- 21
6 --- 22
8 --- 9
8 --- 10
8 --- 11
8 --- 12
8 --- 13
8 --- 14
8 --- 15
8 --- 16
8 --- 17
8 --- 18
8 --- 19
8 --- 20
8 --- 21
8 --- 22
23 --- 24
24 --- 25
24 --- 26
24 --- 27
24 --- 28
24 ---- 30
24 --- 29
25 --- 31
25 --- 37
25 --- 38
26 --- 32
26 --- 39
26 --- 40
27 --- 33
27 --- 41
27 --- 42
28 --- 34
28 --- 43
28 --- 44
30 --- 31
30 --- 32
30 --- 33
30 --- 34
30 --- 35
30 --- 36
30 --- 37
30 --- 38
30 --- 39
30 --- 40
30 --- 41
30 --- 42
30 --- 43
30 --- 44
```

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,14 @@
fn cube(center) {
return startSketchOn(XY)
|> startProfileAt([center[0] - 10, center[1] - 10], %)
|> line(endAbsolute = [center[0] + 10, center[1] - 10])
|> line(endAbsolute = [center[0] + 10, center[1] + 10])
|> line(endAbsolute = [center[0] - 10, center[1] + 10])
|> close()
|> extrude(length = 10)
}
part001 = cube([0, 0])
part002 = cube([8, 8])
fullPart = intersect([part001, part002])

View File

@ -0,0 +1,158 @@
---
source: kcl-lib/src/simulation_tests.rs
description: Operations executed intersect_cubes.kcl
---
[
{
"type": "UserDefinedFunctionCall",
"name": "cube",
"functionSourceRange": [
7,
328,
0
],
"unlabeledArg": null,
"labeledArgs": {},
"sourceRange": []
},
{
"labeledArgs": {
"data": {
"value": {
"type": "Plane",
"artifact_id": "[uuid]"
},
"sourceRange": []
}
},
"name": "startSketchOn",
"sourceRange": [],
"type": "StdLibCall",
"unlabeledArg": null
},
{
"labeledArgs": {
"length": {
"value": {
"type": "Number",
"value": 10.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"sourceRange": []
}
},
"name": "extrude",
"sourceRange": [],
"type": "StdLibCall",
"unlabeledArg": {
"value": {
"type": "Sketch",
"value": {
"artifactId": "[uuid]"
}
},
"sourceRange": []
}
},
{
"type": "UserDefinedFunctionReturn"
},
{
"type": "UserDefinedFunctionCall",
"name": "cube",
"functionSourceRange": [
7,
328,
0
],
"unlabeledArg": null,
"labeledArgs": {},
"sourceRange": []
},
{
"labeledArgs": {
"data": {
"value": {
"type": "Plane",
"artifact_id": "[uuid]"
},
"sourceRange": []
}
},
"name": "startSketchOn",
"sourceRange": [],
"type": "StdLibCall",
"unlabeledArg": null
},
{
"labeledArgs": {
"length": {
"value": {
"type": "Number",
"value": 10.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"sourceRange": []
}
},
"name": "extrude",
"sourceRange": [],
"type": "StdLibCall",
"unlabeledArg": {
"value": {
"type": "Sketch",
"value": {
"artifactId": "[uuid]"
}
},
"sourceRange": []
}
},
{
"type": "UserDefinedFunctionReturn"
},
{
"labeledArgs": {
"solids": {
"value": {
"type": "Array",
"value": [
{
"type": "Solid",
"value": {
"artifactId": "[uuid]"
}
},
{
"type": "Solid",
"value": {
"artifactId": "[uuid]"
}
}
]
},
"sourceRange": []
}
},
"name": "intersect",
"sourceRange": [],
"type": "StdLibCall",
"unlabeledArg": null
}
]

View File

@ -0,0 +1,543 @@
---
source: kcl-lib/src/simulation_tests.rs
description: Variables in memory after executing intersect_cubes.kcl
---
{
"cube": {
"type": "Function"
},
"fullPart": {
"type": "Solid",
"value": {
"type": "Solid",
"id": "[uuid]",
"artifactId": "[uuid]",
"value": [
{
"faceId": "[uuid]",
"id": "[uuid]",
"sourceRange": [],
"tag": null,
"type": "extrudePlane"
},
{
"faceId": "[uuid]",
"id": "[uuid]",
"sourceRange": [],
"tag": null,
"type": "extrudePlane"
},
{
"faceId": "[uuid]",
"id": "[uuid]",
"sourceRange": [],
"tag": null,
"type": "extrudePlane"
},
{
"faceId": "[uuid]",
"id": "[uuid]",
"sourceRange": [],
"tag": null,
"type": "extrudePlane"
}
],
"sketch": {
"type": "Sketch",
"id": "[uuid]",
"paths": [
{
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
},
"from": [
-10.0,
-10.0
],
"tag": null,
"to": [
10.0,
-10.0
],
"type": "ToPoint",
"units": {
"type": "Mm"
}
},
{
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
},
"from": [
10.0,
-10.0
],
"tag": null,
"to": [
10.0,
10.0
],
"type": "ToPoint",
"units": {
"type": "Mm"
}
},
{
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
},
"from": [
10.0,
10.0
],
"tag": null,
"to": [
-10.0,
10.0
],
"type": "ToPoint",
"units": {
"type": "Mm"
}
},
{
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
},
"from": [
-10.0,
10.0
],
"tag": null,
"to": [
-10.0,
-10.0
],
"type": "ToPoint",
"units": {
"type": "Mm"
}
}
],
"on": {
"type": "plane",
"id": "[uuid]",
"artifactId": "[uuid]",
"value": "XY",
"origin": {
"x": 0.0,
"y": 0.0,
"z": 0.0
},
"xAxis": {
"x": 1.0,
"y": 0.0,
"z": 0.0
},
"yAxis": {
"x": 0.0,
"y": 1.0,
"z": 0.0
},
"zAxis": {
"x": 0.0,
"y": 0.0,
"z": 1.0
},
"units": {
"type": "Mm"
}
},
"start": {
"from": [
-10.0,
-10.0
],
"to": [
-10.0,
-10.0
],
"units": {
"type": "Mm"
},
"tag": null,
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
}
},
"artifactId": "[uuid]",
"originalId": "[uuid]",
"units": {
"type": "Mm"
}
},
"height": 10.0,
"startCapId": "[uuid]",
"endCapId": "[uuid]",
"units": {
"type": "Mm"
}
}
},
"part001": {
"type": "Solid",
"value": {
"type": "Solid",
"id": "[uuid]",
"artifactId": "[uuid]",
"value": [
{
"faceId": "[uuid]",
"id": "[uuid]",
"sourceRange": [],
"tag": null,
"type": "extrudePlane"
},
{
"faceId": "[uuid]",
"id": "[uuid]",
"sourceRange": [],
"tag": null,
"type": "extrudePlane"
},
{
"faceId": "[uuid]",
"id": "[uuid]",
"sourceRange": [],
"tag": null,
"type": "extrudePlane"
},
{
"faceId": "[uuid]",
"id": "[uuid]",
"sourceRange": [],
"tag": null,
"type": "extrudePlane"
}
],
"sketch": {
"type": "Sketch",
"id": "[uuid]",
"paths": [
{
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
},
"from": [
-10.0,
-10.0
],
"tag": null,
"to": [
10.0,
-10.0
],
"type": "ToPoint",
"units": {
"type": "Mm"
}
},
{
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
},
"from": [
10.0,
-10.0
],
"tag": null,
"to": [
10.0,
10.0
],
"type": "ToPoint",
"units": {
"type": "Mm"
}
},
{
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
},
"from": [
10.0,
10.0
],
"tag": null,
"to": [
-10.0,
10.0
],
"type": "ToPoint",
"units": {
"type": "Mm"
}
},
{
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
},
"from": [
-10.0,
10.0
],
"tag": null,
"to": [
-10.0,
-10.0
],
"type": "ToPoint",
"units": {
"type": "Mm"
}
}
],
"on": {
"type": "plane",
"id": "[uuid]",
"artifactId": "[uuid]",
"value": "XY",
"origin": {
"x": 0.0,
"y": 0.0,
"z": 0.0
},
"xAxis": {
"x": 1.0,
"y": 0.0,
"z": 0.0
},
"yAxis": {
"x": 0.0,
"y": 1.0,
"z": 0.0
},
"zAxis": {
"x": 0.0,
"y": 0.0,
"z": 1.0
},
"units": {
"type": "Mm"
}
},
"start": {
"from": [
-10.0,
-10.0
],
"to": [
-10.0,
-10.0
],
"units": {
"type": "Mm"
},
"tag": null,
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
}
},
"artifactId": "[uuid]",
"originalId": "[uuid]",
"units": {
"type": "Mm"
}
},
"height": 10.0,
"startCapId": "[uuid]",
"endCapId": "[uuid]",
"units": {
"type": "Mm"
}
}
},
"part002": {
"type": "Solid",
"value": {
"type": "Solid",
"id": "[uuid]",
"artifactId": "[uuid]",
"value": [
{
"faceId": "[uuid]",
"id": "[uuid]",
"sourceRange": [],
"tag": null,
"type": "extrudePlane"
},
{
"faceId": "[uuid]",
"id": "[uuid]",
"sourceRange": [],
"tag": null,
"type": "extrudePlane"
},
{
"faceId": "[uuid]",
"id": "[uuid]",
"sourceRange": [],
"tag": null,
"type": "extrudePlane"
},
{
"faceId": "[uuid]",
"id": "[uuid]",
"sourceRange": [],
"tag": null,
"type": "extrudePlane"
}
],
"sketch": {
"type": "Sketch",
"id": "[uuid]",
"paths": [
{
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
},
"from": [
-2.0,
-2.0
],
"tag": null,
"to": [
18.0,
-2.0
],
"type": "ToPoint",
"units": {
"type": "Mm"
}
},
{
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
},
"from": [
18.0,
-2.0
],
"tag": null,
"to": [
18.0,
18.0
],
"type": "ToPoint",
"units": {
"type": "Mm"
}
},
{
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
},
"from": [
18.0,
18.0
],
"tag": null,
"to": [
-2.0,
18.0
],
"type": "ToPoint",
"units": {
"type": "Mm"
}
},
{
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
},
"from": [
-2.0,
18.0
],
"tag": null,
"to": [
-2.0,
-2.0
],
"type": "ToPoint",
"units": {
"type": "Mm"
}
}
],
"on": {
"type": "plane",
"id": "[uuid]",
"artifactId": "[uuid]",
"value": "XY",
"origin": {
"x": 0.0,
"y": 0.0,
"z": 0.0
},
"xAxis": {
"x": 1.0,
"y": 0.0,
"z": 0.0
},
"yAxis": {
"x": 0.0,
"y": 1.0,
"z": 0.0
},
"zAxis": {
"x": 0.0,
"y": 0.0,
"z": 1.0
},
"units": {
"type": "Mm"
}
},
"start": {
"from": [
-2.0,
-2.0
],
"to": [
-2.0,
-2.0
],
"units": {
"type": "Mm"
},
"tag": null,
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
}
},
"artifactId": "[uuid]",
"originalId": "[uuid]",
"units": {
"type": "Mm"
}
},
"height": 10.0,
"startCapId": "[uuid]",
"endCapId": "[uuid]",
"units": {
"type": "Mm"
}
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

View File

@ -0,0 +1,18 @@
---
source: kcl-lib/src/simulation_tests.rs
description: Result of unparsing intersect_cubes.kcl
---
fn cube(center) {
return startSketchOn(XY)
|> startProfileAt([center[0] - 10, center[1] - 10], %)
|> line(endAbsolute = [center[0] + 10, center[1] - 10])
|> line(endAbsolute = [center[0] + 10, center[1] + 10])
|> line(endAbsolute = [center[0] - 10, center[1] + 10])
|> close()
|> extrude(length = 10)
}
part001 = cube([0, 0])
part002 = cube([8, 8])
fullPart = intersect([part001, part002])

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,6 @@
---
source: kcl-lib/src/simulation_tests.rs
description: Artifact graph flowchart dual-basin-utility-sink.kcl
extension: md
snapshot_kind: binary
---

View File

@ -0,0 +1,726 @@
```mermaid
flowchart LR
subgraph path2 [Path]
2["Path<br>[647, 681, 0]"]
3["Segment<br>[687, 717, 0]"]
4["Segment<br>[723, 753, 0]"]
5["Segment<br>[759, 790, 0]"]
6["Segment<br>[796, 852, 0]"]
7["Segment<br>[858, 865, 0]"]
8[Solid2d]
end
subgraph path32 [Path]
32["Path<br>[1258, 1311, 0]"]
33["Segment<br>[1317, 1347, 0]"]
34["Segment<br>[1353, 1383, 0]"]
35["Segment<br>[1389, 1420, 0]"]
36["Segment<br>[1426, 1482, 0]"]
37["Segment<br>[1488, 1495, 0]"]
38[Solid2d]
end
subgraph path59 [Path]
59["Path<br>[1760, 1813, 0]"]
60["Segment<br>[1819, 1849, 0]"]
61["Segment<br>[1855, 1885, 0]"]
62["Segment<br>[1891, 1922, 0]"]
63["Segment<br>[1928, 1984, 0]"]
64["Segment<br>[1990, 1997, 0]"]
65[Solid2d]
end
subgraph path83 [Path]
83["Path<br>[2391, 2446, 0]"]
84["Segment<br>[2452, 2482, 0]"]
85["Segment<br>[2488, 2518, 0]"]
86["Segment<br>[2524, 2555, 0]"]
87["Segment<br>[2561, 2617, 0]"]
88["Segment<br>[2623, 2630, 0]"]
89[Solid2d]
end
subgraph path111 [Path]
111["Path<br>[2932, 2970, 0]"]
112["Segment<br>[2976, 3006, 0]"]
113["Segment<br>[3012, 3036, 0]"]
114["Segment<br>[3042, 3073, 0]"]
115["Segment<br>[3079, 3135, 0]"]
116["Segment<br>[3141, 3148, 0]"]
117[Solid2d]
end
subgraph path134 [Path]
134["Path<br>[3331, 3384, 0]"]
135["Segment<br>[3390, 3420, 0]"]
136["Segment<br>[3426, 3456, 0]"]
137["Segment<br>[3462, 3493, 0]"]
138["Segment<br>[3499, 3555, 0]"]
139["Segment<br>[3561, 3568, 0]"]
140[Solid2d]
end
subgraph path158 [Path]
158["Path<br>[3794, 3831, 0]"]
159["Segment<br>[3837, 3861, 0]"]
160["Segment<br>[3867, 3891, 0]"]
161["Segment<br>[3897, 3922, 0]"]
162["Segment<br>[3928, 3984, 0]"]
163["Segment<br>[3990, 3997, 0]"]
164[Solid2d]
end
subgraph path180 [Path]
180["Path<br>[4275, 4343, 0]"]
181["Segment<br>[4349, 4373, 0]"]
182["Segment<br>[4379, 4403, 0]"]
183["Segment<br>[4409, 4434, 0]"]
184["Segment<br>[4440, 4496, 0]"]
185["Segment<br>[4502, 4509, 0]"]
186[Solid2d]
end
subgraph path202 [Path]
202["Path<br>[4698, 4794, 0]"]
203["Segment<br>[4800, 4841, 0]"]
204["Segment<br>[4847, 4887, 0]"]
205["Segment<br>[4893, 4935, 0]"]
206["Segment<br>[4941, 4997, 0]"]
207["Segment<br>[5003, 5010, 0]"]
208[Solid2d]
end
subgraph path225 [Path]
225["Path<br>[5538, 5579, 0]"]
226["Segment<br>[5585, 5615, 0]"]
227["Segment<br>[5621, 5644, 0]"]
228["Segment<br>[5650, 5681, 0]"]
229["Segment<br>[5687, 5743, 0]"]
230["Segment<br>[5749, 5756, 0]"]
231[Solid2d]
end
subgraph path252 [Path]
252["Path<br>[6039, 6080, 0]"]
253["Segment<br>[6086, 6110, 0]"]
254["Segment<br>[6116, 6146, 0]"]
255["Segment<br>[6152, 6177, 0]"]
256["Segment<br>[6183, 6239, 0]"]
257["Segment<br>[6245, 6252, 0]"]
258[Solid2d]
end
subgraph path276 [Path]
276["Path<br>[6731, 6781, 0]"]
277["Segment<br>[6787, 6822, 0]"]
278["Segment<br>[6828, 6912, 0]"]
279["Segment<br>[6918, 6952, 0]"]
280["Segment<br>[6958, 7050, 0]"]
281["Segment<br>[7056, 7090, 0]"]
end
subgraph path283 [Path]
283["Path<br>[7153, 7250, 0]"]
284["Segment<br>[7153, 7250, 0]"]
285[Solid2d]
end
1["Plane<br>[540, 557, 0]"]
9["Sweep Extrusion<br>[1026, 1053, 0]"]
10[Wall]
11[Wall]
12[Wall]
13[Wall]
14["Cap Start"]
15["Cap End"]
16["SweepEdge Opposite"]
17["SweepEdge Adjacent"]
18["SweepEdge Opposite"]
19["SweepEdge Adjacent"]
20["SweepEdge Opposite"]
21["SweepEdge Adjacent"]
22["SweepEdge Opposite"]
23["SweepEdge Adjacent"]
24["Sweep Extrusion<br>[1026, 1053, 0]"]
25["Sweep Extrusion<br>[1026, 1053, 0]"]
26["Sweep Extrusion<br>[1026, 1053, 0]"]
27["Sweep Extrusion<br>[1026, 1053, 0]"]
28["Sweep Extrusion<br>[1026, 1053, 0]"]
29["Sweep Extrusion<br>[1026, 1053, 0]"]
30["Sweep Extrusion<br>[1026, 1053, 0]"]
31["Plane<br>[1185, 1239, 0]"]
39["Sweep Extrusion<br>[1658, 1692, 0]"]
40[Wall]
41[Wall]
42[Wall]
43[Wall]
44["Cap Start"]
45["Cap End"]
46["SweepEdge Opposite"]
47["SweepEdge Adjacent"]
48["SweepEdge Opposite"]
49["SweepEdge Adjacent"]
50["SweepEdge Opposite"]
51["SweepEdge Adjacent"]
52["SweepEdge Opposite"]
53["SweepEdge Adjacent"]
54["Sweep Extrusion<br>[1658, 1692, 0]"]
55["Sweep Extrusion<br>[1658, 1692, 0]"]
56["Sweep Extrusion<br>[1658, 1692, 0]"]
57["Sweep Extrusion<br>[1658, 1692, 0]"]
58["Sweep Extrusion<br>[1658, 1692, 0]"]
66["Sweep Extrusion<br>[2094, 2128, 0]"]
67[Wall]
68[Wall]
69[Wall]
70[Wall]
71["Cap Start"]
72["Cap End"]
73["SweepEdge Opposite"]
74["SweepEdge Adjacent"]
75["SweepEdge Opposite"]
76["SweepEdge Adjacent"]
77["SweepEdge Opposite"]
78["SweepEdge Adjacent"]
79["SweepEdge Opposite"]
80["SweepEdge Adjacent"]
81["Sweep Extrusion<br>[2094, 2128, 0]"]
82["Plane<br>[2245, 2296, 0]"]
90["Sweep Extrusion<br>[2793, 2828, 0]"]
91[Wall]
92[Wall]
93[Wall]
94[Wall]
95["Cap Start"]
96["Cap End"]
97["SweepEdge Opposite"]
98["SweepEdge Adjacent"]
99["SweepEdge Opposite"]
100["SweepEdge Adjacent"]
101["SweepEdge Opposite"]
102["SweepEdge Adjacent"]
103["SweepEdge Opposite"]
104["SweepEdge Adjacent"]
105["Sweep Extrusion<br>[2793, 2828, 0]"]
106["Sweep Extrusion<br>[2793, 2828, 0]"]
107["Sweep Extrusion<br>[2793, 2828, 0]"]
108["Sweep Extrusion<br>[2793, 2828, 0]"]
109["Sweep Extrusion<br>[2793, 2828, 0]"]
110["Plane<br>[2875, 2912, 0]"]
118["Sweep Extrusion<br>[3228, 3263, 0]"]
119[Wall]
120[Wall]
121[Wall]
122[Wall]
123["Cap Start"]
124["Cap End"]
125["SweepEdge Opposite"]
126["SweepEdge Adjacent"]
127["SweepEdge Opposite"]
128["SweepEdge Adjacent"]
129["SweepEdge Opposite"]
130["SweepEdge Adjacent"]
131["SweepEdge Opposite"]
132["SweepEdge Adjacent"]
133["Sweep Extrusion<br>[3228, 3263, 0]"]
141["Sweep Extrusion<br>[3665, 3700, 0]"]
142[Wall]
143[Wall]
144[Wall]
145[Wall]
146["Cap Start"]
147["Cap End"]
148["SweepEdge Opposite"]
149["SweepEdge Adjacent"]
150["SweepEdge Opposite"]
151["SweepEdge Adjacent"]
152["SweepEdge Opposite"]
153["SweepEdge Adjacent"]
154["SweepEdge Opposite"]
155["SweepEdge Adjacent"]
156["Sweep Extrusion<br>[3665, 3700, 0]"]
157["Plane<br>[3740, 3777, 0]"]
165["Sweep Extrusion<br>[4003, 4036, 0]"]
166[Wall]
167[Wall]
168[Wall]
169[Wall]
170["Cap Start"]
171["Cap End"]
172["SweepEdge Opposite"]
173["SweepEdge Adjacent"]
174["SweepEdge Opposite"]
175["SweepEdge Adjacent"]
176["SweepEdge Opposite"]
177["SweepEdge Adjacent"]
178["SweepEdge Opposite"]
179["SweepEdge Adjacent"]
187["Sweep Extrusion<br>[4599, 4626, 0]"]
188[Wall]
189[Wall]
190[Wall]
191[Wall]
192["Cap End"]
193["SweepEdge Opposite"]
194["SweepEdge Adjacent"]
195["SweepEdge Opposite"]
196["SweepEdge Adjacent"]
197["SweepEdge Opposite"]
198["SweepEdge Adjacent"]
199["SweepEdge Opposite"]
200["SweepEdge Adjacent"]
201["Sweep Extrusion<br>[4599, 4626, 0]"]
209["Sweep Extrusion<br>[5099, 5127, 0]"]
210[Wall]
211[Wall]
212[Wall]
213[Wall]
214["Cap Start"]
215["SweepEdge Opposite"]
216["SweepEdge Adjacent"]
217["SweepEdge Opposite"]
218["SweepEdge Adjacent"]
219["SweepEdge Opposite"]
220["SweepEdge Adjacent"]
221["SweepEdge Opposite"]
222["SweepEdge Adjacent"]
223["Sweep Extrusion<br>[5099, 5127, 0]"]
224["Plane<br>[5476, 5525, 0]"]
232["Sweep Extrusion<br>[5855, 5883, 0]"]
233[Wall]
234[Wall]
235[Wall]
236[Wall]
237["Cap Start"]
238["Cap End"]
239["SweepEdge Opposite"]
240["SweepEdge Adjacent"]
241["SweepEdge Opposite"]
242["SweepEdge Adjacent"]
243["SweepEdge Opposite"]
244["SweepEdge Adjacent"]
245["SweepEdge Opposite"]
246["SweepEdge Adjacent"]
247["Sweep Extrusion<br>[5855, 5883, 0]"]
248["Sweep Extrusion<br>[5855, 5883, 0]"]
249["Sweep Extrusion<br>[5855, 5883, 0]"]
250["Sweep Extrusion<br>[5855, 5883, 0]"]
251["Sweep Extrusion<br>[5855, 5883, 0]"]
259["Sweep Extrusion<br>[6334, 6362, 0]"]
260[Wall]
261[Wall]
262[Wall]
263[Wall]
264["Cap Start"]
265["Cap End"]
266["SweepEdge Opposite"]
267["SweepEdge Adjacent"]
268["SweepEdge Opposite"]
269["SweepEdge Adjacent"]
270["SweepEdge Opposite"]
271["SweepEdge Adjacent"]
272["SweepEdge Opposite"]
273["SweepEdge Adjacent"]
274["Sweep Extrusion<br>[6334, 6362, 0]"]
275["Plane<br>[6657, 6708, 0]"]
282["Plane<br>[7112, 7129, 0]"]
286["Sweep Sweep<br>[7267, 7320, 0]"]
287[Wall]
288["Cap Start"]
289["Cap Start"]
290["SweepEdge Opposite"]
291["SweepEdge Adjacent"]
292["StartSketchOnPlane<br>[1171, 1240, 0]"]
293["StartSketchOnPlane<br>[2231, 2297, 0]"]
294["StartSketchOnPlane<br>[2861, 2913, 0]"]
295["StartSketchOnPlane<br>[3726, 3778, 0]"]
296["StartSketchOnFace<br>[4220, 4256, 0]"]
297["StartSketchOnFace<br>[4646, 4680, 0]"]
298["StartSketchOnPlane<br>[5462, 5526, 0]"]
299["StartSketchOnPlane<br>[6643, 6709, 0]"]
1 --- 2
2 --- 3
2 --- 4
2 --- 5
2 --- 6
2 --- 7
2 ---- 9
2 --- 8
3 --- 13
3 --- 22
3 --- 23
4 --- 12
4 --- 20
4 --- 21
5 --- 11
5 --- 18
5 --- 19
6 --- 10
6 --- 16
6 --- 17
9 --- 10
9 --- 11
9 --- 12
9 --- 13
9 --- 14
9 --- 15
9 --- 16
9 --- 17
9 --- 18
9 --- 19
9 --- 20
9 --- 21
9 --- 22
9 --- 23
31 --- 32
31 --- 59
32 --- 33
32 --- 34
32 --- 35
32 --- 36
32 --- 37
32 ---- 39
32 --- 38
33 --- 43
33 --- 52
33 --- 53
34 --- 42
34 --- 50
34 --- 51
35 --- 41
35 --- 48
35 --- 49
36 --- 40
36 --- 46
36 --- 47
39 --- 40
39 --- 41
39 --- 42
39 --- 43
39 --- 44
39 --- 45
39 --- 46
39 --- 47
39 --- 48
39 --- 49
39 --- 50
39 --- 51
39 --- 52
39 --- 53
59 --- 60
59 --- 61
59 --- 62
59 --- 63
59 --- 64
59 ---- 66
59 --- 65
60 --- 70
60 --- 79
60 --- 80
61 --- 69
61 --- 77
61 --- 78
62 --- 68
62 --- 75
62 --- 76
63 --- 67
63 --- 73
63 --- 74
66 --- 67
66 --- 68
66 --- 69
66 --- 70
66 --- 71
66 --- 72
66 --- 73
66 --- 74
66 --- 75
66 --- 76
66 --- 77
66 --- 78
66 --- 79
66 --- 80
82 --- 83
83 --- 84
83 --- 85
83 --- 86
83 --- 87
83 --- 88
83 ---- 90
83 --- 89
84 --- 94
84 --- 103
84 --- 104
85 --- 93
85 --- 101
85 --- 102
86 --- 92
86 --- 99
86 --- 100
87 --- 91
87 --- 97
87 --- 98
90 --- 91
90 --- 92
90 --- 93
90 --- 94
90 --- 95
90 --- 96
90 --- 97
90 --- 98
90 --- 99
90 --- 100
90 --- 101
90 --- 102
90 --- 103
90 --- 104
110 --- 111
110 --- 134
111 --- 112
111 --- 113
111 --- 114
111 --- 115
111 --- 116
111 ---- 118
111 --- 117
112 --- 122
112 --- 131
112 --- 132
113 --- 121
113 --- 129
113 --- 130
114 --- 120
114 --- 127
114 --- 128
115 --- 119
115 --- 125
115 --- 126
118 --- 119
118 --- 120
118 --- 121
118 --- 122
118 --- 123
118 --- 124
118 --- 125
118 --- 126
118 --- 127
118 --- 128
118 --- 129
118 --- 130
118 --- 131
118 --- 132
134 --- 135
134 --- 136
134 --- 137
134 --- 138
134 --- 139
134 ---- 141
134 --- 140
135 --- 145
135 --- 154
135 --- 155
136 --- 144
136 --- 152
136 --- 153
137 --- 143
137 --- 150
137 --- 151
138 --- 142
138 --- 148
138 --- 149
141 --- 142
141 --- 143
141 --- 144
141 --- 145
141 --- 146
141 --- 147
141 --- 148
141 --- 149
141 --- 150
141 --- 151
141 --- 152
141 --- 153
141 --- 154
141 --- 155
157 --- 158
158 --- 159
158 --- 160
158 --- 161
158 --- 162
158 --- 163
158 ---- 165
158 --- 164
159 --- 169
159 --- 178
159 --- 179
160 --- 168
160 --- 176
160 --- 177
161 --- 167
161 --- 174
161 --- 175
162 --- 166
162 --- 172
162 --- 173
165 --- 166
165 --- 167
165 --- 168
165 --- 169
165 --- 170
165 --- 171
165 --- 172
165 --- 173
165 --- 174
165 --- 175
165 --- 176
165 --- 177
165 --- 178
165 --- 179
170 --- 180
171 --- 202
180 --- 181
180 --- 182
180 --- 183
180 --- 184
180 --- 185
180 ---- 187
180 --- 186
181 --- 188
181 --- 193
181 --- 194
182 --- 189
182 --- 195
182 --- 196
183 --- 190
183 --- 197
183 --- 198
184 --- 191
184 --- 199
184 --- 200
187 --- 188
187 --- 189
187 --- 190
187 --- 191
187 --- 192
187 --- 193
187 --- 194
187 --- 195
187 --- 196
187 --- 197
187 --- 198
187 --- 199
187 --- 200
202 --- 203
202 --- 204
202 --- 205
202 --- 206
202 --- 207
202 ---- 209
202 --- 208
203 --- 213
203 --- 221
203 --- 222
204 --- 212
204 --- 219
204 --- 220
205 --- 211
205 --- 217
205 --- 218
206 --- 210
206 --- 215
206 --- 216
209 --- 210
209 --- 211
209 --- 212
209 --- 213
209 --- 214
209 --- 215
209 --- 216
209 --- 217
209 --- 218
209 --- 219
209 --- 220
209 --- 221
209 --- 222
224 --- 225
224 --- 252
225 --- 226
225 --- 227
225 --- 228
225 --- 229
225 --- 230
225 ---- 232
225 --- 231
226 --- 236
226 --- 245
226 --- 246
227 --- 235
227 --- 243
227 --- 244
228 --- 234
228 --- 241
228 --- 242
229 --- 233
229 --- 239
229 --- 240
232 --- 233
232 --- 234
232 --- 235
232 --- 236
232 --- 237
232 --- 238
232 --- 239
232 --- 240
232 --- 241
232 --- 242
232 --- 243
232 --- 244
232 --- 245
232 --- 246
252 --- 253
252 --- 254
252 --- 255
252 --- 256
252 --- 257
252 ---- 259
252 --- 258
253 --- 263
253 --- 272
253 --- 273
254 --- 262
254 --- 270
254 --- 271
255 --- 261
255 --- 268
255 --- 269
256 --- 260
256 --- 266
256 --- 267
259 --- 260
259 --- 261
259 --- 262
259 --- 263
259 --- 264
259 --- 265
259 --- 266
259 --- 267
259 --- 268
259 --- 269
259 --- 270
259 --- 271
259 --- 272
259 --- 273
275 --- 276
276 --- 277
276 --- 278
276 --- 279
276 --- 280
276 --- 281
282 --- 283
283 --- 284
283 ---- 286
283 --- 285
284 --- 287
284 --- 290
284 --- 291
286 --- 287
286 --- 288
286 --- 289
286 --- 290
286 --- 291
31 <--x 292
82 <--x 293
110 <--x 294
157 <--x 295
170 <--x 296
171 <--x 297
224 <--x 298
275 <--x 299
```

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

View File

@ -14178,7 +14178,7 @@ description: Variables in memory after executing kitt.kcl
}
},
"height": 0.5,
"startCapId": "[uuid]",
"startCapId": null,
"endCapId": "[uuid]",
"units": {
"type": "Mm"
@ -16216,7 +16216,7 @@ description: Variables in memory after executing kitt.kcl
}
},
"height": 0.5,
"startCapId": "[uuid]",
"startCapId": null,
"endCapId": "[uuid]",
"units": {
"type": "Mm"

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,6 @@
---
source: kcl-lib/src/simulation_tests.rs
description: Artifact graph flowchart makeup-mirror.kcl
extension: md
snapshot_kind: binary
---

View File

@ -0,0 +1,317 @@
```mermaid
flowchart LR
subgraph path2 [Path]
2["Path<br>[520, 565, 0]"]
3["Segment<br>[520, 565, 0]"]
4[Solid2d]
end
subgraph path12 [Path]
12["Path<br>[520, 565, 0]"]
13["Segment<br>[520, 565, 0]"]
14[Solid2d]
end
subgraph path22 [Path]
22["Path<br>[520, 565, 0]"]
23["Segment<br>[520, 565, 0]"]
24[Solid2d]
end
subgraph path32 [Path]
32["Path<br>[520, 565, 0]"]
33["Segment<br>[520, 565, 0]"]
34[Solid2d]
end
subgraph path42 [Path]
42["Path<br>[520, 565, 0]"]
43["Segment<br>[520, 565, 0]"]
44[Solid2d]
end
subgraph path52 [Path]
52["Path<br>[520, 565, 0]"]
53["Segment<br>[520, 565, 0]"]
54[Solid2d]
end
subgraph path62 [Path]
62["Path<br>[520, 565, 0]"]
63["Segment<br>[520, 565, 0]"]
64[Solid2d]
end
subgraph path72 [Path]
72["Path<br>[1136, 1191, 0]"]
73["Segment<br>[1136, 1191, 0]"]
74[Solid2d]
end
subgraph path82 [Path]
82["Path<br>[1136, 1191, 0]"]
83["Segment<br>[1136, 1191, 0]"]
84[Solid2d]
end
subgraph path92 [Path]
92["Path<br>[1553, 1616, 0]"]
93["Segment<br>[1553, 1616, 0]"]
94[Solid2d]
end
subgraph path101 [Path]
101["Path<br>[1662, 1716, 0]"]
102["Segment<br>[1724, 1748, 0]"]
103["Segment<br>[1756, 1870, 0]"]
104["Segment<br>[1878, 1902, 0]"]
105["Segment<br>[1910, 2041, 0]"]
106["Segment<br>[2049, 2056, 0]"]
107[Solid2d]
end
1["Plane<br>[484, 511, 0]"]
5["Sweep Extrusion<br>[573, 602, 0]"]
6[Wall]
7["Cap Start"]
8["Cap End"]
9["SweepEdge Opposite"]
10["SweepEdge Adjacent"]
11["Plane<br>[484, 511, 0]"]
15["Sweep Extrusion<br>[573, 602, 0]"]
16[Wall]
17["Cap Start"]
18["Cap End"]
19["SweepEdge Opposite"]
20["SweepEdge Adjacent"]
21["Plane<br>[484, 511, 0]"]
25["Sweep Extrusion<br>[573, 602, 0]"]
26[Wall]
27["Cap Start"]
28["Cap End"]
29["SweepEdge Opposite"]
30["SweepEdge Adjacent"]
31["Plane<br>[484, 511, 0]"]
35["Sweep Extrusion<br>[573, 602, 0]"]
36[Wall]
37["Cap Start"]
38["Cap End"]
39["SweepEdge Opposite"]
40["SweepEdge Adjacent"]
41["Plane<br>[484, 511, 0]"]
45["Sweep Extrusion<br>[573, 602, 0]"]
46[Wall]
47["Cap Start"]
48["Cap End"]
49["SweepEdge Opposite"]
50["SweepEdge Adjacent"]
51["Plane<br>[484, 511, 0]"]
55["Sweep Extrusion<br>[573, 602, 0]"]
56[Wall]
57["Cap Start"]
58["Cap End"]
59["SweepEdge Opposite"]
60["SweepEdge Adjacent"]
61["Plane<br>[484, 511, 0]"]
65["Sweep Extrusion<br>[573, 602, 0]"]
66[Wall]
67["Cap Start"]
68["Cap End"]
69["SweepEdge Opposite"]
70["SweepEdge Adjacent"]
71["Plane<br>[1108, 1128, 0]"]
75["Sweep Extrusion<br>[1199, 1226, 0]"]
76[Wall]
77["Cap Start"]
78["Cap End"]
79["SweepEdge Opposite"]
80["SweepEdge Adjacent"]
81["Plane<br>[1108, 1128, 0]"]
85["Sweep Extrusion<br>[1199, 1226, 0]"]
86[Wall]
87["Cap Start"]
88["Cap End"]
89["SweepEdge Opposite"]
90["SweepEdge Adjacent"]
91["Plane<br>[1489, 1539, 0]"]
95["Sweep Extrusion<br>[1624, 1647, 0]"]
96[Wall]
97["Cap Start"]
98["Cap End"]
99["SweepEdge Opposite"]
100["SweepEdge Adjacent"]
108["Sweep Extrusion<br>[2064, 2087, 0]"]
109[Wall]
110[Wall]
111[Wall]
112[Wall]
113["Cap Start"]
114["Cap End"]
115["SweepEdge Opposite"]
116["SweepEdge Adjacent"]
117["SweepEdge Opposite"]
118["SweepEdge Adjacent"]
119["SweepEdge Opposite"]
120["SweepEdge Adjacent"]
121["SweepEdge Opposite"]
122["SweepEdge Adjacent"]
123["StartSketchOnPlane<br>[470, 512, 0]"]
124["StartSketchOnPlane<br>[470, 512, 0]"]
125["StartSketchOnPlane<br>[470, 512, 0]"]
126["StartSketchOnPlane<br>[470, 512, 0]"]
127["StartSketchOnPlane<br>[470, 512, 0]"]
128["StartSketchOnPlane<br>[470, 512, 0]"]
129["StartSketchOnPlane<br>[470, 512, 0]"]
130["StartSketchOnPlane<br>[1475, 1540, 0]"]
1 --- 2
2 --- 3
2 ---- 5
2 --- 4
3 --- 6
3 --- 9
3 --- 10
5 --- 6
5 --- 7
5 --- 8
5 --- 9
5 --- 10
11 --- 12
12 --- 13
12 ---- 15
12 --- 14
13 --- 16
13 --- 19
13 --- 20
15 --- 16
15 --- 17
15 --- 18
15 --- 19
15 --- 20
21 --- 22
22 --- 23
22 ---- 25
22 --- 24
23 --- 26
23 --- 29
23 --- 30
25 --- 26
25 --- 27
25 --- 28
25 --- 29
25 --- 30
31 --- 32
32 --- 33
32 ---- 35
32 --- 34
33 --- 36
33 --- 39
33 --- 40
35 --- 36
35 --- 37
35 --- 38
35 --- 39
35 --- 40
41 --- 42
42 --- 43
42 ---- 45
42 --- 44
43 --- 46
43 --- 49
43 --- 50
45 --- 46
45 --- 47
45 --- 48
45 --- 49
45 --- 50
51 --- 52
52 --- 53
52 ---- 55
52 --- 54
53 --- 56
53 --- 59
53 --- 60
55 --- 56
55 --- 57
55 --- 58
55 --- 59
55 --- 60
61 --- 62
62 --- 63
62 ---- 65
62 --- 64
63 --- 66
63 --- 69
63 --- 70
65 --- 66
65 --- 67
65 --- 68
65 --- 69
65 --- 70
71 --- 72
72 --- 73
72 ---- 75
72 --- 74
73 --- 76
73 --- 79
73 --- 80
75 --- 76
75 --- 77
75 --- 78
75 --- 79
75 --- 80
81 --- 82
82 --- 83
82 ---- 85
82 --- 84
83 --- 86
83 --- 89
83 --- 90
85 --- 86
85 --- 87
85 --- 88
85 --- 89
85 --- 90
91 --- 92
91 --- 101
92 --- 93
92 ---- 95
92 --- 94
93 --- 96
93 --- 99
93 --- 100
95 --- 96
95 --- 97
95 --- 98
95 --- 99
95 --- 100
101 --- 102
101 --- 103
101 --- 104
101 --- 105
101 --- 106
101 ---- 108
101 --- 107
102 --- 112
102 --- 121
102 --- 122
103 --- 111
103 --- 119
103 --- 120
104 --- 110
104 --- 117
104 --- 118
105 --- 109
105 --- 115
105 --- 116
108 --- 109
108 --- 110
108 --- 111
108 --- 112
108 --- 113
108 --- 114
108 --- 115
108 --- 116
108 --- 117
108 --- 118
108 --- 119
108 --- 120
108 --- 121
108 --- 122
1 <--x 123
11 <--x 124
21 <--x 125
31 <--x 126
41 <--x 127
51 <--x 128
61 <--x 129
91 <--x 130
```

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

View File

@ -0,0 +1,468 @@
---
source: kcl-lib/src/simulation_tests.rs
description: Artifact commands subtract_cylinder_from_cube.kcl
---
[
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "edge_lines_visible",
"hidden": false
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "set_scene_units",
"unit": "mm"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "object_visible",
"object_id": "[uuid]",
"hidden": true
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "object_visible",
"object_id": "[uuid]",
"hidden": true
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "make_plane",
"origin": {
"x": 0.0,
"y": 0.0,
"z": 0.0
},
"x_axis": {
"x": 1.0,
"y": 0.0,
"z": 0.0
},
"y_axis": {
"x": 0.0,
"y": 1.0,
"z": 0.0
},
"size": 60.0,
"clobber": false,
"hide": true
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "enable_sketch_mode",
"entity_id": "[uuid]",
"ortho": false,
"animated": false,
"adjust_camera": false,
"planar_normal": {
"x": 0.0,
"y": 0.0,
"z": 1.0
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "start_path"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "move_path_pen",
"path": "[uuid]",
"to": {
"x": -10.0,
"y": -10.0,
"z": 0.0
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "sketch_mode_disable"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "extend_path",
"path": "[uuid]",
"segment": {
"type": "line",
"end": {
"x": 10.0,
"y": -10.0,
"z": 0.0
},
"relative": false
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "extend_path",
"path": "[uuid]",
"segment": {
"type": "line",
"end": {
"x": 10.0,
"y": 10.0,
"z": 0.0
},
"relative": false
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "extend_path",
"path": "[uuid]",
"segment": {
"type": "line",
"end": {
"x": -10.0,
"y": 10.0,
"z": 0.0
},
"relative": false
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "close_path",
"path_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "enable_sketch_mode",
"entity_id": "[uuid]",
"ortho": false,
"animated": false,
"adjust_camera": false,
"planar_normal": {
"x": 0.0,
"y": 0.0,
"z": 1.0
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "extrude",
"target": "[uuid]",
"distance": 10.0,
"faces": null
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "sketch_mode_disable"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "object_bring_to_front",
"object_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_extrusion_face_info",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "make_plane",
"origin": {
"x": 0.0,
"y": 0.0,
"z": 0.0
},
"x_axis": {
"x": 1.0,
"y": 0.0,
"z": 0.0
},
"y_axis": {
"x": 0.0,
"y": 1.0,
"z": 0.0
},
"size": 60.0,
"clobber": false,
"hide": true
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "enable_sketch_mode",
"entity_id": "[uuid]",
"ortho": false,
"animated": false,
"adjust_camera": false,
"planar_normal": {
"x": 0.0,
"y": 0.0,
"z": 1.0
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "start_path"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "move_path_pen",
"path": "[uuid]",
"to": {
"x": 2.0,
"y": 0.0,
"z": 0.0
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "sketch_mode_disable"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "extend_path",
"path": "[uuid]",
"segment": {
"type": "arc",
"center": {
"x": 0.0,
"y": 0.0
},
"radius": 2.0,
"start": {
"unit": "degrees",
"value": 0.0
},
"end": {
"unit": "degrees",
"value": 360.0
},
"relative": false
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "close_path",
"path_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "enable_sketch_mode",
"entity_id": "[uuid]",
"ortho": false,
"animated": false,
"adjust_camera": false,
"planar_normal": {
"x": 0.0,
"y": 0.0,
"z": 1.0
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "extrude",
"target": "[uuid]",
"distance": 10.0,
"faces": null
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "sketch_mode_disable"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "object_bring_to_front",
"object_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_extrusion_face_info",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
}
]

View File

@ -0,0 +1,6 @@
---
source: kcl-lib/src/simulation_tests.rs
description: Artifact graph flowchart subtract_cylinder_from_cube.kcl
extension: md
snapshot_kind: binary
---

View File

@ -0,0 +1,84 @@
```mermaid
flowchart LR
subgraph path2 [Path]
2["Path<br>[52, 103, 0]"]
3["Segment<br>[111, 163, 0]"]
4["Segment<br>[171, 223, 0]"]
5["Segment<br>[231, 283, 0]"]
6["Segment<br>[291, 298, 0]"]
7[Solid2d]
end
subgraph path24 [Path]
24["Path<br>[388, 423, 0]"]
25["Segment<br>[388, 423, 0]"]
26[Solid2d]
end
1["Plane<br>[27, 44, 0]"]
8["Sweep Extrusion<br>[306, 326, 0]"]
9[Wall]
10[Wall]
11[Wall]
12[Wall]
13["Cap Start"]
14["Cap End"]
15["SweepEdge Opposite"]
16["SweepEdge Adjacent"]
17["SweepEdge Opposite"]
18["SweepEdge Adjacent"]
19["SweepEdge Opposite"]
20["SweepEdge Adjacent"]
21["SweepEdge Opposite"]
22["SweepEdge Adjacent"]
23["Plane<br>[363, 382, 0]"]
27["Sweep Extrusion<br>[429, 449, 0]"]
28[Wall]
29["Cap Start"]
30["Cap End"]
31["SweepEdge Opposite"]
32["SweepEdge Adjacent"]
1 --- 2
2 --- 3
2 --- 4
2 --- 5
2 --- 6
2 ---- 8
2 --- 7
3 --- 9
3 --- 15
3 --- 16
4 --- 10
4 --- 17
4 --- 18
5 --- 11
5 --- 19
5 --- 20
6 --- 12
6 --- 21
6 --- 22
8 --- 9
8 --- 10
8 --- 11
8 --- 12
8 --- 13
8 --- 14
8 --- 15
8 --- 16
8 --- 17
8 --- 18
8 --- 19
8 --- 20
8 --- 21
8 --- 22
23 --- 24
24 --- 25
24 ---- 27
24 --- 26
25 --- 28
25 --- 31
25 --- 32
27 --- 28
27 --- 29
27 --- 30
27 --- 31
27 --- 32
```

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,16 @@
fn cube(center) {
return startSketchOn(XY)
|> startProfileAt([center[0] - 10, center[1] - 10], %)
|> line(endAbsolute = [center[0] + 10, center[1] - 10])
|> line(endAbsolute = [center[0] + 10, center[1] + 10])
|> line(endAbsolute = [center[0] - 10, center[1] + 10])
|> close()
|> extrude(length = 10)
}
part001 = cube([0, 0])
part002 = startSketchOn('XY')
|> circle(center = [0, 0], radius = 2)
|> extrude(length = 10)
fullPart = subtract([part001], tools=[part002])

View File

@ -0,0 +1,216 @@
---
source: kcl-lib/src/simulation_tests.rs
description: Operations executed subtract_cylinder_from_cube.kcl
---
[
{
"type": "UserDefinedFunctionCall",
"name": "cube",
"functionSourceRange": [
7,
328,
0
],
"unlabeledArg": null,
"labeledArgs": {},
"sourceRange": []
},
{
"labeledArgs": {
"data": {
"value": {
"type": "Plane",
"artifact_id": "[uuid]"
},
"sourceRange": []
}
},
"name": "startSketchOn",
"sourceRange": [],
"type": "StdLibCall",
"unlabeledArg": null
},
{
"labeledArgs": {
"length": {
"value": {
"type": "Number",
"value": 10.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"sourceRange": []
}
},
"name": "extrude",
"sourceRange": [],
"type": "StdLibCall",
"unlabeledArg": {
"value": {
"type": "Sketch",
"value": {
"artifactId": "[uuid]"
}
},
"sourceRange": []
}
},
{
"type": "UserDefinedFunctionReturn"
},
{
"labeledArgs": {
"data": {
"value": {
"type": "String",
"value": "XY"
},
"sourceRange": []
}
},
"name": "startSketchOn",
"sourceRange": [],
"type": "StdLibCall",
"unlabeledArg": null
},
{
"type": "UserDefinedFunctionCall",
"name": "circle",
"functionSourceRange": [
0,
0,
0
],
"unlabeledArg": null,
"labeledArgs": {
"center": {
"value": {
"type": "Array",
"value": [
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
{
"type": "Number",
"value": 0.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
}
]
},
"sourceRange": []
},
"radius": {
"value": {
"type": "Number",
"value": 2.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"sourceRange": []
}
},
"sourceRange": []
},
{
"type": "UserDefinedFunctionReturn"
},
{
"labeledArgs": {
"length": {
"value": {
"type": "Number",
"value": 10.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"sourceRange": []
}
},
"name": "extrude",
"sourceRange": [],
"type": "StdLibCall",
"unlabeledArg": {
"value": {
"type": "Sketch",
"value": {
"artifactId": "[uuid]"
}
},
"sourceRange": []
}
},
{
"labeledArgs": {
"tools": {
"value": {
"type": "Array",
"value": [
{
"type": "Solid",
"value": {
"artifactId": "[uuid]"
}
}
]
},
"sourceRange": []
}
},
"name": "subtract",
"sourceRange": [],
"type": "StdLibCall",
"unlabeledArg": {
"value": {
"type": "Array",
"value": [
{
"type": "Solid",
"value": {
"artifactId": "[uuid]"
}
}
]
},
"sourceRange": []
}
}
]

View File

@ -0,0 +1,471 @@
---
source: kcl-lib/src/simulation_tests.rs
description: Variables in memory after executing subtract_cylinder_from_cube.kcl
---
{
"cube": {
"type": "Function"
},
"fullPart": {
"type": "Solid",
"value": {
"type": "Solid",
"id": "[uuid]",
"artifactId": "[uuid]",
"value": [
{
"faceId": "[uuid]",
"id": "[uuid]",
"sourceRange": [],
"tag": null,
"type": "extrudePlane"
},
{
"faceId": "[uuid]",
"id": "[uuid]",
"sourceRange": [],
"tag": null,
"type": "extrudePlane"
},
{
"faceId": "[uuid]",
"id": "[uuid]",
"sourceRange": [],
"tag": null,
"type": "extrudePlane"
},
{
"faceId": "[uuid]",
"id": "[uuid]",
"sourceRange": [],
"tag": null,
"type": "extrudePlane"
}
],
"sketch": {
"type": "Sketch",
"id": "[uuid]",
"paths": [
{
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
},
"from": [
-10.0,
-10.0
],
"tag": null,
"to": [
10.0,
-10.0
],
"type": "ToPoint",
"units": {
"type": "Mm"
}
},
{
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
},
"from": [
10.0,
-10.0
],
"tag": null,
"to": [
10.0,
10.0
],
"type": "ToPoint",
"units": {
"type": "Mm"
}
},
{
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
},
"from": [
10.0,
10.0
],
"tag": null,
"to": [
-10.0,
10.0
],
"type": "ToPoint",
"units": {
"type": "Mm"
}
},
{
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
},
"from": [
-10.0,
10.0
],
"tag": null,
"to": [
-10.0,
-10.0
],
"type": "ToPoint",
"units": {
"type": "Mm"
}
}
],
"on": {
"type": "plane",
"id": "[uuid]",
"artifactId": "[uuid]",
"value": "XY",
"origin": {
"x": 0.0,
"y": 0.0,
"z": 0.0
},
"xAxis": {
"x": 1.0,
"y": 0.0,
"z": 0.0
},
"yAxis": {
"x": 0.0,
"y": 1.0,
"z": 0.0
},
"zAxis": {
"x": 0.0,
"y": 0.0,
"z": 1.0
},
"units": {
"type": "Mm"
}
},
"start": {
"from": [
-10.0,
-10.0
],
"to": [
-10.0,
-10.0
],
"units": {
"type": "Mm"
},
"tag": null,
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
}
},
"artifactId": "[uuid]",
"originalId": "[uuid]",
"units": {
"type": "Mm"
}
},
"height": 10.0,
"startCapId": "[uuid]",
"endCapId": "[uuid]",
"units": {
"type": "Mm"
}
}
},
"part001": {
"type": "Solid",
"value": {
"type": "Solid",
"id": "[uuid]",
"artifactId": "[uuid]",
"value": [
{
"faceId": "[uuid]",
"id": "[uuid]",
"sourceRange": [],
"tag": null,
"type": "extrudePlane"
},
{
"faceId": "[uuid]",
"id": "[uuid]",
"sourceRange": [],
"tag": null,
"type": "extrudePlane"
},
{
"faceId": "[uuid]",
"id": "[uuid]",
"sourceRange": [],
"tag": null,
"type": "extrudePlane"
},
{
"faceId": "[uuid]",
"id": "[uuid]",
"sourceRange": [],
"tag": null,
"type": "extrudePlane"
}
],
"sketch": {
"type": "Sketch",
"id": "[uuid]",
"paths": [
{
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
},
"from": [
-10.0,
-10.0
],
"tag": null,
"to": [
10.0,
-10.0
],
"type": "ToPoint",
"units": {
"type": "Mm"
}
},
{
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
},
"from": [
10.0,
-10.0
],
"tag": null,
"to": [
10.0,
10.0
],
"type": "ToPoint",
"units": {
"type": "Mm"
}
},
{
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
},
"from": [
10.0,
10.0
],
"tag": null,
"to": [
-10.0,
10.0
],
"type": "ToPoint",
"units": {
"type": "Mm"
}
},
{
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
},
"from": [
-10.0,
10.0
],
"tag": null,
"to": [
-10.0,
-10.0
],
"type": "ToPoint",
"units": {
"type": "Mm"
}
}
],
"on": {
"type": "plane",
"id": "[uuid]",
"artifactId": "[uuid]",
"value": "XY",
"origin": {
"x": 0.0,
"y": 0.0,
"z": 0.0
},
"xAxis": {
"x": 1.0,
"y": 0.0,
"z": 0.0
},
"yAxis": {
"x": 0.0,
"y": 1.0,
"z": 0.0
},
"zAxis": {
"x": 0.0,
"y": 0.0,
"z": 1.0
},
"units": {
"type": "Mm"
}
},
"start": {
"from": [
-10.0,
-10.0
],
"to": [
-10.0,
-10.0
],
"units": {
"type": "Mm"
},
"tag": null,
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
}
},
"artifactId": "[uuid]",
"originalId": "[uuid]",
"units": {
"type": "Mm"
}
},
"height": 10.0,
"startCapId": "[uuid]",
"endCapId": "[uuid]",
"units": {
"type": "Mm"
}
}
},
"part002": {
"type": "Solid",
"value": {
"type": "Solid",
"id": "[uuid]",
"artifactId": "[uuid]",
"value": [
{
"faceId": "[uuid]",
"id": "[uuid]",
"sourceRange": [],
"tag": null,
"type": "extrudeArc"
}
],
"sketch": {
"type": "Sketch",
"id": "[uuid]",
"paths": [
{
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
},
"ccw": true,
"center": [
0.0,
0.0
],
"from": [
2.0,
0.0
],
"radius": 2.0,
"tag": null,
"to": [
2.0,
0.0
],
"type": "Circle",
"units": {
"type": "Mm"
}
}
],
"on": {
"type": "plane",
"id": "[uuid]",
"artifactId": "[uuid]",
"value": "XY",
"origin": {
"x": 0.0,
"y": 0.0,
"z": 0.0
},
"xAxis": {
"x": 1.0,
"y": 0.0,
"z": 0.0
},
"yAxis": {
"x": 0.0,
"y": 1.0,
"z": 0.0
},
"zAxis": {
"x": 0.0,
"y": 0.0,
"z": 1.0
},
"units": {
"type": "Mm"
}
},
"start": {
"from": [
2.0,
0.0
],
"to": [
2.0,
0.0
],
"units": {
"type": "Mm"
},
"tag": null,
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
}
},
"artifactId": "[uuid]",
"originalId": "[uuid]",
"units": {
"type": "Mm"
}
},
"height": 10.0,
"startCapId": "[uuid]",
"endCapId": "[uuid]",
"units": {
"type": "Mm"
}
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

View File

@ -0,0 +1,20 @@
---
source: kcl-lib/src/simulation_tests.rs
description: Result of unparsing subtract_cylinder_from_cube.kcl
---
fn cube(center) {
return startSketchOn(XY)
|> startProfileAt([center[0] - 10, center[1] - 10], %)
|> line(endAbsolute = [center[0] + 10, center[1] - 10])
|> line(endAbsolute = [center[0] + 10, center[1] + 10])
|> line(endAbsolute = [center[0] - 10, center[1] + 10])
|> close()
|> extrude(length = 10)
}
part001 = cube([0, 0])
part002 = startSketchOn(XY)
|> circle(center = [0, 0], radius = 2)
|> extrude(length = 10)
fullPart = subtract([part001], tools = [part002])

View File

@ -0,0 +1,554 @@
---
source: kcl-lib/src/simulation_tests.rs
description: Artifact commands union_cubes.kcl
---
[
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "edge_lines_visible",
"hidden": false
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "set_scene_units",
"unit": "mm"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "object_visible",
"object_id": "[uuid]",
"hidden": true
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "object_visible",
"object_id": "[uuid]",
"hidden": true
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "make_plane",
"origin": {
"x": 0.0,
"y": 0.0,
"z": 0.0
},
"x_axis": {
"x": 1.0,
"y": 0.0,
"z": 0.0
},
"y_axis": {
"x": 0.0,
"y": 1.0,
"z": 0.0
},
"size": 60.0,
"clobber": false,
"hide": true
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "enable_sketch_mode",
"entity_id": "[uuid]",
"ortho": false,
"animated": false,
"adjust_camera": false,
"planar_normal": {
"x": 0.0,
"y": 0.0,
"z": 1.0
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "start_path"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "move_path_pen",
"path": "[uuid]",
"to": {
"x": -10.0,
"y": -10.0,
"z": 0.0
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "sketch_mode_disable"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "extend_path",
"path": "[uuid]",
"segment": {
"type": "line",
"end": {
"x": 10.0,
"y": -10.0,
"z": 0.0
},
"relative": false
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "extend_path",
"path": "[uuid]",
"segment": {
"type": "line",
"end": {
"x": 10.0,
"y": 10.0,
"z": 0.0
},
"relative": false
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "extend_path",
"path": "[uuid]",
"segment": {
"type": "line",
"end": {
"x": -10.0,
"y": 10.0,
"z": 0.0
},
"relative": false
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "close_path",
"path_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "enable_sketch_mode",
"entity_id": "[uuid]",
"ortho": false,
"animated": false,
"adjust_camera": false,
"planar_normal": {
"x": 0.0,
"y": 0.0,
"z": 1.0
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "extrude",
"target": "[uuid]",
"distance": 10.0,
"faces": null
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "sketch_mode_disable"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "object_bring_to_front",
"object_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_extrusion_face_info",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "make_plane",
"origin": {
"x": 0.0,
"y": 0.0,
"z": 0.0
},
"x_axis": {
"x": 1.0,
"y": 0.0,
"z": 0.0
},
"y_axis": {
"x": 0.0,
"y": 1.0,
"z": 0.0
},
"size": 60.0,
"clobber": false,
"hide": true
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "enable_sketch_mode",
"entity_id": "[uuid]",
"ortho": false,
"animated": false,
"adjust_camera": false,
"planar_normal": {
"x": 0.0,
"y": 0.0,
"z": 1.0
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "start_path"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "move_path_pen",
"path": "[uuid]",
"to": {
"x": 10.0,
"y": 0.0,
"z": 0.0
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "sketch_mode_disable"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "extend_path",
"path": "[uuid]",
"segment": {
"type": "line",
"end": {
"x": 30.0,
"y": 0.0,
"z": 0.0
},
"relative": false
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "extend_path",
"path": "[uuid]",
"segment": {
"type": "line",
"end": {
"x": 30.0,
"y": 20.0,
"z": 0.0
},
"relative": false
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "extend_path",
"path": "[uuid]",
"segment": {
"type": "line",
"end": {
"x": 10.0,
"y": 20.0,
"z": 0.0
},
"relative": false
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "close_path",
"path_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "enable_sketch_mode",
"entity_id": "[uuid]",
"ortho": false,
"animated": false,
"adjust_camera": false,
"planar_normal": {
"x": 0.0,
"y": 0.0,
"z": 1.0
}
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "extrude",
"target": "[uuid]",
"distance": 10.0,
"faces": null
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "sketch_mode_disable"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "object_bring_to_front",
"object_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_extrusion_face_info",
"object_id": "[uuid]",
"edge_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_opposite_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
},
{
"cmdId": "[uuid]",
"range": [],
"command": {
"type": "solid3d_get_next_adjacent_edge",
"object_id": "[uuid]",
"edge_id": "[uuid]",
"face_id": "[uuid]"
}
}
]

View File

@ -0,0 +1,6 @@
---
source: kcl-lib/src/simulation_tests.rs
description: Artifact graph flowchart union_cubes.kcl
extension: md
snapshot_kind: binary
---

View File

@ -0,0 +1,117 @@
```mermaid
flowchart LR
subgraph path2 [Path]
2["Path<br>[52, 103, 0]"]
3["Segment<br>[111, 163, 0]"]
4["Segment<br>[171, 223, 0]"]
5["Segment<br>[231, 283, 0]"]
6["Segment<br>[291, 298, 0]"]
7[Solid2d]
end
subgraph path24 [Path]
24["Path<br>[52, 103, 0]"]
25["Segment<br>[111, 163, 0]"]
26["Segment<br>[171, 223, 0]"]
27["Segment<br>[231, 283, 0]"]
28["Segment<br>[291, 298, 0]"]
29[Solid2d]
end
1["Plane<br>[27, 44, 0]"]
8["Sweep Extrusion<br>[306, 326, 0]"]
9[Wall]
10[Wall]
11[Wall]
12[Wall]
13["Cap Start"]
14["Cap End"]
15["SweepEdge Opposite"]
16["SweepEdge Adjacent"]
17["SweepEdge Opposite"]
18["SweepEdge Adjacent"]
19["SweepEdge Opposite"]
20["SweepEdge Adjacent"]
21["SweepEdge Opposite"]
22["SweepEdge Adjacent"]
23["Plane<br>[27, 44, 0]"]
30["Sweep Extrusion<br>[306, 326, 0]"]
31[Wall]
32[Wall]
33[Wall]
34[Wall]
35["Cap Start"]
36["Cap End"]
37["SweepEdge Opposite"]
38["SweepEdge Adjacent"]
39["SweepEdge Opposite"]
40["SweepEdge Adjacent"]
41["SweepEdge Opposite"]
42["SweepEdge Adjacent"]
43["SweepEdge Opposite"]
44["SweepEdge Adjacent"]
1 --- 2
2 --- 3
2 --- 4
2 --- 5
2 --- 6
2 ---- 8
2 --- 7
3 --- 9
3 --- 15
3 --- 16
4 --- 10
4 --- 17
4 --- 18
5 --- 11
5 --- 19
5 --- 20
6 --- 12
6 --- 21
6 --- 22
8 --- 9
8 --- 10
8 --- 11
8 --- 12
8 --- 13
8 --- 14
8 --- 15
8 --- 16
8 --- 17
8 --- 18
8 --- 19
8 --- 20
8 --- 21
8 --- 22
23 --- 24
24 --- 25
24 --- 26
24 --- 27
24 --- 28
24 ---- 30
24 --- 29
25 --- 31
25 --- 37
25 --- 38
26 --- 32
26 --- 39
26 --- 40
27 --- 33
27 --- 41
27 --- 42
28 --- 34
28 --- 43
28 --- 44
30 --- 31
30 --- 32
30 --- 33
30 --- 34
30 --- 35
30 --- 36
30 --- 37
30 --- 38
30 --- 39
30 --- 40
30 --- 41
30 --- 42
30 --- 43
30 --- 44
```

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,14 @@
fn cube(center) {
return startSketchOn(XY)
|> startProfileAt([center[0] - 10, center[1] - 10], %)
|> line(endAbsolute = [center[0] + 10, center[1] - 10])
|> line(endAbsolute = [center[0] + 10, center[1] + 10])
|> line(endAbsolute = [center[0] - 10, center[1] + 10])
|> close()
|> extrude(length = 10)
}
part001 = cube([0, 0])
part002 = cube([20, 10])
fullPart = union([part001, part002])

View File

@ -0,0 +1,158 @@
---
source: kcl-lib/src/simulation_tests.rs
description: Operations executed union_cubes.kcl
---
[
{
"type": "UserDefinedFunctionCall",
"name": "cube",
"functionSourceRange": [
7,
328,
0
],
"unlabeledArg": null,
"labeledArgs": {},
"sourceRange": []
},
{
"labeledArgs": {
"data": {
"value": {
"type": "Plane",
"artifact_id": "[uuid]"
},
"sourceRange": []
}
},
"name": "startSketchOn",
"sourceRange": [],
"type": "StdLibCall",
"unlabeledArg": null
},
{
"labeledArgs": {
"length": {
"value": {
"type": "Number",
"value": 10.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"sourceRange": []
}
},
"name": "extrude",
"sourceRange": [],
"type": "StdLibCall",
"unlabeledArg": {
"value": {
"type": "Sketch",
"value": {
"artifactId": "[uuid]"
}
},
"sourceRange": []
}
},
{
"type": "UserDefinedFunctionReturn"
},
{
"type": "UserDefinedFunctionCall",
"name": "cube",
"functionSourceRange": [
7,
328,
0
],
"unlabeledArg": null,
"labeledArgs": {},
"sourceRange": []
},
{
"labeledArgs": {
"data": {
"value": {
"type": "Plane",
"artifact_id": "[uuid]"
},
"sourceRange": []
}
},
"name": "startSketchOn",
"sourceRange": [],
"type": "StdLibCall",
"unlabeledArg": null
},
{
"labeledArgs": {
"length": {
"value": {
"type": "Number",
"value": 10.0,
"ty": {
"type": "Default",
"len": {
"type": "Mm"
},
"angle": {
"type": "Degrees"
}
}
},
"sourceRange": []
}
},
"name": "extrude",
"sourceRange": [],
"type": "StdLibCall",
"unlabeledArg": {
"value": {
"type": "Sketch",
"value": {
"artifactId": "[uuid]"
}
},
"sourceRange": []
}
},
{
"type": "UserDefinedFunctionReturn"
},
{
"labeledArgs": {
"solids": {
"value": {
"type": "Array",
"value": [
{
"type": "Solid",
"value": {
"artifactId": "[uuid]"
}
},
{
"type": "Solid",
"value": {
"artifactId": "[uuid]"
}
}
]
},
"sourceRange": []
}
},
"name": "union",
"sourceRange": [],
"type": "StdLibCall",
"unlabeledArg": null
}
]

View File

@ -0,0 +1,543 @@
---
source: kcl-lib/src/simulation_tests.rs
description: Variables in memory after executing union_cubes.kcl
---
{
"cube": {
"type": "Function"
},
"fullPart": {
"type": "Solid",
"value": {
"type": "Solid",
"id": "[uuid]",
"artifactId": "[uuid]",
"value": [
{
"faceId": "[uuid]",
"id": "[uuid]",
"sourceRange": [],
"tag": null,
"type": "extrudePlane"
},
{
"faceId": "[uuid]",
"id": "[uuid]",
"sourceRange": [],
"tag": null,
"type": "extrudePlane"
},
{
"faceId": "[uuid]",
"id": "[uuid]",
"sourceRange": [],
"tag": null,
"type": "extrudePlane"
},
{
"faceId": "[uuid]",
"id": "[uuid]",
"sourceRange": [],
"tag": null,
"type": "extrudePlane"
}
],
"sketch": {
"type": "Sketch",
"id": "[uuid]",
"paths": [
{
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
},
"from": [
-10.0,
-10.0
],
"tag": null,
"to": [
10.0,
-10.0
],
"type": "ToPoint",
"units": {
"type": "Mm"
}
},
{
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
},
"from": [
10.0,
-10.0
],
"tag": null,
"to": [
10.0,
10.0
],
"type": "ToPoint",
"units": {
"type": "Mm"
}
},
{
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
},
"from": [
10.0,
10.0
],
"tag": null,
"to": [
-10.0,
10.0
],
"type": "ToPoint",
"units": {
"type": "Mm"
}
},
{
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
},
"from": [
-10.0,
10.0
],
"tag": null,
"to": [
-10.0,
-10.0
],
"type": "ToPoint",
"units": {
"type": "Mm"
}
}
],
"on": {
"type": "plane",
"id": "[uuid]",
"artifactId": "[uuid]",
"value": "XY",
"origin": {
"x": 0.0,
"y": 0.0,
"z": 0.0
},
"xAxis": {
"x": 1.0,
"y": 0.0,
"z": 0.0
},
"yAxis": {
"x": 0.0,
"y": 1.0,
"z": 0.0
},
"zAxis": {
"x": 0.0,
"y": 0.0,
"z": 1.0
},
"units": {
"type": "Mm"
}
},
"start": {
"from": [
-10.0,
-10.0
],
"to": [
-10.0,
-10.0
],
"units": {
"type": "Mm"
},
"tag": null,
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
}
},
"artifactId": "[uuid]",
"originalId": "[uuid]",
"units": {
"type": "Mm"
}
},
"height": 10.0,
"startCapId": "[uuid]",
"endCapId": "[uuid]",
"units": {
"type": "Mm"
}
}
},
"part001": {
"type": "Solid",
"value": {
"type": "Solid",
"id": "[uuid]",
"artifactId": "[uuid]",
"value": [
{
"faceId": "[uuid]",
"id": "[uuid]",
"sourceRange": [],
"tag": null,
"type": "extrudePlane"
},
{
"faceId": "[uuid]",
"id": "[uuid]",
"sourceRange": [],
"tag": null,
"type": "extrudePlane"
},
{
"faceId": "[uuid]",
"id": "[uuid]",
"sourceRange": [],
"tag": null,
"type": "extrudePlane"
},
{
"faceId": "[uuid]",
"id": "[uuid]",
"sourceRange": [],
"tag": null,
"type": "extrudePlane"
}
],
"sketch": {
"type": "Sketch",
"id": "[uuid]",
"paths": [
{
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
},
"from": [
-10.0,
-10.0
],
"tag": null,
"to": [
10.0,
-10.0
],
"type": "ToPoint",
"units": {
"type": "Mm"
}
},
{
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
},
"from": [
10.0,
-10.0
],
"tag": null,
"to": [
10.0,
10.0
],
"type": "ToPoint",
"units": {
"type": "Mm"
}
},
{
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
},
"from": [
10.0,
10.0
],
"tag": null,
"to": [
-10.0,
10.0
],
"type": "ToPoint",
"units": {
"type": "Mm"
}
},
{
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
},
"from": [
-10.0,
10.0
],
"tag": null,
"to": [
-10.0,
-10.0
],
"type": "ToPoint",
"units": {
"type": "Mm"
}
}
],
"on": {
"type": "plane",
"id": "[uuid]",
"artifactId": "[uuid]",
"value": "XY",
"origin": {
"x": 0.0,
"y": 0.0,
"z": 0.0
},
"xAxis": {
"x": 1.0,
"y": 0.0,
"z": 0.0
},
"yAxis": {
"x": 0.0,
"y": 1.0,
"z": 0.0
},
"zAxis": {
"x": 0.0,
"y": 0.0,
"z": 1.0
},
"units": {
"type": "Mm"
}
},
"start": {
"from": [
-10.0,
-10.0
],
"to": [
-10.0,
-10.0
],
"units": {
"type": "Mm"
},
"tag": null,
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
}
},
"artifactId": "[uuid]",
"originalId": "[uuid]",
"units": {
"type": "Mm"
}
},
"height": 10.0,
"startCapId": "[uuid]",
"endCapId": "[uuid]",
"units": {
"type": "Mm"
}
}
},
"part002": {
"type": "Solid",
"value": {
"type": "Solid",
"id": "[uuid]",
"artifactId": "[uuid]",
"value": [
{
"faceId": "[uuid]",
"id": "[uuid]",
"sourceRange": [],
"tag": null,
"type": "extrudePlane"
},
{
"faceId": "[uuid]",
"id": "[uuid]",
"sourceRange": [],
"tag": null,
"type": "extrudePlane"
},
{
"faceId": "[uuid]",
"id": "[uuid]",
"sourceRange": [],
"tag": null,
"type": "extrudePlane"
},
{
"faceId": "[uuid]",
"id": "[uuid]",
"sourceRange": [],
"tag": null,
"type": "extrudePlane"
}
],
"sketch": {
"type": "Sketch",
"id": "[uuid]",
"paths": [
{
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
},
"from": [
10.0,
0.0
],
"tag": null,
"to": [
30.0,
0.0
],
"type": "ToPoint",
"units": {
"type": "Mm"
}
},
{
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
},
"from": [
30.0,
0.0
],
"tag": null,
"to": [
30.0,
20.0
],
"type": "ToPoint",
"units": {
"type": "Mm"
}
},
{
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
},
"from": [
30.0,
20.0
],
"tag": null,
"to": [
10.0,
20.0
],
"type": "ToPoint",
"units": {
"type": "Mm"
}
},
{
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
},
"from": [
10.0,
20.0
],
"tag": null,
"to": [
10.0,
0.0
],
"type": "ToPoint",
"units": {
"type": "Mm"
}
}
],
"on": {
"type": "plane",
"id": "[uuid]",
"artifactId": "[uuid]",
"value": "XY",
"origin": {
"x": 0.0,
"y": 0.0,
"z": 0.0
},
"xAxis": {
"x": 1.0,
"y": 0.0,
"z": 0.0
},
"yAxis": {
"x": 0.0,
"y": 1.0,
"z": 0.0
},
"zAxis": {
"x": 0.0,
"y": 0.0,
"z": 1.0
},
"units": {
"type": "Mm"
}
},
"start": {
"from": [
10.0,
0.0
],
"to": [
10.0,
0.0
],
"units": {
"type": "Mm"
},
"tag": null,
"__geoMeta": {
"id": "[uuid]",
"sourceRange": []
}
},
"artifactId": "[uuid]",
"originalId": "[uuid]",
"units": {
"type": "Mm"
}
},
"height": 10.0,
"startCapId": "[uuid]",
"endCapId": "[uuid]",
"units": {
"type": "Mm"
}
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

View File

@ -0,0 +1,18 @@
---
source: kcl-lib/src/simulation_tests.rs
description: Result of unparsing union_cubes.kcl
---
fn cube(center) {
return startSketchOn(XY)
|> startProfileAt([center[0] - 10, center[1] - 10], %)
|> line(endAbsolute = [center[0] + 10, center[1] - 10])
|> line(endAbsolute = [center[0] + 10, center[1] + 10])
|> line(endAbsolute = [center[0] - 10, center[1] + 10])
|> close()
|> extrude(length = 10)
}
part001 = cube([0, 0])
part002 = cube([20, 10])
fullPart = union([part001, part002])

View File

@ -0,0 +1,18 @@
# Stop the script when a cmdlet or a native command fails
# from https://www.meziantou.net/stop-the-script-when-an-error-occurs-in-powershell.htm
$ErrorActionPreference = 'Stop'
$PSNativeCommandUseErrorActionPreference = $true
rm -Recurse -Force rust/kcl-wasm-lib/pkg
mkdir -p rust/kcl-wasm-lib/pkg
rm -Recurse -Force rust/kcl-lib/bindings
cd rust
$env:RUSTFLAGS='--cfg getrandom_backend="wasm_js"'
wasm-pack build kcl-wasm-lib --dev --target web --out-dir pkg
$env:RUSTFLAGS=''
cargo test -p kcl-lib export_bindings
cd ..
copy rust\kcl-wasm-lib\pkg\kcl_wasm_lib_bg.wasm public
yarn fmt:generated

16
scripts/build-wasm-dev.sh Executable file
View File

@ -0,0 +1,16 @@
#!/bin/bash
set -euo pipefail
rm -rf rust/kcl-wasm-lib/pkg
mkdir -p rust/kcl-wasm-lib/pkg
rm -rf rust/kcl-lib/bindings
cd rust
export RUSTFLAGS='--cfg getrandom_backend="wasm_js"'
wasm-pack build kcl-wasm-lib --dev --target web --out-dir pkg
export RUSTFLAGS=''
cargo test -p kcl-lib export_bindings
cd ..
cp rust/kcl-wasm-lib/pkg/kcl_wasm_lib_bg.wasm public
yarn fmt:generated

View File

@ -669,7 +669,7 @@ const ConstraintSymbol = ({
return Promise.reject(pResult)
const _node1 = getNodeFromPath<CallExpression | CallExpressionKw>(
pResult.program!,
pResult.program,
pathToNode,
['CallExpression', 'CallExpressionKw'],
true

View File

@ -43,8 +43,8 @@ export const INTERSECTION_PLANE_LAYER = 1
export const SKETCH_LAYER = 2
// redundant types so that it can be changed temporarily but CI will catch the wrong type
export const DEBUG_SHOW_INTERSECTION_PLANE: false = false
export const DEBUG_SHOW_BOTH_SCENES: false = false
export const DEBUG_SHOW_INTERSECTION_PLANE = false
export const DEBUG_SHOW_BOTH_SCENES = false
export const RAYCASTABLE_PLANE = 'raycastable-plane'

View File

@ -1037,7 +1037,7 @@ class ArcSegment implements SegmentUtils {
endAngle,
scale,
color: grey, // Red color for the angle indicator
}) as Line
})
angleIndicator.name = 'angleIndicator'
// Create a new angle indicator for the end angle
@ -1048,7 +1048,7 @@ class ArcSegment implements SegmentUtils {
endAngle: (endAngle * Math.PI) / 180,
scale,
color: grey, // Green color for the end angle indicator
}) as Line
})
endAngleIndicator.name = 'endAngleIndicator'
// Create a length indicator for the end angle

View File

@ -1,8 +1,7 @@
import {
IconDefinition as SolidIconDefinition,
IconDefinition,
faCircleExclamation,
} from '@fortawesome/free-solid-svg-icons'
import { IconDefinition as BrandIconDefinition } from '@fortawesome/free-brands-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { CustomIcon, CustomIconName } from './CustomIcon'
@ -14,7 +13,7 @@ const iconSizes = {
}
export interface ActionIconProps extends React.PropsWithChildren {
icon?: SolidIconDefinition | BrandIconDefinition | CustomIconName
icon?: IconDefinition | CustomIconName
iconColor?: string
className?: string
bgClassName?: string

View File

@ -8,7 +8,7 @@ import Tooltip from 'components/Tooltip'
import { roundOff } from 'lib/utils'
import { commandBarActor, useCommandBarState } from 'machines/commandBarMachine'
function CommandBarHeader({ children }: React.PropsWithChildren<{}>) {
function CommandBarHeader({ children }: React.PropsWithChildren<object>) {
const commandBarState = useCommandBarState()
const {
context: { selectedCommand, currentArgument, argumentsToSubmit },
@ -98,9 +98,7 @@ function CommandBarHeader({ children }: React.PropsWithChildren<{}>) {
.map(([argName, arg], i) => {
const argValue =
(typeof argumentsToSubmit[argName] === 'function'
? (argumentsToSubmit[argName] as Function)(
commandBarState.context
)
? argumentsToSubmit[argName](commandBarState.context)
: argumentsToSubmit[argName]) || ''
return (

View File

@ -27,6 +27,7 @@ import { getNodeFromPath } from 'lang/queryAst'
import { isPathToNode, SourceRange, VariableDeclarator } from 'lang/wasm'
import { Node } from '@rust/kcl-lib/bindings/Node'
import { err } from 'lib/trap'
import { Spinner } from 'components/Spinner'
// TODO: remove the need for this selector once we decouple all actors from React
const machineContextSelector = (snapshot?: SnapshotFrom<AnyStateMachine>) =>
@ -80,7 +81,8 @@ function CommandBarKclInput({
: arg.variableName
}
// or derive it from the previously set value or the argument name
return previouslySetValue && 'variableName' in previouslySetValue
return typeof previouslySetValue === 'object' &&
'variableName' in previouslySetValue
? previouslySetValue.variableName
: arg.name
}, [
@ -96,7 +98,8 @@ function CommandBarKclInput({
)
const [value, setValue] = useState(initialValue)
const [createNewVariable, setCreateNewVariable] = useState(
(previouslySetValue && 'variableName' in previouslySetValue) ||
(typeof previouslySetValue === 'object' &&
'variableName' in previouslySetValue) ||
arg.createVariable === 'byDefault' ||
arg.createVariable === 'force' ||
false
@ -113,6 +116,7 @@ function CommandBarKclInput({
setNewVariableName,
isNewVariableNameUnique,
prevVariables,
isExecuting,
} = useCalculateKclExpression({
value,
initialVariableName,
@ -132,7 +136,8 @@ function CommandBarKclInput({
selection: {
anchor: 0,
head:
previouslySetValue && 'valueText' in previouslySetValue
typeof previouslySetValue === 'object' &&
'valueText' in previouslySetValue
? previouslySetValue.valueText.length
: defaultValue.length,
},
@ -197,9 +202,11 @@ function CommandBarKclInput({
useEffect(() => {
setCanSubmit(
calcResult !== 'NAN' && (!createNewVariable || isNewVariableNameUnique)
calcResult !== 'NAN' &&
(!createNewVariable || isNewVariableNameUnique) &&
!isExecuting
)
}, [calcResult, createNewVariable, isNewVariableNameUnique])
}, [calcResult, createNewVariable, isNewVariableNameUnique, isExecuting])
function handleSubmit(e?: React.FormEvent<HTMLFormElement>) {
e?.preventDefault()
@ -265,9 +272,13 @@ function CommandBarKclInput({
: 'text-succeed-80 dark:text-succeed-40'
}
>
{calcResult === 'NAN'
? "Can't calculate"
: roundOff(Number(calcResult), 4)}
{isExecuting === true || !calcResult ? (
<Spinner className="text-inherit w-4 h-4" />
) : calcResult === 'NAN' ? (
"Can't calculate"
) : (
roundOff(Number(calcResult), 4)
)}
</span>
</label>
{createNewVariable ? (

View File

@ -6,7 +6,7 @@ import {
getSelectionCountByType,
getSelectionTypeDisplayText,
} from 'lib/selections'
import { kclManager } from 'lib/singletons'
import { engineCommandManager, kclManager } from 'lib/singletons'
import { reportRejection } from 'lib/trap'
import { toSync } from 'lib/utils'
import { commandBarActor, useCommandBarState } from 'machines/commandBarMachine'
@ -112,6 +112,23 @@ function CommandBarSelectionInput({
onSubmit(selection)
}
// Clear selection if needed
useEffect(() => {
arg.clearSelectionFirst &&
engineCommandManager.modelingSend({
type: 'Set selection',
data: {
selectionType: 'singleCodeCursor',
},
})
}, [arg.clearSelectionFirst])
// Set selection filter if needed, and reset it when the component unmounts
useEffect(() => {
arg.selectionFilter && kclManager.setSelectionFilter(arg.selectionFilter)
return () => kclManager.defaultSelectionFilter(selection)
}, [arg.selectionFilter])
return (
<form id="arg-form" onSubmit={handleSubmit}>
<label

View File

@ -7,6 +7,7 @@ import {
} from 'lib/selections'
import { useSelector } from '@xstate/react'
import { commandBarActor, useCommandBarState } from 'machines/commandBarMachine'
import { kclManager } from 'lib/singletons'
const selectionSelector = (snapshot: any) => snapshot?.context.selectionRanges
@ -56,6 +57,12 @@ export default function CommandBarSelectionMixedInput({
}
}, [])
// Set selection filter if needed, and reset it when the component unmounts
useEffect(() => {
arg.selectionFilter && kclManager.setSelectionFilter(arg.selectionFilter)
return () => kclManager.defaultSelectionFilter(selection)
}, [arg.selectionFilter])
function handleChange() {
inputRef.current?.focus()
}

View File

@ -387,7 +387,7 @@ const CustomIconMap = {
<path
fillRule="evenodd"
clipRule="evenodd"
d="M10 2.51583L10.3536 2.86938L12.3536 4.86938L11.6465 5.57649L10.5 4.43004V10.1012C11.0826 10.3071 11.5 10.8627 11.5 11.5158C11.5 12.3443 10.8284 13.0158 10 13.0158C9.17157 13.0158 8.5 12.3443 8.5 11.5158C8.5 10.8627 8.9174 10.3071 9.5 10.1012V4.43004L8.35356 5.57649L7.64645 4.86938L9.64645 2.86938L10 2.51583ZM3.95886 10.8441L8.5 8.06893V9.24088L4.91773 11.43L10 14.5359L15.0823 11.43L11.5 9.24087V8.06893L16.0411 10.8441L17 11.43L17 13.4842H16V12.0412L10.5 15.4023V17.4842H9.5V15.4023L4 12.0412V13.4842H3V11.43L3.95886 10.8441Z"
d="M10 3.29317L10.2346 3.41776L15.728 6.33576L15.9935 6.47676V6.77733V12.7391V13.0185L15.7555 13.165L10.2621 16.5456L10 16.7068L9.73796 16.5456L4.24448 13.165L4.00653 13.0185V12.7391V6.77733V6.47676L4.27198 6.33576L9.76546 3.41776L10 3.29317ZM10 4.42549L5.56039 6.78371L10 9.21124L14.4396 6.78371L10 4.42549ZM14.9935 7.62059L10.5 10.0776V15.225L14.9935 12.4597V7.62059ZM9.50001 15.225V10.0776L5.00653 7.62059V12.4597L9.50001 15.225Z"
fill="currentColor"
/>
</svg>
@ -732,7 +732,7 @@ const CustomIconMap = {
<path
fillRule="evenodd"
clipRule="evenodd"
d="M13.7954 6.22689C14.7749 5.73715 15 5.2456 15 5C15 4.7544 14.7749 4.26285 13.7954 3.77311C12.8758 3.31327 11.5353 3 10 3C8.46473 3 7.12424 3.31327 6.20457 3.77311C5.22509 4.26285 5 4.7544 5 5C5 5.2456 5.22509 5.73715 6.20457 6.22689C6.29872 6.27397 6.39728 6.3195 6.5 6.36333L6.5 7.43698C4.98593 6.89239 4 6.00376 4 5C4 3.34315 6.68629 2 10 2C13.3137 2 16 3.34315 16 5C16 6.00376 15.0141 6.89239 13.5 7.43698V6.36333C13.6027 6.3195 13.7013 6.27397 13.7954 6.22689ZM11.5 8.5531V9.72505L15.0823 11.9142L10 15.0201L4.91773 11.9142L8.5 9.72505V8.5531L3.95886 11.3282L3 11.9142V13.9683H4V12.5253L9.5 15.8864V17.9683H10.5V15.8864L16 12.5253V13.9683H17L17 11.9142L16.0411 11.3282L11.5 8.5531ZM10 4.29289L10.3536 4.64645L12.3536 6.64644L11.6465 7.35355L10.5 6.20711V10.5854C11.0826 10.7913 11.5 11.3469 11.5 12C11.5 12.8284 10.8284 13.5 10 13.5C9.17157 13.5 8.5 12.8284 8.5 12C8.5 11.3469 8.91741 10.7913 9.5 10.5854V6.20711L8.35356 7.35355L7.64645 6.64644L9.64645 4.64645L10 4.29289Z"
d="M9.9995 4.85357C9.15003 4.85357 8.32765 5.04209 7.7242 5.3905C7.11795 5.74052 6.92818 6.12938 6.92818 6.41547C6.92818 6.70156 7.11795 7.09042 7.7242 7.44044C8.32765 7.78884 9.15003 7.97737 9.9995 7.97737C10.849 7.97737 11.6714 7.78884 12.2748 7.44044C12.8811 7.09042 13.0708 6.70156 13.0708 6.41547C13.0708 6.12938 12.8811 5.74052 12.2748 5.3905C11.6714 5.04209 10.849 4.85357 9.9995 4.85357ZM9.9995 3.85357C10.978 3.85357 11.9836 4.06765 12.7748 4.52447C13.4807 4.93205 13.9615 5.50902 14.0544 6.1775L15.8813 12.0861L15.9958 12.4564L15.6656 12.6596L10.2616 15.9852L9.9995 16.1464L9.73745 15.9852L4.33339 12.6596L4.00415 12.457L4.11736 12.0873L5.96911 6.04134C6.10445 5.43072 6.56665 4.90411 7.2242 4.52447C8.01544 4.06765 9.02101 3.85357 9.9995 3.85357ZM6.49467 7.7401L5.18673 12.0105L9.4995 14.6646V8.95868C8.68544 8.8976 7.88098 8.68566 7.2242 8.30647C6.9414 8.1432 6.69474 7.95274 6.49467 7.7401ZM10.4995 8.95868V14.6646L14.8114 12.0111L13.4942 7.75085C13.2959 7.95916 13.0528 8.14595 12.7748 8.30647C12.118 8.68566 11.3136 8.8976 10.4995 8.95868Z"
fill="currentColor"
/>
</svg>
@ -1048,7 +1048,7 @@ const CustomIconMap = {
<path
fillRule="evenodd"
clipRule="evenodd"
d="M6.89927 4.693C7.36143 4.41381 7.87 4.21672 8.40842 4.10376C7.83595 4.69964 7.47 5.50199 7.47 6.31393C7.47 7.34818 8.06376 8.11443 8.9218 8.3459C8.85859 8.44278 8.80068 8.54347 8.74845 8.64757C8.69108 8.76191 8.6411 8.87927 8.59864 8.99896L9.87934 8.72674C10.0433 8.52252 10.2451 8.35006 10.4752 8.21957L10.4736 8.21676C11.6445 7.74118 12.53 6.5014 12.53 5.2384C12.53 4.20393 11.936 3.43756 11.0776 3.20628L11.0781 3.19471C9.34471 2.75461 7.64421 2.9631 6.28878 3.78191C4.93335 4.60073 4.01395 5.97492 3.69937 7.6522C3.55495 8.4222 3.54245 9.23235 3.65633 10.0495L3.88904 10L4.59283 9.85042C4.53004 9.23247 4.55179 8.62188 4.6613 8.038C4.93318 6.58836 5.7278 5.40068 6.89927 4.693ZM7.47005 15.1799C6.65634 14.4835 5.96657 13.6244 5.46142 12.6658L4.54925 12.8597L4.57626 12.9127C5.40057 14.5194 6.672 15.8914 8.18092 16.8103C8.28057 16.8945 8.38913 16.9684 8.50564 17.0308L9.08339 16.1011C8.87304 15.9884 8.70487 15.8151 8.5944 15.5972C8.48392 15.3793 8.43471 15.1238 8.45129 14.8543C8.46788 14.5848 8.54973 14.31 8.68929 14.0552C8.82885 13.8005 9.02162 13.574 9.24981 13.3967C9.47801 13.2193 9.73427 13.0969 9.99495 13.0406C10.2556 12.9843 10.5123 12.996 10.7413 13.0747C10.9608 13.15 11.1481 13.2845 11.2874 13.4665C11.7756 13.525 12.1412 13.4705 12.4217 13.3627C12.354 13.1483 12.2554 12.9503 12.128 12.7748C11.8981 12.4582 11.5819 12.225 11.2086 12.0968C11.1027 12.0605 10.9931 12.0329 10.8808 12.0141C10.6353 11.9374 10.407 11.816 10.2071 11.6571L9.0562 11.9017C9.09421 11.9513 9.13379 11.9999 9.17491 12.0473C9.2375 12.1194 9.30323 12.1884 9.37183 12.254C9.16516 12.3521 8.9652 12.4755 8.77697 12.6218C8.40494 12.9109 8.09066 13.2801 7.86313 13.6955C7.6356 14.1108 7.50216 14.5588 7.47513 14.9982C7.47137 15.0592 7.46969 15.1198 7.47005 15.1799ZM9.99038 7.3647L10 7.36268C10.8571 7.18051 11.5518 6.32252 11.5518 5.44631C11.5518 4.5701 10.8571 4.00748 10 4.18965C9.14293 4.37183 8.44815 5.22981 8.44815 6.10602C8.44815 6.9614 9.11029 7.51793 9.93915 7.37442C9.95332 7.36608 9.96757 7.35785 9.98189 7.34973L9.99038 7.3647ZM16.6 8.29822L16.1109 8.40218L14.074 8.83515V9.83515L16.1109 9.40218L16.6 9.29822V8.29822ZM7.96305 11.1341L12.037 10.2681V9.26813L7.96305 10.1341V11.1341ZM3.8891 12L5.92607 11.567V10.567L3.8891 11L3.40002 11.104V12.104L3.8891 12ZM15.4172 11.1225L15.9703 10.8085L16.0604 11.4381L16.4532 14.1827L15.5948 14.3056L15.5027 13.662L15.5423 12.9555L15.3598 13.5867C15.1404 13.9788 14.8672 14.3472 14.529 14.662C13.8137 15.3278 12.8466 15.7187 11.5898 15.635C11.3638 16.0194 10.9459 16.2774 10.4678 16.2774C9.74943 16.2774 9.16711 15.6951 9.16711 14.9767C9.16711 14.2584 9.74943 13.6761 10.4678 13.6761C11.1178 13.6761 11.6565 14.153 11.753 14.776C12.7384 14.8173 13.4355 14.4952 13.9382 14.0273C14.4048 13.5929 14.7326 13.0058 14.9513 12.384L13.4607 13.2302L13.0326 12.4761L15.4172 11.1225Z"
d="M4.97327 10C4.97327 6.80658 7.36805 4.28237 10.2454 4.28237C10.3165 4.28237 10.387 4.28406 10.4572 4.28741C10.3234 4.38231 10.1981 4.48718 10.0831 4.59971C9.66718 5.00672 9.35509 5.54523 9.28757 6.13142C9.25522 6.4123 9.28279 6.67823 9.36215 6.91776C8.7912 7.07426 8.34416 7.4985 8.05428 8.021C7.71049 8.64064 7.55775 9.44003 7.64354 10.2751C7.72936 11.1104 8.042 11.8668 8.50239 12.413C8.96051 12.9566 9.6047 13.3307 10.3298 13.2686C10.6312 13.2428 10.91 13.1468 11.1582 12.9971C11.3304 13.3048 11.6082 13.5576 11.9545 13.74C12.4863 14.0202 13.1232 14.1081 13.7186 14.0462C13.7798 14.0398 13.8412 14.0318 13.9024 14.0221C12.9641 15.0711 11.6798 15.7176 10.2454 15.7176C7.36805 15.7176 4.97327 13.1934 4.97327 10ZM10.2454 3.28237C11.2075 3.28237 12.0872 3.53636 12.8836 3.93906C12.9184 3.95564 12.9526 3.97334 12.9861 3.99218C13.5751 4.32277 13.8895 4.9548 13.8061 5.67865C13.7386 6.26484 13.4265 6.80335 13.0105 7.21036C12.5931 7.61883 12.04 7.92623 11.4392 8.0229C11.0197 8.0904 10.6153 8.04835 10.2653 7.89614L10.2521 7.89037C10.1541 7.84893 9.99432 7.83721 9.77368 7.85609C9.46998 7.88207 9.1612 8.08711 8.92871 8.50614C8.69698 8.92382 8.57054 9.51335 8.63831 10.1729C8.70605 10.8322 8.95064 11.3932 9.26703 11.7686C9.5857 12.1467 9.93784 12.2985 10.2445 12.2723C10.5632 12.245 10.8934 12.0327 11.1204 11.6221C11.1374 11.5865 11.1559 11.5513 11.1757 11.5164C11.2866 11.3214 11.438 11.1435 11.6225 10.9865C12.0767 10.6 12.6795 10.3834 13.2743 10.3216C13.8698 10.2596 14.5067 10.3475 15.0385 10.6277C15.8132 11.0358 16.2217 11.8039 15.935 12.5969C15.9205 12.6369 15.9045 12.6763 15.8868 12.7152C14.9186 15.0185 12.8217 16.7176 10.2454 16.7176C6.74706 16.7176 3.97327 13.6744 3.97327 10C3.97327 6.32561 6.74706 3.28237 10.2454 3.28237ZM12.5022 4.86738C12.4834 4.85752 12.4645 4.84778 12.4455 4.83814C12.2919 4.76722 12.0795 4.73165 11.8133 4.77448C11.4407 4.83443 11.0707 5.03242 10.7825 5.31444C10.4928 5.59793 10.3168 5.93501 10.281 6.24584C10.2381 6.61795 10.4 6.86003 10.6545 6.97486L10.6664 6.9801C10.8179 7.04538 11.0245 7.07676 11.2803 7.0356C11.653 6.97564 12.0229 6.77766 12.3111 6.49563C12.6008 6.21215 12.7768 5.87507 12.8127 5.56423C12.8526 5.21705 12.7138 4.98872 12.5022 4.86738ZM12.0511 12.0001C12.0391 12.0242 12.0267 12.0482 12.014 12.0719C11.9553 12.2043 11.9565 12.3248 11.9952 12.4311C12.0421 12.5603 12.1642 12.7202 12.4206 12.8553C12.7448 13.0261 13.1759 13.0972 13.6152 13.0515C14.055 13.0058 14.4537 12.8483 14.7224 12.6196C14.8489 12.512 14.927 12.4058 14.9718 12.3114C14.9803 12.2909 14.9888 12.2703 14.9971 12.2497C15.0698 12.0387 15.0148 11.7455 14.5723 11.5124C14.2481 11.3416 13.817 11.2705 13.3778 11.3162C12.9379 11.3619 12.5392 11.5195 12.2706 11.7481C12.1687 11.8348 12.098 11.9208 12.0511 12.0001Z"
fill="currentColor"
/>
</svg>
@ -1148,7 +1148,7 @@ const CustomIconMap = {
<path
fillRule="evenodd"
clipRule="evenodd"
d="M15.4743 3.19282L15.7063 2.49694L14.9738 2.53539L11.7806 2.703L11.833 3.70162L12.2189 3.68137L13.0309 3.47351L12.4065 3.79549C11.5985 4.23813 10.7423 4.7732 10.0381 5.41523C9.28624 6.1008 8.66584 6.94665 8.50598 7.97341C8.36948 8.8502 8.57961 9.78564 9.20597 10.7756C9.07507 10.9983 9 11.2577 9 11.5347C9 12.3631 9.67157 13.0347 10.5 13.0347C11.3284 13.0347 12 12.3631 12 11.5347C12 10.7063 11.3284 10.0347 10.5 10.0347C10.3174 10.0347 10.1425 10.0673 9.98067 10.127C9.51409 9.34655 9.40701 8.68651 9.49408 8.12725C9.60506 7.41442 10.0472 6.76028 10.7119 6.15418C11.3749 5.54964 12.218 5.03092 13.0491 4.58458C13.4267 4.38176 13.797 4.19644 14.1426 4.02567L13.5257 5.87659L14.4743 6.19282L15.4743 3.19282ZM10.4854 8.10284C10.4627 8.2645 10.4579 8.44276 10.4848 8.63934L15.0823 11.4489L10 14.5548L4.91773 11.4489L7.66526 9.76987C7.56422 9.41819 7.50187 9.06536 7.47765 8.71258L3.95886 10.8629L3 11.4489V13.5031H4V12.06L9.5 15.4211V17.5031H10.5V15.4211L16 12.06V13.5031H17L17 11.4489L16.0411 10.8629L10.6351 7.55929C10.5598 7.74567 10.5101 7.92698 10.4854 8.10284Z"
d="M13.2244 5.21542C12.7054 5.21541 12.2135 5.33116 11.8622 5.53399C11.5544 5.7117 11.4656 5.8865 11.4482 5.98748L11.4492 6.07746C11.469 6.18657 11.5595 6.35486 11.8622 6.5296C12.2135 6.73243 12.7054 6.84817 13.2244 6.84817C13.7434 6.84817 14.2354 6.73243 14.5867 6.5296C14.8973 6.35026 14.9846 6.17771 15.0011 6.06896V5.98963C14.9845 5.88898 14.8967 5.71296 14.5867 5.53399C14.2354 5.33116 13.7434 5.21542 13.2244 5.21542ZM16.0011 6.13177C16.0065 6.06023 16.0059 5.98711 15.9988 5.91256C15.9489 5.38456 15.5851 4.95575 15.0867 4.66796C14.5476 4.35671 13.8725 4.21542 13.2244 4.21542C12.5764 4.21541 11.9013 4.35671 11.3622 4.66796C10.8637 4.95575 10.4999 5.38455 10.45 5.91255C10.4421 5.99636 10.4424 6.07837 10.4501 6.15834L10.4658 7.50046L7.9749 6.14153L7.96667 6.13704L7.95828 6.13286C6.85997 5.58608 5.83833 5.76171 5.10363 6.3622C4.39705 6.9397 3.99599 7.87502 3.99599 8.80303V13.9334C3.97948 14.5257 4.3658 15.0159 4.91332 15.332C5.45242 15.6433 6.12752 15.7846 6.77554 15.7846C7.42356 15.7846 8.09866 15.6433 8.63776 15.332C9.18527 15.0159 9.57161 14.5257 9.55509 13.9334L9.5551 12.8862L11.8715 14.1386L11.8813 14.1439L11.8914 14.1488C13.0016 14.6864 14.036 14.6066 14.8049 14.1168C15.5567 13.6378 16.0011 12.7977 16.0011 11.9264L16.0011 6.13177ZM15.0011 7.44303C14.4771 7.72126 13.8386 7.84817 13.2244 7.84817C12.6171 7.84817 11.986 7.72406 11.4653 7.45225L11.4757 8.34239L11.4758 8.35085L11.4756 8.35932L11.4477 9.62112L10.4479 9.59897L10.4692 8.64142L7.50456 7.02407C6.75157 6.65229 6.15623 6.7934 5.73647 7.13648C5.28711 7.50376 4.99599 8.1415 4.99599 8.80303V13.9411V13.95L4.99568 13.9588C4.99232 14.0538 5.04963 14.256 5.41332 14.466C5.76463 14.6688 6.25654 14.7846 6.77554 14.7846C7.29453 14.7846 7.78644 14.6688 8.13776 14.466C8.50145 14.256 8.55877 14.0538 8.55541 13.9588L8.55509 13.95V13.9411L8.5551 12.3442L7.78422 11.9237L8.26314 11.0458L9.29291 11.6076L9.29456 11.6085L12.337 13.2535C13.1716 13.6544 13.8297 13.5524 14.2676 13.2734C14.7242 12.9825 15.0011 12.4644 15.0011 11.9264L15.0011 7.44303Z"
fill="currentColor"
/>
</svg>

View File

@ -517,10 +517,7 @@ interface FileTreeProps {
className?: string
file?: IndexLoaderData['file']
onNavigateToFile: (
focusableElement?:
| HTMLElement
| React.MutableRefObject<HTMLElement | null>
| undefined
focusableElement?: HTMLElement | React.MutableRefObject<HTMLElement | null>
) => void
}

View File

@ -1431,7 +1431,6 @@ export const ModelingMachineProvider = ({
parsed = pResult.program
if (trap(parsed)) return Promise.reject(parsed)
parsed = parsed as Node<Program>
if (!result.pathToReplaced)
return Promise.reject(new Error('No path to replaced node'))
const {

View File

@ -1,11 +1,11 @@
import { Dialog } from '@headlessui/react'
import { ActionButton } from 'components/ActionButton'
interface DeleteConfirmationDialogProps extends React.PropsWithChildren<{}> {
type DeleteConfirmationDialogProps = React.PropsWithChildren<{
title: string
onConfirm: () => void
onDismiss: () => void
}
}>
export function DeleteConfirmationDialog({
title,

View File

@ -6,7 +6,7 @@ import {
import { ForwardedRef, forwardRef } from 'react'
import { useLocation } from 'react-router-dom'
interface AllKeybindingsFieldsProps {}
type AllKeybindingsFieldsProps = object
export const AllKeybindingsFields = forwardRef(
(

View File

@ -8,9 +8,9 @@ export const NODE_ENV = env.NODE_ENV as string | undefined
export const VITE_KC_API_WS_MODELING_URL = env.VITE_KC_API_WS_MODELING_URL as
| string
| undefined
export const VITE_KC_API_BASE_URL = env.VITE_KC_API_BASE_URL as string
export const VITE_KC_SITE_BASE_URL = env.VITE_KC_SITE_BASE_URL as string
export const VITE_KC_SITE_APP_URL = env.VITE_KC_SITE_APP_URL as string
export const VITE_KC_API_BASE_URL = env.VITE_KC_API_BASE_URL
export const VITE_KC_SITE_BASE_URL = env.VITE_KC_SITE_BASE_URL
export const VITE_KC_SITE_APP_URL = env.VITE_KC_SITE_APP_URL
export const VITE_KC_SKIP_AUTH = env.VITE_KC_SKIP_AUTH as string | undefined
export const VITE_KC_CONNECTION_TIMEOUT_MS =
env.VITE_KC_CONNECTION_TIMEOUT_MS as string | undefined

View File

@ -811,40 +811,53 @@ export function addOffsetPlane({
*/
export function addHelix({
node,
axis,
cylinder,
revolutions,
angleStart,
ccw,
radius,
axis,
length,
ccw,
insertIndex,
variableName,
}: {
node: Node<Program>
axis?: Node<Literal> | Node<Name | CallExpression | CallExpressionKw>
cylinder?: VariableDeclarator
revolutions: Expr
angleStart: Expr
radius?: Expr
length?: Expr
ccw: boolean
radius: Expr
axis: Node<Literal> | Node<Name | CallExpression | CallExpressionKw>
length: Expr
insertIndex?: number
variableName?: string
}): { modifiedAst: Node<Program>; pathToNode: PathToNode } {
const modifiedAst = structuredClone(node)
const name =
variableName ?? findUniqueName(node, KCL_DEFAULT_CONSTANT_PREFIXES.HELIX)
const modeArgs: CallExpressionKw['arguments'] = []
if (axis && radius) {
modeArgs.push(createLabeledArg('axis', axis))
modeArgs.push(createLabeledArg('radius', radius))
if (length) {
modeArgs.push(createLabeledArg('length', length))
}
} else if (cylinder) {
modeArgs.push(
createLabeledArg('cylinder', createLocalName(cylinder.id.name))
)
}
const variable = createVariableDeclaration(
name,
createCallExpressionStdLibKw(
'helix',
null, // Not in a pipeline
[
...modeArgs,
createLabeledArg('revolutions', revolutions),
createLabeledArg('angleStart', angleStart),
createLabeledArg('ccw', createLiteral(ccw)),
createLabeledArg('radius', radius),
createLabeledArg('axis', axis),
createLabeledArg('length', length),
]
)
)

View File

@ -320,6 +320,7 @@ export function mutateAstWithTagForSketchSegment(
// Check whether selection is a valid segment
if (
!segmentNode.node.callee ||
!(
segmentNode.node.callee.name.name in sketchLineHelperMap ||
segmentNode.node.callee.name.name in sketchLineHelperMapKw

View File

@ -4,9 +4,7 @@ import {
Program,
PathToNode,
Expr,
CallExpression,
VariableDeclarator,
CallExpressionKw,
ArtifactGraph,
} from 'lang/wasm'
import { Selections } from 'lib/selections'
@ -47,13 +45,6 @@ export function getAxisExpressionAndIndex(
ast,
edge.graphSelections[0]?.codeRef.range
)
const lineNode = getNodeFromPath<CallExpression | CallExpressionKw>(
ast,
pathToAxisSelection,
['CallExpression', 'CallExpressionKw']
)
if (err(lineNode)) return lineNode
const tagResult = mutateAstWithTagForSketchSegment(ast, pathToAxisSelection)
// Have the tag whether it is already created or a new one is generated
@ -90,12 +81,14 @@ export function getAxisExpressionAndIndex(
export function revolveSketch(
ast: Node<Program>,
pathToSketchNode: PathToNode,
angle: Expr = createLiteral(4),
angle: Expr,
axisOrEdge: 'Axis' | 'Edge',
axis: string,
edge: Selections,
axis: string | undefined,
edge: Selections | undefined,
artifactGraph: ArtifactGraph,
artifact?: Artifact
artifact?: Artifact,
variableName?: string,
insertIndex?: number
):
| {
modifiedAst: Node<Program>
@ -121,7 +114,12 @@ export function revolveSketch(
if (err(sketchVariableDeclaratorNode)) return sketchVariableDeclaratorNode
const { node: sketchVariableDeclarator } = sketchVariableDeclaratorNode
const getAxisResult = getAxisExpressionAndIndex(axisOrEdge, axis, edge, ast)
const getAxisResult = getAxisExpressionAndIndex(
axisOrEdge,
axis,
edge,
clonedAst
)
if (err(getAxisResult)) return getAxisResult
const { generatedAxis, axisIndexIfAxis } = getAxisResult
if (!generatedAxis) return new Error('Generated axis selection is missing.')
@ -134,21 +132,30 @@ export function revolveSketch(
// We're not creating a pipe expression,
// but rather a separate constant for the extrusion
const name = findUniqueName(clonedAst, KCL_DEFAULT_CONSTANT_PREFIXES.REVOLVE)
const VariableDeclaration = createVariableDeclaration(name, revolveCall)
const lastSketchNodePath =
orderedSketchNodePaths[orderedSketchNodePaths.length - 1]
let sketchIndexInBody = Number(lastSketchNodePath[1][0])
if (typeof sketchIndexInBody !== 'number') {
return new Error('expected sketchIndexInBody to be a number')
const name =
variableName ??
findUniqueName(clonedAst, KCL_DEFAULT_CONSTANT_PREFIXES.REVOLVE)
const declaration = createVariableDeclaration(name, revolveCall)
let sketchIndexInBody: number | undefined
// If it's an edit flow (no change on selection yet)
if (insertIndex) {
sketchIndexInBody = insertIndex
} else {
const lastSketchNodePath =
orderedSketchNodePaths[orderedSketchNodePaths.length - 1]
sketchIndexInBody = Number(lastSketchNodePath[1][0])
if (typeof sketchIndexInBody !== 'number') {
return new Error('expected sketchIndexInBody to be a number')
}
// If an axis was selected in KCL, find the max index to insert the revolve command
if (axisIndexIfAxis) {
sketchIndexInBody = Math.max(sketchIndexInBody, axisIndexIfAxis)
}
}
// If an axis was selected in KCL, find the max index to insert the revolve command
if (axisIndexIfAxis) {
sketchIndexInBody = Math.max(sketchIndexInBody, axisIndexIfAxis)
}
clonedAst.body.splice(sketchIndexInBody + 1, 0, VariableDeclaration)
clonedAst.body.splice(sketchIndexInBody + 1, 0, declaration)
const pathToRevolveArg: PathToNode = [
['body', ''],

View File

@ -0,0 +1,338 @@
import { Node } from '@rust/kcl-lib/bindings/Node'
import EditorManager from 'editor/manager'
import CodeManager from 'lang/codeManager'
import { KclManager } from 'lang/KclSingleton'
import { updateModelingState } from 'lang/modelingWorkflows'
import {
createArrayExpression,
createCallExpressionStdLibKw,
createLabeledArg,
createLocalName,
createVariableDeclaration,
findUniqueName,
} from 'lang/modifyAst'
import { getNodeFromPath } from 'lang/queryAst'
import { getNodePathFromSourceRange } from 'lang/queryAstNodePathUtils'
import { getFaceCodeRef } from 'lang/std/artifactGraph'
import { EngineCommandManager } from 'lang/std/engineConnection'
import {
Artifact,
ArtifactGraph,
Program,
VariableDeclaration,
} from 'lang/wasm'
import { EXECUTION_TYPE_REAL } from 'lib/constants'
import { Selection, Selections } from 'lib/selections'
import { err } from 'lib/trap'
import { isArray } from 'lib/utils'
export async function applySubtractFromTargetOperatorSelections(
target: Selection,
tool: Selection,
dependencies: {
kclManager: KclManager
engineCommandManager: EngineCommandManager
codeManager: CodeManager
editorManager: EditorManager
}
): Promise<Error | void> {
const ast = dependencies.kclManager.ast
if (!target.artifact || !tool.artifact) {
return new Error('No artifact found')
}
const orderedChildrenTarget = findAllChildrenAndOrderByPlaceInCode(
target.artifact,
dependencies.engineCommandManager.artifactGraph
)
const orderedChildrenTool = findAllChildrenAndOrderByPlaceInCode(
tool.artifact,
dependencies.engineCommandManager.artifactGraph
)
const lastVarTarget = getLastVariable(orderedChildrenTarget, ast)
const lastVarTool = getLastVariable(orderedChildrenTool, ast)
if (!lastVarTarget || !lastVarTool) {
return new Error('No variable found')
}
const modifiedAst = booleanSubtractAstMod({
ast,
targets: [lastVarTarget?.variableDeclaration?.node],
tools: [lastVarTool?.variableDeclaration.node],
})
await updateModelingState(modifiedAst, EXECUTION_TYPE_REAL, dependencies)
}
export async function applyUnionFromTargetOperatorSelections(
solids: Selections,
dependencies: {
kclManager: KclManager
engineCommandManager: EngineCommandManager
codeManager: CodeManager
editorManager: EditorManager
}
): Promise<Error | void> {
const ast = dependencies.kclManager.ast
const artifacts: Artifact[] = []
for (const selection of solids.graphSelections) {
if (selection.artifact) {
artifacts.push(selection.artifact)
}
}
if (artifacts.length < 2) {
return new Error('Not enough artifacts selected')
}
const orderedChildrenEach = artifacts.map((artifact) =>
findAllChildrenAndOrderByPlaceInCode(
artifact,
dependencies.engineCommandManager.artifactGraph
)
)
const lastVars: VariableDeclaration[] = []
for (const orderedArtifactLeafs of orderedChildrenEach) {
const lastVar = getLastVariable(orderedArtifactLeafs, ast)
if (!lastVar) continue
lastVars.push(lastVar.variableDeclaration.node)
}
if (lastVars.length < 2) {
return new Error('Not enough variables found')
}
const modifiedAst = booleanUnionAstMod({
ast,
solids: lastVars,
})
await updateModelingState(modifiedAst, EXECUTION_TYPE_REAL, dependencies)
}
export async function applyIntersectFromTargetOperatorSelections(
solids: Selections,
dependencies: {
kclManager: KclManager
engineCommandManager: EngineCommandManager
codeManager: CodeManager
editorManager: EditorManager
}
): Promise<Error | void> {
const ast = dependencies.kclManager.ast
const artifacts: Artifact[] = []
for (const selection of solids.graphSelections) {
if (selection.artifact) {
artifacts.push(selection.artifact)
}
}
if (artifacts.length < 2) {
return new Error('Not enough artifacts selected')
}
const orderedChildrenEach = artifacts.map((artifact) =>
findAllChildrenAndOrderByPlaceInCode(
artifact,
dependencies.engineCommandManager.artifactGraph
)
)
const lastVars: VariableDeclaration[] = []
for (const orderedArtifactLeafs of orderedChildrenEach) {
const lastVar = getLastVariable(orderedArtifactLeafs, ast)
if (!lastVar) continue
lastVars.push(lastVar.variableDeclaration.node)
}
if (lastVars.length < 2) {
return new Error('Not enough variables found')
}
const modifiedAst = booleanIntersectAstMod({
ast,
solids: lastVars,
})
await updateModelingState(modifiedAst, EXECUTION_TYPE_REAL, dependencies)
}
/** returns all children of a given artifact, and sorts them DESC by start sourceRange
* The usecase is we want the last declare relevant child to use in the boolean operations
* but might be useful else where.
*/
export function findAllChildrenAndOrderByPlaceInCode(
artifact: Artifact,
artifactGraph: ArtifactGraph
): Artifact[] {
const result: string[] = []
const stack: string[] = [artifact.id]
const getArtifacts = (stringIds: string[]): Artifact[] => {
const artifactsWithCodeRefs: Artifact[] = []
for (const id of stringIds) {
const artifact = artifactGraph.get(id)
if (artifact) {
const codeRef = getFaceCodeRef(artifact)
if (codeRef && codeRef.range[1] > 0) {
artifactsWithCodeRefs.push(artifact)
}
}
}
return artifactsWithCodeRefs
}
const pushToSomething = (
resultId: string,
childrenIdOrIds: null | string | string[]
) => {
if (isArray(childrenIdOrIds)) {
if (childrenIdOrIds.length) {
stack.push(...childrenIdOrIds)
result.push(resultId)
} else {
}
} else {
if (childrenIdOrIds) {
stack.push(childrenIdOrIds)
result.push(resultId)
} else {
}
}
}
while (stack.length > 0) {
const currentId = stack.pop()!
const current = artifactGraph.get(currentId)
if (current?.type === 'path') {
pushToSomething(currentId, current?.sweepId)
pushToSomething(currentId, current?.segIds)
} else if (current?.type === 'sweep') {
pushToSomething(currentId, current?.surfaceIds)
} else if (current?.type === 'wall' || current?.type === 'cap') {
pushToSomething(currentId, current?.pathIds)
} else if (current?.type === 'segment') {
pushToSomething(currentId, current?.edgeCutId)
pushToSomething(currentId, current?.surfaceId)
} else if (current?.type === 'edgeCut') {
pushToSomething(currentId, current?.surfaceId)
} else if (current?.type === 'startSketchOnPlane') {
pushToSomething(currentId, current?.planeId)
} else if (current?.type === 'plane') {
pushToSomething(currentId, current.pathIds)
}
}
const codeRefArtifacts = getArtifacts(result)
const orderedByCodeRefDest = codeRefArtifacts.sort((a, b) => {
const aCodeRef = getFaceCodeRef(a)
const bCodeRef = getFaceCodeRef(b)
if (!aCodeRef || !bCodeRef) {
return 0
}
return bCodeRef.range[0] - aCodeRef.range[0]
})
return orderedByCodeRefDest
}
/** Returns the last declared in code, relevant child */
export function getLastVariable(
orderedDescArtifacts: Artifact[],
ast: Node<Program>
) {
for (const artifact of orderedDescArtifacts) {
const codeRef = getFaceCodeRef(artifact)
if (codeRef) {
const pathToNode = getNodePathFromSourceRange(ast, codeRef.range)
const varDec = getNodeFromPath<VariableDeclaration>(
ast,
pathToNode,
'VariableDeclaration'
)
if (!err(varDec)) {
return {
variableDeclaration: varDec,
pathToNode: pathToNode,
artifact,
}
}
}
}
return null
}
export function booleanSubtractAstMod({
ast,
targets,
tools,
}: {
ast: Node<Program>
targets: VariableDeclaration[]
tools: VariableDeclaration[]
}): Node<Program> {
const newAst = structuredClone(ast)
const newVarName = findUniqueName(newAst, 'solid')
const createArrExpr = (varDecs: VariableDeclaration[]) =>
createArrayExpression(
varDecs.map((varDec) => createLocalName(varDec.declaration.id.name))
)
const targetsArrayExpression = createArrExpr(targets)
const toolsArrayExpression = createArrExpr(tools)
const newVarDec = createVariableDeclaration(
newVarName,
createCallExpressionStdLibKw('subtract', targetsArrayExpression, [
createLabeledArg('tools', toolsArrayExpression),
])
)
newAst.body.push(newVarDec)
return newAst
}
export function booleanUnionAstMod({
ast,
solids,
}: {
ast: Node<Program>
solids: VariableDeclaration[]
}): Node<Program> {
const newAst = structuredClone(ast)
const newVarName = findUniqueName(newAst, 'solid')
const createArrExpr = (varDecs: VariableDeclaration[]) =>
createArrayExpression(
varDecs.map((varDec) => createLocalName(varDec.declaration.id.name))
)
const solidsArrayExpression = createArrExpr(solids)
const newVarDec = createVariableDeclaration(
newVarName,
createCallExpressionStdLibKw('union', solidsArrayExpression, [])
)
newAst.body.push(newVarDec)
return newAst
}
export function booleanIntersectAstMod({
ast,
solids,
}: {
ast: Node<Program>
solids: VariableDeclaration[]
}): Node<Program> {
const newAst = structuredClone(ast)
const newVarName = findUniqueName(newAst, 'solid')
const createArrExpr = (varDecs: VariableDeclaration[]) =>
createArrayExpression(
varDecs.map((varDec) => createLocalName(varDec.declaration.id.name))
)
const solidsArrayExpression = createArrExpr(solids)
const newVarDec = createVariableDeclaration(
newVarName,
createCallExpressionStdLibKw('intersect', solidsArrayExpression, [])
)
newAst.body.push(newVarDec)
return newAst
}

View File

@ -23,6 +23,8 @@ import {
import { getVariableDeclaration } from 'lang/queryAst/getVariableDeclaration'
import { getNodePathFromSourceRange } from 'lang/queryAstNodePathUtils'
import { getNodeFromPath } from 'lang/queryAst'
import { IS_NIGHTLY_OR_DEBUG } from 'routes/Settings'
import { DEV } from 'env'
type OutputFormat = Models['OutputFormat3d_type']
type OutputTypeKey = OutputFormat['type']
@ -38,8 +40,10 @@ export const EXTRUSION_RESULTS = [
export const COMMAND_APPEARANCE_COLOR_DEFAULT = 'default'
export type HelixModes = 'Axis' | 'Edge' | 'Cylinder'
export type ModelingCommandSchema = {
'Enter sketch': {}
'Enter sketch': { forceNewSketch?: boolean }
Export: {
type: OutputTypeKey
storage?: StorageUnion
@ -73,11 +77,15 @@ export type ModelingCommandSchema = {
thickness: KclCommandValue
}
Revolve: {
// Enables editing workflow
nodeToEdit?: PathToNode
// Flow arg
axisOrEdge: 'Axis' | 'Edge'
// KCL stdlib arguments
selection: Selections
angle: KclCommandValue
axisOrEdge: 'Axis' | 'Edge'
axis: string
edge: Selections
axis: string | undefined
edge: Selections | undefined
}
Fillet: {
// Enables editing workflow
@ -103,15 +111,17 @@ export type ModelingCommandSchema = {
// Enables editing workflow
nodeToEdit?: PathToNode
// Flow arg
axisOrEdge: 'Axis' | 'Edge'
mode: HelixModes
// Three different arguments depending on mode
axis?: string
edge?: Selections
cylinder?: Selections
// KCL stdlib arguments
axis: string | undefined
edge: Selections | undefined
revolutions: KclCommandValue
angleStart: KclCommandValue
ccw: boolean
radius: KclCommandValue
length: KclCommandValue
radius?: KclCommandValue // axis or edge modes only
length?: KclCommandValue // axis or edge modes only
ccw: boolean // optional boolean argument, default value to false
}
'event.parameter.create': {
value: KclCommandValue
@ -142,11 +152,23 @@ export type ModelingCommandSchema = {
prompt: string
selection: Selections
}
// TODO: {} means any non-nullish value. This is probably not what we want.
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
'Delete selection': {}
Appearance: {
nodeToEdit?: PathToNode
color: string
}
'Boolean Subtract': {
target: Selections
tool: Selections
}
'Boolean Union': {
solids: Selections
}
'Boolean Intersect': {
solids: Selections
}
}
export const modelingMachineCommandConfig: StateMachineCommandSetConfig<
@ -322,7 +344,7 @@ export const modelingMachineCommandConfig: StateMachineCommandSetConfig<
defaultValue: (commandBarContext) => {
return Object.values(
commandBarContext.machineManager.machines || []
)[0] as components['schemas']['MachineInfoResponse']
)[0]
},
},
},
@ -454,6 +476,13 @@ export const modelingMachineCommandConfig: StateMachineCommandSetConfig<
icon: 'revolve',
needsReview: true,
args: {
nodeToEdit: {
description:
'Path to the node in the AST to edit. Never shown to the user.',
skip: true,
inputType: 'text',
required: false,
},
selection: {
inputType: 'selection',
selectionTypes: ['solid2d', 'segment'],
@ -482,6 +511,7 @@ export const modelingMachineCommandConfig: StateMachineCommandSetConfig<
{ name: 'X Axis', isCurrent: true, value: 'X' },
{ name: 'Y Axis', isCurrent: false, value: 'Y' },
],
hidden: (context) => Boolean(context.argumentsToSubmit.nodeToEdit),
},
edge: {
required: (commandContext) =>
@ -501,6 +531,67 @@ export const modelingMachineCommandConfig: StateMachineCommandSetConfig<
},
},
},
'Boolean Subtract': {
hide: DEV || IS_NIGHTLY_OR_DEBUG ? undefined : 'both',
description: 'Subtract one solid from another.',
icon: 'booleanSubtract',
needsReview: true,
args: {
target: {
inputType: 'selection',
selectionTypes: ['path'],
selectionFilter: ['object'],
multiple: false,
required: true,
skip: true,
hidden: (context) => Boolean(context.argumentsToSubmit.nodeToEdit),
},
tool: {
clearSelectionFirst: true,
inputType: 'selection',
selectionTypes: ['path'],
selectionFilter: ['object'],
multiple: false,
required: true,
skip: false,
hidden: (context) => Boolean(context.argumentsToSubmit.nodeToEdit),
},
},
},
'Boolean Union': {
hide: DEV || IS_NIGHTLY_OR_DEBUG ? undefined : 'both',
description: 'Union multiple solids into a single solid.',
icon: 'booleanUnion',
needsReview: true,
args: {
solids: {
inputType: 'selection',
selectionTypes: ['path'],
selectionFilter: ['object'],
multiple: true,
required: true,
skip: false,
hidden: (context) => Boolean(context.argumentsToSubmit.nodeToEdit),
},
},
},
'Boolean Intersect': {
hide: DEV || IS_NIGHTLY_OR_DEBUG ? undefined : 'both',
description: 'Subtract one solid from another.',
icon: 'booleanIntersect',
needsReview: true,
args: {
solids: {
inputType: 'selectionMixed',
selectionTypes: ['path'],
selectionFilter: ['object'],
multiple: true,
required: true,
skip: false,
hidden: (context) => Boolean(context.argumentsToSubmit.nodeToEdit),
},
},
},
'Offset plane': {
description: 'Offset a plane.',
icon: 'plane',
@ -530,7 +621,6 @@ export const modelingMachineCommandConfig: StateMachineCommandSetConfig<
Helix: {
description: 'Create a helix or spiral in 3D about an axis.',
icon: 'helix',
status: 'development',
needsReview: true,
args: {
nodeToEdit: {
@ -541,69 +631,89 @@ export const modelingMachineCommandConfig: StateMachineCommandSetConfig<
required: false,
hidden: true,
},
axisOrEdge: {
mode: {
inputType: 'options',
required: true,
defaultValue: 'Axis',
options: [
{ name: 'Axis', isCurrent: true, value: 'Axis' },
{ name: 'Edge', isCurrent: false, value: 'Edge' },
{ name: 'Cylinder', isCurrent: false, value: 'Cylinder' },
],
hidden: (context) => Boolean(context.argumentsToSubmit.nodeToEdit),
},
axis: {
inputType: 'options',
required: (commandContext) =>
['Axis'].includes(
commandContext.argumentsToSubmit.axisOrEdge as string
),
['Axis'].includes(commandContext.argumentsToSubmit.mode as string),
options: [
{ name: 'X Axis', value: 'X' },
{ name: 'Y Axis', value: 'Y' },
{ name: 'Z Axis', value: 'Z' },
],
hidden: false, // for consistency here, we can actually edit here since it's not a selection
},
edge: {
required: (commandContext) =>
['Edge'].includes(
commandContext.argumentsToSubmit.axisOrEdge as string
),
['Edge'].includes(commandContext.argumentsToSubmit.mode as string),
inputType: 'selection',
selectionTypes: ['segment', 'sweepEdge'],
multiple: false,
hidden: (context) => Boolean(context.argumentsToSubmit.nodeToEdit),
},
cylinder: {
required: (commandContext) =>
['Cylinder'].includes(
commandContext.argumentsToSubmit.mode as string
),
inputType: 'selection',
selectionTypes: ['wall'],
multiple: false,
hidden: (context) => Boolean(context.argumentsToSubmit.nodeToEdit),
},
revolutions: {
inputType: 'kcl',
defaultValue: '1',
required: true,
warningMessage:
'The helix workflow is new and under tested. Please break it and report issues.',
},
angleStart: {
inputType: 'kcl',
defaultValue: KCL_DEFAULT_DEGREE,
required: true,
},
ccw: {
inputType: 'options',
required: true,
displayName: 'CounterClockWise',
defaultValue: false,
options: [
{ name: 'False', value: false },
{ name: 'True', value: true },
],
},
radius: {
inputType: 'kcl',
defaultValue: KCL_DEFAULT_LENGTH,
required: true,
required: (commandContext) =>
!['Cylinder'].includes(
commandContext.argumentsToSubmit.mode as string
),
},
length: {
inputType: 'kcl',
defaultValue: KCL_DEFAULT_LENGTH,
required: (commandContext) =>
['Axis'].includes(commandContext.argumentsToSubmit.mode as string),
},
ccw: {
inputType: 'options',
skip: true,
required: true,
defaultValue: false,
valueSummary: (value) => String(value),
displayName: 'CounterClockWise',
options: (commandContext) => [
{
name: 'False',
value: false,
isCurrent: !Boolean(commandContext.argumentsToSubmit.ccw),
},
{
name: 'True',
value: true,
isCurrent: Boolean(commandContext.argumentsToSubmit.ccw),
},
],
},
},
},
@ -913,3 +1023,5 @@ export const modelingMachineCommandConfig: StateMachineCommandSetConfig<
},
},
}
modelingMachineCommandConfig

View File

@ -4,7 +4,7 @@ import { isDesktop } from 'lib/isDesktop'
import { projectsMachine } from 'machines/projectsMachine'
export type ProjectsCommandSchema = {
'Read projects': {}
'Read projects': Record<string, unknown>
'Create project': {
name: string
}
@ -74,8 +74,8 @@ export const projectsCommandBarConfig: StateMachineCommandSetConfig<
required: true,
options: (_, context) =>
context?.projects.map((p) => ({
name: p.name!,
value: p.name!,
name: p.name,
value: p.name,
})) || [],
},
},
@ -91,8 +91,8 @@ export const projectsCommandBarConfig: StateMachineCommandSetConfig<
required: true,
options: (_, context) =>
context?.projects.map((p) => ({
name: p.name!,
value: p.name!,
name: p.name,
value: p.name,
})) || [],
},
newName: {
@ -136,8 +136,8 @@ export const projectsCommandBarConfig: StateMachineCommandSetConfig<
skip: true,
options: (_, context) =>
context?.projects.map((p) => ({
name: p.name!,
value: p.name!,
name: p.name,
value: p.name,
})) || [],
},
name: {

View File

@ -1,14 +1,14 @@
import { CustomIconName } from 'components/CustomIcon'
import { AllMachines } from 'hooks/useStateMachineCommands'
import { Actor, AnyStateMachine, ContextFrom, EventFrom } from 'xstate'
import { Expr, VariableDeclaration } from 'lang/wasm'
import { Expr, Name, VariableDeclaration } from 'lang/wasm'
import { commandBarMachine } from 'machines/commandBarMachine'
import { ReactNode } from 'react'
import { MachineManager } from 'components/MachineManagerProvider'
import { Node } from '@rust/kcl-lib/bindings/Node'
import { Artifact } from 'lang/std/artifactGraph'
import { CommandBarContext } from 'machines/commandBarMachine'
import { Name } from '@rust/kcl-lib/bindings/Name'
import { EntityType_type } from '@kittycad/lib/dist/types/src/models'
type Icon = CustomIconName
const _PLATFORMS = ['both', 'web', 'desktop'] as const
@ -160,6 +160,8 @@ export type CommandArgumentConfig<
| {
inputType: 'selection'
selectionTypes: Artifact['type'][]
clearSelectionFirst?: boolean
selectionFilter?: EntityType_type[]
multiple: boolean
validation?: ({
data,
@ -172,6 +174,7 @@ export type CommandArgumentConfig<
| {
inputType: 'selectionMixed'
selectionTypes: Artifact['type'][]
selectionFilter?: EntityType_type[]
multiple: boolean
allowNoSelection?: boolean
validation?: ({
@ -281,6 +284,8 @@ export type CommandArgument<
| {
inputType: 'selection'
selectionTypes: Artifact['type'][]
clearSelectionFirst?: boolean
selectionFilter?: EntityType_type[]
multiple: boolean
validation?: ({
data,
@ -293,6 +298,7 @@ export type CommandArgument<
| {
inputType: 'selectionMixed'
selectionTypes: Artifact['type'][]
selectionFilter?: EntityType_type[]
multiple: boolean
allowNoSelection?: boolean
validation?: ({

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