Compare commits

..

3 Commits

Author SHA1 Message Date
87dfda28a9 Move axes to std constants; move helix, revolve, and mirror2d to be declated in KCL
Signed-off-by: Nick Cameron <nrc@ncameron.org>
2025-04-02 17:05:28 +13:00
42f44e11f5 Add Edge type to std
Signed-off-by: Nick Cameron <nrc@ncameron.org>
2025-03-28 11:18:10 +08:00
16ad7ff77a Move turns to a submodule of std
Signed-off-by: Nick Cameron <nrc@ncameron.org>
2025-03-28 11:10:51 +08:00
537 changed files with 24884 additions and 53229 deletions

View File

@ -20,20 +20,9 @@
"plugin:react-hooks/recommended" "plugin:react-hooks/recommended"
], ],
"rules": { "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-empty-object-type": "error",
"@typescript-eslint/no-floating-promises": "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-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", { "@typescript-eslint/no-unused-vars": ["error", {
"varsIgnorePattern": "^_", "varsIgnorePattern": "^_",
"argsIgnorePattern": "^_", "argsIgnorePattern": "^_",
@ -41,7 +30,6 @@
"vars": "all", "vars": "all",
"args": "none" "args": "none"
}], }],
"@typescript-eslint/prefer-as-const": "warn",
"jsx-a11y/click-events-have-key-events": "off", "jsx-a11y/click-events-have-key-events": "off",
"jsx-a11y/no-autofocus": "off", "jsx-a11y/no-autofocus": "off",
"jsx-a11y/no-noninteractive-element-interactions": "off", "jsx-a11y/no-noninteractive-element-interactions": "off",

View File

@ -229,6 +229,10 @@ jobs:
timeout_minutes: 30 timeout_minutes: 30
max_attempts: 3 max_attempts: 3
env: env:
CI: true
NODE_ENV: development
VITE_KC_DEV_TOKEN: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
VITE_KC_SKIP_AUTH: true
token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }} token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
snapshottoken: ${{ secrets.KITTYCAD_API_TOKEN }} snapshottoken: ${{ secrets.KITTYCAD_API_TOKEN }}
@ -373,7 +377,11 @@ jobs:
timeout_minutes: 45 timeout_minutes: 45
max_attempts: 15 max_attempts: 15
env: env:
CI: true
FAIL_ON_CONSOLE_ERRORS: true FAIL_ON_CONSOLE_ERRORS: true
NODE_ENV: development
VITE_KC_DEV_TOKEN: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
VITE_KC_SKIP_AUTH: true
token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }} token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
- uses: actions/upload-artifact@v4 - uses: actions/upload-artifact@v4

View File

@ -28,87 +28,43 @@ jobs:
- run: yarn fmt-check - run: yarn fmt-check
yarn-build-wasm: yarn-build-wasm:
# Build the wasm blob once on the fastest runner. runs-on: ubuntu-22.04
runs-on: runs-on=${{ github.run_id }}/family=i7ie.2xlarge/image=ubuntu22-full-x64
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: actions/setup-node@v4 - uses: actions/setup-node@v4
with: with:
node-version-file: '.nvmrc' node-version-file: '.nvmrc'
cache: 'yarn' cache: 'yarn'
- run: yarn install
- name: Install dependencies - uses: taiki-e/install-action@37bdc826eaedac215f638a96472df572feab0f9b
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: with:
cache: false # Configured below. 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
with:
workspaces: './rust'
- uses: taiki-e/install-action@37bdc826eaedac215f638a96472df572feab0f9b - uses: taiki-e/install-action@37bdc826eaedac215f638a96472df572feab0f9b
with: with:
tool: wasm-pack tool: wasm-pack
- run: yarn build:wasm
- name: Rust Cache
uses: Swatinem/rust-cache@v2
with:
workspaces: './rust'
- name: Build Wasm
shell: bash
run: yarn build:wasm
- 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
- 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 tsc - run: yarn tsc
yarn-lint: yarn-lint:
runs-on: ubuntu-latest runs-on: ubuntu-22.04
needs: yarn-build-wasm
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
@ -117,23 +73,7 @@ jobs:
node-version-file: '.nvmrc' node-version-file: '.nvmrc'
cache: 'yarn' cache: 'yarn'
- run: yarn install - 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 lint - run: yarn lint
python-codespell: python-codespell:
@ -151,7 +91,6 @@ jobs:
yarn-unit-test-kcl-samples: yarn-unit-test-kcl-samples:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: yarn-build-wasm
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
@ -164,22 +103,7 @@ jobs:
- uses: taiki-e/install-action@37bdc826eaedac215f638a96472df572feab0f9b - uses: taiki-e/install-action@37bdc826eaedac215f638a96472df572feab0f9b
with: with:
tool: wasm-pack 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 - run: yarn simpleserver:bg
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }} if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}
@ -196,7 +120,6 @@ jobs:
yarn-unit-test: yarn-unit-test:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: yarn-build-wasm
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
@ -209,22 +132,7 @@ jobs:
- uses: taiki-e/install-action@37bdc826eaedac215f638a96472df572feab0f9b - uses: taiki-e/install-action@37bdc826eaedac215f638a96472df572feab0f9b
with: with:
tool: wasm-pack 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 - run: yarn simpleserver:bg
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }} if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}

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 build-desktop: public/kcl_wasm_lib_bg.wasm .vite/build/main.js
public/kcl_wasm_lib_bg.wasm: $(CARGO_SOURCES)$(RUST_SOURCES) public/kcl_wasm_lib_bg.wasm: $(CARGO_SOURCES)$(RUST_SOURCES)
yarn build:wasm:dev yarn build:wasm
build/index.html: $(REACT_SOURCES) $(TYPESCRIPT_SOURCES) $(VITE_SOURCES) build/index.html: $(REACT_SOURCES) $(TYPESCRIPT_SOURCES) $(VITE_SOURCES)
yarn build:local yarn build:local
@ -99,7 +99,7 @@ test-e2e-web: install build-web ## Run the web e2e tests
.PHONY: test-e2e-desktop .PHONY: test-e2e-desktop
test-e2e-desktop: install build-desktop ## Run the desktop e2e tests 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 # CLEAN

View File

@ -54,7 +54,7 @@ example = extrude(exampleSketch, length = 5)
// Add color to a revolved solid. // Add color to a revolved solid.
sketch001 = startSketchOn(XY) sketch001 = startSketchOn(XY)
|> circle(center = [15, 0], radius = 5) |> circle(center = [15, 0], radius = 5)
|> revolve(angle = 360, axis = 'y') |> revolve(angle = 360, axis = Y)
|> appearance(color = '#ff0000', metalness = 90, roughness = 90) |> appearance(color = '#ff0000', metalness = 90, roughness = 90)
``` ```

View File

@ -9,9 +9,12 @@ layout: manual
### `std` ### `std`
- [`X`](/docs/kcl/consts/std-X)
- [`XY`](/docs/kcl/consts/std-XY) - [`XY`](/docs/kcl/consts/std-XY)
- [`XZ`](/docs/kcl/consts/std-XZ) - [`XZ`](/docs/kcl/consts/std-XZ)
- [`Y`](/docs/kcl/consts/std-Y)
- [`YZ`](/docs/kcl/consts/std-YZ) - [`YZ`](/docs/kcl/consts/std-YZ)
- [`Z`](/docs/kcl/consts/std-Z)
### `std::math` ### `std::math`

15
docs/kcl/consts/std-X.md Normal file
View File

@ -0,0 +1,15 @@
---
title: "std::X"
excerpt: ""
layout: manual
---
```js
std::X
```

15
docs/kcl/consts/std-Y.md Normal file
View File

@ -0,0 +1,15 @@
---
title: "std::Y"
excerpt: ""
layout: manual
---
```js
std::Y
```

15
docs/kcl/consts/std-Z.md Normal file
View File

@ -0,0 +1,15 @@
---
title: "std::Z"
excerpt: ""
layout: manual
---
```js
std::Z
```

File diff suppressed because one or more lines are too long

View File

@ -22,6 +22,9 @@ layout: manual
* [`string`](kcl/types/string) * [`string`](kcl/types/string)
* [`tag`](kcl/types/tag) * [`tag`](kcl/types/tag)
* **std** * **std**
* [`Axis2d`](kcl/types/Axis2d)
* [`Axis3d`](kcl/types/Axis3d)
* [`Edge`](kcl/types/Edge)
* [`Face`](kcl/types/Face) * [`Face`](kcl/types/Face)
* [`Helix`](kcl/types/Helix) * [`Helix`](kcl/types/Helix)
* [`Plane`](kcl/types/Plane) * [`Plane`](kcl/types/Plane)
@ -29,9 +32,12 @@ layout: manual
* [`Point3d`](kcl/types/Point3d) * [`Point3d`](kcl/types/Point3d)
* [`Sketch`](kcl/types/Sketch) * [`Sketch`](kcl/types/Sketch)
* [`Solid`](kcl/types/Solid) * [`Solid`](kcl/types/Solid)
* [`X`](kcl/consts/std-X)
* [`XY`](kcl/consts/std-XY) * [`XY`](kcl/consts/std-XY)
* [`XZ`](kcl/consts/std-XZ) * [`XZ`](kcl/consts/std-XZ)
* [`Y`](kcl/consts/std-Y)
* [`YZ`](kcl/consts/std-YZ) * [`YZ`](kcl/consts/std-YZ)
* [`Z`](kcl/consts/std-Z)
* [`abs`](kcl/abs) * [`abs`](kcl/abs)
* [`acos`](kcl/acos) * [`acos`](kcl/acos)
* [`angleToMatchLengthX`](kcl/angleToMatchLengthX) * [`angleToMatchLengthX`](kcl/angleToMatchLengthX)
@ -68,7 +74,7 @@ layout: manual
* [`getNextAdjacentEdge`](kcl/getNextAdjacentEdge) * [`getNextAdjacentEdge`](kcl/getNextAdjacentEdge)
* [`getOppositeEdge`](kcl/getOppositeEdge) * [`getOppositeEdge`](kcl/getOppositeEdge)
* [`getPreviousAdjacentEdge`](kcl/getPreviousAdjacentEdge) * [`getPreviousAdjacentEdge`](kcl/getPreviousAdjacentEdge)
* [`helix`](kcl/helix) * [`helix`](kcl/std-helix)
* [`hole`](kcl/hole) * [`hole`](kcl/hole)
* [`hollow`](kcl/hollow) * [`hollow`](kcl/hollow)
* [`inch`](kcl/inch) * [`inch`](kcl/inch)
@ -87,7 +93,6 @@ layout: manual
* [`map`](kcl/map) * [`map`](kcl/map)
* [`max`](kcl/max) * [`max`](kcl/max)
* [`min`](kcl/min) * [`min`](kcl/min)
* [`mirror2d`](kcl/mirror2d)
* [`mm`](kcl/mm) * [`mm`](kcl/mm)
* [`offsetPlane`](kcl/offsetPlane) * [`offsetPlane`](kcl/offsetPlane)
* [`patternCircular2d`](kcl/patternCircular2d) * [`patternCircular2d`](kcl/patternCircular2d)
@ -106,7 +111,7 @@ layout: manual
* [`push`](kcl/push) * [`push`](kcl/push)
* [`reduce`](kcl/reduce) * [`reduce`](kcl/reduce)
* [`rem`](kcl/rem) * [`rem`](kcl/rem)
* [`revolve`](kcl/revolve) * [`revolve`](kcl/std-revolve)
* [`rotate`](kcl/rotate) * [`rotate`](kcl/rotate)
* [`round`](kcl/round) * [`round`](kcl/round)
* [`scale`](kcl/scale) * [`scale`](kcl/scale)
@ -142,6 +147,7 @@ layout: manual
* [`tan`](kcl/std-math-tan) * [`tan`](kcl/std-math-tan)
* **std::sketch** * **std::sketch**
* [`circle`](kcl/std-sketch-circle) * [`circle`](kcl/std-sketch-circle)
* [`mirror2d`](kcl/std-sketch-mirror2d)
* **std::turns** * **std::turns**
* [`turns::HALF_TURN`](kcl/consts/std-turns-HALF_TURN) * [`turns::HALF_TURN`](kcl/consts/std-turns-HALF_TURN)
* [`turns::QUARTER_TURN`](kcl/consts/std-turns-QUARTER_TURN) * [`turns::QUARTER_TURN`](kcl/consts/std-turns-QUARTER_TURN)

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -6,10 +6,6 @@ layout: manual
Rotate a solid or a sketch. Rotate a solid or a sketch.
This is really useful for assembling parts together. You can create a part and then rotate it to the correct orientation.
For sketches, you can use this to rotate a sketch and then loft it with another sketch.
### Using Roll, Pitch, and Yaw ### Using Roll, Pitch, and Yaw
When rotating a part in 3D space, "roll," "pitch," and "yaw" refer to the three rotational axes used to describe its orientation: roll is rotation around the longitudinal axis (front-to-back), pitch is rotation around the lateral axis (wing-to-wing), and yaw is rotation around the vertical axis (up-down); essentially, it's like tilting the part on its side (roll), tipping the nose up or down (pitch), and turning it left or right (yaw). When rotating a part in 3D space, "roll," "pitch," and "yaw" refer to the three rotational axes used to describe its orientation: roll is rotation around the longitudinal axis (front-to-back), pitch is rotation around the lateral axis (wing-to-wing), and yaw is rotation around the vertical axis (up-down); essentially, it's like tilting the part on its side (roll), tipping the nose up or down (pitch), and turning it left or right (yaw).
@ -170,7 +166,7 @@ fn square() {
profile001 = square() profile001 = square()
profile002 = square() profile002 = square()
|> translate(x = 0, y = 0, z = 20) |> translate(translate = [0, 0, 20])
|> rotate(axis = [0, 0, 1.0], angle = 45) |> rotate(axis = [0, 0, 1.0], angle = 45)
loft([profile001, profile002]) loft([profile001, profile002])

File diff suppressed because one or more lines are too long

View File

@ -146,7 +146,7 @@ exampleSketch = startSketchOn(XY)
|> line(end = [-2, 0]) |> line(end = [-2, 0])
|> close() |> close()
example = revolve(exampleSketch, axis = 'y', angle = 180) example = revolve(exampleSketch, axis = Y, angle = 180)
exampleSketch002 = startSketchOn(example, 'end') exampleSketch002 = startSketchOn(example, 'end')
|> startProfileAt([4.5, -5], %) |> startProfileAt([4.5, -5], %)
@ -177,7 +177,7 @@ exampleSketch = startSketchOn(XY)
example = revolve( example = revolve(
exampleSketch, exampleSketch,
axis = 'y', axis = Y,
angle = 180, angle = 180,
tagEnd = $end01, tagEnd = $end01,
) )

116
docs/kcl/std-helix.md Normal file

File diff suppressed because one or more lines are too long

246
docs/kcl/std-revolve.md Normal file

File diff suppressed because one or more lines are too long

View File

@ -17,7 +17,7 @@ circle(@sketch_or_surface: Sketch | Plane | Face, center: Point2d, radius: numbe
| Name | Type | Description | Required | | Name | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `sketch_or_surface` | [`Sketch`](/docs/kcl/types/Sketch) OR [`Plane`](/docs/kcl/types/Plane) OR [`Face`](/docs/kcl/types/Face) | Sketch to extend, or plane or surface to sketch on. | Yes | | `sketch_or_surface` | [`Sketch`](/docs/kcl/types/Sketch) `|` [`Plane`](/docs/kcl/types/Face) `|` [`Plane`](/docs/kcl/types/Face) | Sketch to extend, or plane or surface to sketch on. | Yes |
| `center` | [`Point2d`](/docs/kcl/types/Point2d) | The center of the circle. | Yes | | `center` | [`Point2d`](/docs/kcl/types/Point2d) | The center of the circle. | Yes |
| `radius` | [`number`](/docs/kcl/types/number) | The radius of the circle. | Yes | | `radius` | [`number`](/docs/kcl/types/number) | The radius of the circle. | Yes |
| [`tag`](/docs/kcl/types/tag) | [`tag`](/docs/kcl/types/tag) | Create a new tag which refers to this circle. | No | | [`tag`](/docs/kcl/types/tag) | [`tag`](/docs/kcl/types/tag) | Create a new tag which refers to this circle. | No |

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -74,7 +74,7 @@ helixPath = helix(
revolutions = 4, revolutions = 4,
length = 10, length = 10,
radius = 5, radius = 5,
axis = 'Z', axis = Z,
) )
// Create a spring by sweeping around the helix path. // Create a spring by sweeping around the helix path.

File diff suppressed because one or more lines are too long

12
docs/kcl/types/Axis2d.md Normal file
View File

@ -0,0 +1,12 @@
---
title: "std::Axis2d"
excerpt: "An infinte line in 2d space."
layout: manual
---
An infinte line in 2d space.

12
docs/kcl/types/Axis3d.md Normal file
View File

@ -0,0 +1,12 @@
---
title: "std::Axis3d"
excerpt: "An infinte line in 3d space."
layout: manual
---
An infinte line in 3d space.

12
docs/kcl/types/Edge.md Normal file
View File

@ -0,0 +1,12 @@
---
title: "std::Edge"
excerpt: "The edge of a solid."
layout: manual
---
The edge of a solid.

View File

@ -28,7 +28,7 @@ An extrude plane.
| `faceId` |[`string`](/docs/kcl/types/string)| The face id for the extrude plane. | No | | `faceId` |[`string`](/docs/kcl/types/string)| The face id for the extrude plane. | No |
| [`tag`](/docs/kcl/types/tag) |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| The tag. | No | | [`tag`](/docs/kcl/types/tag) |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| The tag. | No |
| `id` |[`string`](/docs/kcl/types/string)| The id of the geometry. | No | | `id` |[`string`](/docs/kcl/types/string)| The id of the geometry. | No |
| `sourceRange` |`[integer, integer, integer]`| The source range. | No | | `sourceRange` |[`SourceRange`](/docs/kcl/types/SourceRange)| The source range. | No |
---- ----
@ -48,7 +48,7 @@ An extruded arc.
| `faceId` |[`string`](/docs/kcl/types/string)| The face id for the extrude plane. | No | | `faceId` |[`string`](/docs/kcl/types/string)| The face id for the extrude plane. | No |
| [`tag`](/docs/kcl/types/tag) |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| The tag. | No | | [`tag`](/docs/kcl/types/tag) |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| The tag. | No |
| `id` |[`string`](/docs/kcl/types/string)| The id of the geometry. | No | | `id` |[`string`](/docs/kcl/types/string)| The id of the geometry. | No |
| `sourceRange` |`[integer, integer, integer]`| The source range. | No | | `sourceRange` |[`SourceRange`](/docs/kcl/types/SourceRange)| The source range. | No |
---- ----
@ -68,7 +68,7 @@ Geometry metadata.
| `faceId` |[`string`](/docs/kcl/types/string)| The id for the chamfer surface. | No | | `faceId` |[`string`](/docs/kcl/types/string)| The id for the chamfer surface. | No |
| [`tag`](/docs/kcl/types/tag) |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| The tag. | No | | [`tag`](/docs/kcl/types/tag) |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| The tag. | No |
| `id` |[`string`](/docs/kcl/types/string)| The id of the geometry. | No | | `id` |[`string`](/docs/kcl/types/string)| The id of the geometry. | No |
| `sourceRange` |`[integer, integer, integer]`| The source range. | No | | `sourceRange` |[`SourceRange`](/docs/kcl/types/SourceRange)| The source range. | No |
---- ----
@ -88,7 +88,7 @@ Geometry metadata.
| `faceId` |[`string`](/docs/kcl/types/string)| The id for the fillet surface. | No | | `faceId` |[`string`](/docs/kcl/types/string)| The id for the fillet surface. | No |
| [`tag`](/docs/kcl/types/tag) |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| The tag. | No | | [`tag`](/docs/kcl/types/tag) |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| The tag. | No |
| `id` |[`string`](/docs/kcl/types/string)| The id of the geometry. | No | | `id` |[`string`](/docs/kcl/types/string)| The id of the geometry. | No |
| `sourceRange` |`[integer, integer, integer]`| The source range. | No | | `sourceRange` |[`SourceRange`](/docs/kcl/types/SourceRange)| The source range. | No |
---- ----

View File

@ -17,6 +17,6 @@ Geometry metadata.
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `id` |[`string`](/docs/kcl/types/string)| The id of the geometry. | No | | `id` |[`string`](/docs/kcl/types/string)| The id of the geometry. | No |
| `sourceRange` |`[integer, integer, integer]`| The source range. | No | | `sourceRange` |[`SourceRange`](/docs/kcl/types/SourceRange)| The source range. | No |

View File

@ -17,7 +17,7 @@ A helix.
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `value` |[`string`](/docs/kcl/types/string)| The id of the helix. | No | | `value` |[`string`](/docs/kcl/types/string)| The id of the helix. | No |
| `artifactId` |[`string`](/docs/kcl/types/string)| The artifact ID. | No | | `artifactId` |[`ArtifactId`](/docs/kcl/types/ArtifactId)| The artifact ID. | No |
| `revolutions` |[`number`](/docs/kcl/types/number)| Number of revolutions. | No | | `revolutions` |[`number`](/docs/kcl/types/number)| Number of revolutions. | No |
| `angleStart` |[`number`](/docs/kcl/types/number)| Start angle (in degrees). | No | | `angleStart` |[`number`](/docs/kcl/types/number)| Start angle (in degrees). | No |
| `ccw` |`boolean`| Is the helix rotation counter clockwise? | No | | `ccw` |`boolean`| Is the helix rotation counter clockwise? | No |

View File

@ -285,7 +285,7 @@ Data for an imported geometry.
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `type` |enum: `Module`| | No | | `type` |enum: `Module`| | No |
| `value` |`integer`| Identifier of a source file. Uses a u32 to keep the size small. | No | | `value` |[`ModuleId`](/docs/kcl/types/ModuleId)| Identifier of a source file. Uses a u32 to keep the size small. | No |
---- ----

View File

@ -17,6 +17,6 @@ Data for polar coordinates.
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `angle` |[`number`](/docs/kcl/types/number)| The angle of the line (in degrees). | No | | `angle` |[`number`](/docs/kcl/types/number)| The angle of the line (in degrees). | No |
| `length` |[`number`](/docs/kcl/types/number)| The length of the line. | No | | `length` |[`TyF64`](/docs/kcl/types/TyF64)| The length of the line. | No |

View File

@ -25,7 +25,7 @@ A sketch type.
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `type` |enum: `plane`| | No | | `type` |enum: `plane`| | No |
| `id` |[`string`](/docs/kcl/types/string)| The id of the plane. | No | | `id` |[`string`](/docs/kcl/types/string)| The id of the plane. | No |
| `artifactId` |[`string`](/docs/kcl/types/string)| The artifact ID. | No | | `artifactId` |[`ArtifactId`](/docs/kcl/types/ArtifactId)| The artifact ID. | No |
| `value` |[`PlaneType`](/docs/kcl/types/PlaneType)| Type for a plane. | No | | `value` |[`PlaneType`](/docs/kcl/types/PlaneType)| Type for a plane. | No |
| `origin` |[`Point3d`](/docs/kcl/types/Point3d)| Origin of the plane. | No | | `origin` |[`Point3d`](/docs/kcl/types/Point3d)| Origin of the plane. | No |
| `xAxis` |[`Point3d`](/docs/kcl/types/Point3d)| What should the plane's X axis be? | No | | `xAxis` |[`Point3d`](/docs/kcl/types/Point3d)| What should the plane's X axis be? | No |
@ -49,7 +49,7 @@ A face.
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `type` |enum: `face`| | No | | `type` |enum: `face`| | No |
| `id` |[`string`](/docs/kcl/types/string)| The id of the face. | No | | `id` |[`string`](/docs/kcl/types/string)| The id of the face. | No |
| `artifactId` |[`string`](/docs/kcl/types/string)| The artifact ID. | No | | `artifactId` |[`ArtifactId`](/docs/kcl/types/ArtifactId)| The artifact ID. | No |
| `value` |[`string`](/docs/kcl/types/string)| The tag of the face. | No | | `value` |[`string`](/docs/kcl/types/string)| The tag of the face. | No |
| `xAxis` |[`Point3d`](/docs/kcl/types/Point3d)| What should the face's X axis be? | No | | `xAxis` |[`Point3d`](/docs/kcl/types/Point3d)| What should the face's X axis be? | No |
| `yAxis` |[`Point3d`](/docs/kcl/types/Point3d)| What should the face's Y axis be? | No | | `yAxis` |[`Point3d`](/docs/kcl/types/Point3d)| What should the face's Y axis be? | No |

View File

@ -0,0 +1,15 @@
---
title: "SourceRange"
excerpt: ""
layout: manual
---
**Type:** `integer` (`uint`)

View File

@ -5,11 +5,17 @@ layout: manual
--- ---
**Type:** [`number`](/docs/kcl/types/number) (`double`) **Type:** `object`
## Properties
| Property | Type | Description | Required |
|----------|------|-------------|----------|
| `n` |[`number`](/docs/kcl/types/number)| | No |
| `ty` |[`NumericType`](/docs/kcl/types/NumericType)| | No |

View File

@ -85,7 +85,7 @@ async function doBasicSketch(
await page.mouse.click(startXPx, 500 - PUR * 20) await page.mouse.click(startXPx, 500 - PUR * 20)
if (openPanes.includes('code')) { if (openPanes.includes('code')) {
await expect(u.codeLocator) await expect(u.codeLocator)
.toHaveText(`@settings(defaultLengthUnit = in)sketch001 = startSketchOn(XZ)profile001 = startProfileAt(${ .toHaveText(`sketch001 = startSketchOn(XZ)profile001 = startProfileAt(${
commonPoints.startAt commonPoints.startAt
}, sketch001) }, sketch001)
|> xLine(length = ${commonPoints.num1}) |> xLine(length = ${commonPoints.num1})
@ -119,7 +119,10 @@ async function doBasicSketch(
await page.waitForTimeout(100) await page.waitForTimeout(100)
if (openPanes.includes('code')) { if (openPanes.includes('code')) {
expect(await u.getGreatestPixDiff(line1, TEST_COLORS.BLUE)).toBeLessThan(3) await expect(
await u.getGreatestPixDiff(line1, TEST_COLORS.BLUE)
).toBeLessThan(3)
await expect(await u.getGreatestPixDiff(line1, [0, 0, 255])).toBeLessThan(3)
} }
// hold down shift // hold down shift
@ -142,7 +145,7 @@ async function doBasicSketch(
// Open the code pane. // Open the code pane.
await u.openKclCodePanel() await u.openKclCodePanel()
await expect(u.codeLocator) await expect(u.codeLocator)
.toHaveText(`@settings(defaultLengthUnit = in)sketch001 = startSketchOn(XZ)profile001 = startProfileAt(${ .toHaveText(`sketch001 = startSketchOn(XZ)profile001 = startProfileAt(${
commonPoints.startAt commonPoints.startAt
}, sketch001) }, sketch001)
|> xLine(length = ${commonPoints.num1}, tag = $seg01) |> xLine(length = ${commonPoints.num1}, tag = $seg01)

View File

@ -1,117 +0,0 @@
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

@ -46,7 +46,7 @@ test.describe(
}, },
} }
const code = `@settings(defaultLengthUnit = in)sketch001 = startSketchOn(${plane})profile001 = startProfileAt([0.91, -1.22], sketch001)` const code = `sketch001 = startSketchOn(${plane})profile001 = startProfileAt([0.91, -1.22], sketch001)`
await u.openDebugPanel() await u.openDebugPanel()

View File

@ -251,11 +251,11 @@ test(
]) ])
await Promise.all([ await Promise.all([
fsp.copyFile( fsp.copyFile(
executorInputPath('cylinder-inches.kcl'), executorInputPath('router-template-slate.kcl'),
join(routerTemplateDir, 'main.kcl') join(routerTemplateDir, 'main.kcl')
), ),
fsp.copyFile( fsp.copyFile(
executorInputPath('e2e-can-sketch-on-chamfer.kcl'), executorInputPath('focusrite_scarlett_mounting_braket.kcl'),
join(bracketDir, 'main.kcl') join(bracketDir, 'main.kcl')
), ),
]) ])

View File

@ -20,11 +20,11 @@ test(
await Promise.all([fsp.mkdir(bracketDir, { recursive: true })]) await Promise.all([fsp.mkdir(bracketDir, { recursive: true })])
await Promise.all([ await Promise.all([
fsp.copyFile( fsp.copyFile(
executorInputPath('cylinder-inches.kcl'), executorInputPath('router-template-slate.kcl'),
path.join(bracketDir, 'other.kcl') path.join(bracketDir, 'other.kcl')
), ),
fsp.copyFile( fsp.copyFile(
executorInputPath('e2e-can-sketch-on-chamfer.kcl'), executorInputPath('focusrite_scarlett_mounting_braket.kcl'),
path.join(bracketDir, 'main.kcl') path.join(bracketDir, 'main.kcl')
), ),
]) ])
@ -107,7 +107,7 @@ test(
}, },
{ timeout: 15_000 } { timeout: 15_000 }
) )
.toBeGreaterThan(30_000) .toBeGreaterThan(300_000)
}) })
}) })
@ -187,7 +187,7 @@ test(
}, },
{ timeout: 15_000 } { timeout: 15_000 }
) )
.toBeGreaterThan(50_000) .toBeGreaterThan(70_000)
}) })
}) })
} }

View File

@ -32,30 +32,26 @@ test.describe('Editor tests', { tag: ['@skipWin'] }, () => {
await page.keyboard.press('/') await page.keyboard.press('/')
await page.keyboard.up('ControlOrMeta') await page.keyboard.up('ControlOrMeta')
await expect(page.locator('.cm-content')).toHaveText( await expect(page.locator('.cm-content'))
`@settings(defaultLengthUnit = in) .toHaveText(`sketch001 = startSketchOn(XY)
sketch001 = startSketchOn(XY)
|> startProfileAt([-10, -10], %) |> startProfileAt([-10, -10], %)
|> line(end = [20, 0]) |> line(end = [20, 0])
|> line(end = [0, 20]) |> line(end = [0, 20])
|> line(end = [-20, 0]) |> line(end = [-20, 0])
// |> close()`.replaceAll('\n', '') // |> close()`)
)
// uncomment the code // uncomment the code
await page.keyboard.down('ControlOrMeta') await page.keyboard.down('ControlOrMeta')
await page.keyboard.press('/') await page.keyboard.press('/')
await page.keyboard.up('ControlOrMeta') await page.keyboard.up('ControlOrMeta')
await expect(page.locator('.cm-content')).toHaveText( await expect(page.locator('.cm-content'))
`@settings(defaultLengthUnit = in) .toHaveText(`sketch001 = startSketchOn(XY)
sketch001 = startSketchOn(XY)
|> startProfileAt([-10, -10], %) |> startProfileAt([-10, -10], %)
|> line(end = [20, 0]) |> line(end = [20, 0])
|> line(end = [0, 20]) |> line(end = [0, 20])
|> line(end = [-20, 0]) |> line(end = [-20, 0])
|> close()`.replaceAll('\n', '') |> close()`)
)
}) })
test('ensure we use the cache, and do not re-execute', async ({ test('ensure we use the cache, and do not re-execute', async ({
@ -182,15 +178,13 @@ sketch001 = startSketchOn(XY)
await page.locator('#code-pane button:first-child').click() await page.locator('#code-pane button:first-child').click()
await page.locator('button:has-text("Format code")').click() await page.locator('button:has-text("Format code")').click()
await expect(page.locator('.cm-content')).toHaveText( await expect(page.locator('.cm-content'))
`@settings(defaultLengthUnit = in) .toHaveText(`sketch001 = startSketchOn(XY)
sketch001 = startSketchOn(XY)
|> startProfileAt([-10, -10], %) |> startProfileAt([-10, -10], %)
|> line(end = [20, 0]) |> line(end = [20, 0])
|> line(end = [0, 20]) |> line(end = [0, 20])
|> line(end = [-20, 0]) |> line(end = [-20, 0])
|> close()`.replaceAll('\n', '') |> close()`)
)
}) })
test('if you click the format button it formats your code and executes so lints are still there', async ({ test('if you click the format button it formats your code and executes so lints are still there', async ({
@ -233,15 +227,13 @@ sketch001 = startSketchOn(XY)
await u.expectCmdLog('[data-message-type="execution-done"]') await u.expectCmdLog('[data-message-type="execution-done"]')
await u.closeDebugPanel() await u.closeDebugPanel()
await expect(page.locator('.cm-content')).toHaveText( await expect(page.locator('.cm-content'))
`@settings(defaultLengthUnit = in) .toHaveText(`sketch_001 = startSketchOn(XY)
sketch_001 = startSketchOn(XY)
|> startProfileAt([-10, -10], %) |> startProfileAt([-10, -10], %)
|> line(end = [20, 0]) |> line(end = [20, 0])
|> line(end = [0, 20]) |> line(end = [0, 20])
|> line(end = [-20, 0]) |> line(end = [-20, 0])
|> close()`.replaceAll('\n', '') |> close()`)
)
// error in guter // error in guter
await expect(page.locator('.cm-lint-marker-info').first()).toBeVisible() await expect(page.locator('.cm-lint-marker-info').first()).toBeVisible()
@ -479,7 +471,6 @@ sketch_001 = startSketchOn(XY)
test('if you write kcl with lint errors you get lints', async ({ test('if you write kcl with lint errors you get lints', async ({
page, page,
homePage, homePage,
scene,
}) => { }) => {
const u = await getUtils(page) const u = await getUtils(page)
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1000, height: 500 })
@ -499,7 +490,10 @@ sketch_001 = startSketchOn(XY)
await page.keyboard.press('ArrowLeft') await page.keyboard.press('ArrowLeft')
await page.keyboard.press('ArrowRight') await page.keyboard.press('ArrowRight')
await scene.waitForExecutionDone() // FIXME: lsp errors do not propagate to the frontend until engine is connected and code is executed
// This timeout is to wait for engine connection. LSP and code execution errors should be handled differently
// LSP can emit errors as fast as it waits and show them in the editor
await page.waitForTimeout(10000)
// error in guter // error in guter
await expect(page.locator('.cm-lint-marker-info').first()).toBeVisible() await expect(page.locator('.cm-lint-marker-info').first()).toBeVisible()
@ -821,12 +815,10 @@ sketch_001 = startSketchOn(XY)
// there shouldn't be any auto complete options for 'lin' in the comment // there shouldn't be any auto complete options for 'lin' in the comment
await expect(page.locator('.cm-completionLabel')).not.toBeVisible() await expect(page.locator('.cm-completionLabel')).not.toBeVisible()
await expect(page.locator('.cm-content')).toHaveText( await expect(page.locator('.cm-content'))
`@settings(defaultLengthUnit = in) .toHaveText(`sketch001 = startSketchOn(XZ)
sketch001 = startSketchOn(XZ)
|> startProfileAt([3.14, 12], %) |> startProfileAt([3.14, 12], %)
|> xLine(%, length = 5) // lin`.replaceAll('\n', '') |> xLine(%, length = 5) // lin`)
)
// expect there to be no KCL errors // expect there to be no KCL errors
await expect(page.locator('.cm-lint-marker-error')).toHaveCount(0) await expect(page.locator('.cm-lint-marker-error')).toHaveCount(0)
@ -896,12 +888,10 @@ sketch001 = startSketchOn(XZ)
// there shouldn't be any auto complete options for 'lin' in the comment // there shouldn't be any auto complete options for 'lin' in the comment
await expect(page.locator('.cm-completionLabel')).not.toBeVisible() await expect(page.locator('.cm-completionLabel')).not.toBeVisible()
await expect(page.locator('.cm-content')).toHaveText( await expect(page.locator('.cm-content'))
`@settings(defaultLengthUnit = in) .toHaveText(`sketch001 = startSketchOn(XZ)
sketch001 = startSketchOn(XZ)
|> startProfileAt([3.14, 12], %) |> startProfileAt([3.14, 12], %)
|> xLine(%, length = 5) // lin`.replaceAll('\n', '') |> xLine(%, length = 5) // lin`)
)
}) })
}) })
test('Can undo a click and point extrude with ctrl+z', async ({ test('Can undo a click and point extrude with ctrl+z', async ({
@ -1216,55 +1206,4 @@ sketch001 = startSketchOn(XZ)
}) })
} }
) )
test('Rectangle tool panning with middle click', async ({
page,
homePage,
toolbar,
scene,
cmdBar,
editor,
}) => {
await page.setBodyDimensions({ width: 1200, height: 900 })
await homePage.goToModelingScene()
// wait until scene is ready to be interacted with
await scene.connectionEstablished()
await scene.settled(cmdBar)
await page.getByRole('button', { name: 'Start Sketch' }).click()
// select an axis plane
await page.mouse.click(700, 200)
// Needed as we don't yet have a way to get a signal from the engine that the camera has animated to the sketch plane
await page.waitForTimeout(1000)
const middleMousePan = async (
startX: number,
startY: number,
endX: number,
endY: number
) => {
const initialCode = await editor.getCurrentCode()
await page.mouse.click(startX, startY, { button: 'middle' })
await page.mouse.move(endX, endY, {
steps: 10,
})
// We expect the code to be the same, middle mouse click should not modify the code, only do panning
await editor.expectEditor.toBe(initialCode)
}
await test.step(`Verify corner rectangle panning`, async () => {
await page.getByTestId('corner-rectangle').click()
await middleMousePan(800, 500, 900, 600)
})
await test.step(`Verify center rectangle panning`, async () => {
await toolbar.selectCenterRectangle()
await middleMousePan(800, 200, 900, 300)
})
})
}) })

View File

@ -21,7 +21,7 @@ sketch001 = startSketchOn(XZ)
|> angledLine([-45, length001], %) |> angledLine([-45, length001], %)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)]) |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close() |> close()
revolve001 = revolve(sketch001, axis = "X") revolve001 = revolve(sketch001, axis = X)
triangle() triangle()
|> extrude(length = 30) |> extrude(length = 30)
plane001 = offsetPlane(XY, offset = 10) plane001 = offsetPlane(XY, offset = 10)
@ -126,7 +126,7 @@ test.describe('Feature Tree pane', () => {
await testViewSource({ await testViewSource({
operationName: 'Revolve', operationName: 'Revolve',
operationIndex: 0, operationIndex: 0,
expectedActiveLine: 'revolve001 = revolve(sketch001, axis = "X")', expectedActiveLine: 'revolve001 = revolve(sketch001, axis = X)',
}) })
await testViewSource({ await testViewSource({
operationName: 'Triangle', operationName: 'Triangle',

View File

@ -81,13 +81,6 @@ export class EditorFixture {
expectEditor = { expectEditor = {
toContain: this._expectEditorToContain(), toContain: this._expectEditorToContain(),
not: { toContain: this._expectEditorToContain(true) }, not: { toContain: this._expectEditorToContain(true) },
toBe: async (code: string) => {
const currentCode = await this.getCurrentCode()
return expect(currentCode).toBe(code)
},
}
getCurrentCode = async () => {
return await this.codeContent.innerText()
} }
snapshot = async (options?: { timeout?: number; name?: string }) => { snapshot = async (options?: { timeout?: number; name?: string }) => {
const wasPaneOpen = await this.checkIfPaneIsOpen() const wasPaneOpen = await this.checkIfPaneIsOpen()

View File

@ -310,9 +310,7 @@ export async function expectPixelColor(
.toBeTruthy() .toBeTruthy()
.catch((cause) => { .catch((cause) => {
throw new Error( throw new Error(
`ExpectPixelColor: point ${JSON.stringify( `ExpectPixelColor: expecting ${colour} got ${finalValue}`,
coords
)} was expecting ${colour} but got ${finalValue}`,
{ cause } { cause }
) )
}) })

View File

@ -181,14 +181,6 @@ export class ToolbarFixture {
).toBeVisible() ).toBeVisible()
await this.page.getByTestId('dropdown-center-rectangle').click() 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 () => { selectCircleThreePoint = async () => {
await this.page await this.page

View File

@ -258,6 +258,14 @@ export const isErrorWhitelisted = (exception: Error) => {
foundInSpec: 'e2e/playwright/testing-settings.spec.ts', foundInSpec: 'e2e/playwright/testing-settings.spec.ts',
}, },
// TODO: fix this error in the code // 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', name: 'ReferenceError',
message: '_testUtils is not defined', message: '_testUtils is not defined',
@ -265,6 +273,7 @@ export const isErrorWhitelisted = (exception: Error) => {
project: 'Google Chrome', project: 'Google Chrome',
foundInSpec: 'e2e/playwright/snapshot-tests.spec.ts', foundInSpec: 'e2e/playwright/snapshot-tests.spec.ts',
}, },
// TODO: fix this error in the code
{ {
name: 'TypeError', name: 'TypeError',
message: 'Failed to fetch', message: 'Failed to fetch',
@ -272,13 +281,21 @@ export const isErrorWhitelisted = (exception: Error) => {
project: 'Google Chrome', project: 'Google Chrome',
foundInSpec: 'e2e/playwright/snapshot-tests.spec.ts', foundInSpec: 'e2e/playwright/snapshot-tests.spec.ts',
}, },
// TODO: fix this error in the code
{ {
name: 'Error', name: 'ReferenceError',
message: 'The "path" argument must be of type string. Received undefined', message: 'originalCode is not defined',
stack: stack: '',
'Error: The "path" argument must be of type string. Received undefined',
project: 'Google Chrome', project: 'Google Chrome',
foundInSpec: '', // many tests are impacted by this error foundInSpec: 'e2e/playwright/onboarding-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',
}, },
] ]

View File

@ -11,7 +11,7 @@ test(
const bracketDir = join(dir, 'bracket') const bracketDir = join(dir, 'bracket')
await fsp.mkdir(bracketDir, { recursive: true }) await fsp.mkdir(bracketDir, { recursive: true })
await fsp.copyFile( await fsp.copyFile(
executorInputPath('cylinder-inches.kcl'), executorInputPath('focusrite_scarlett_mounting_braket.kcl'),
join(bracketDir, 'main.kcl') join(bracketDir, 'main.kcl')
) )
}) })
@ -51,7 +51,7 @@ test(
const bracketDir = join(dir, 'bracket') const bracketDir = join(dir, 'bracket')
await fsp.mkdir(bracketDir, { recursive: true }) await fsp.mkdir(bracketDir, { recursive: true })
await fsp.copyFile( await fsp.copyFile(
executorInputPath('cylinder-inches.kcl'), executorInputPath('focusrite_scarlett_mounting_braket.kcl'),
join(bracketDir, 'main.kcl') join(bracketDir, 'main.kcl')
) )
}) })

View File

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

View File

@ -137,7 +137,7 @@ test.describe('Point-and-click tests', () => {
await scene.moveCameraTo(cameraPos, cameraTarget) await scene.moveCameraTo(cameraPos, cameraTarget)
await test.step('check chamfer selection changes cursor position', async () => { await test.step('check chamfer selection changes cursor positon', async () => {
await expect(async () => { await expect(async () => {
// sometimes initial click doesn't register // sometimes initial click doesn't register
await clickChamfer() await clickChamfer()
@ -173,7 +173,7 @@ test.describe('Point-and-click tests', () => {
}) })
await test.step('Check there is no errors after code created in previous steps executes', async () => { await test.step('Check there is no errors after code created in previous steps executes', async () => {
await editor.expectState({ await editor.expectState({
activeLines: ['@settings(defaultLengthUnit = in)'], activeLines: ['sketch001 = startSketchOn(XZ)'],
highlightedCode: '', highlightedCode: '',
diagnostics: [], diagnostics: [],
}) })
@ -299,8 +299,7 @@ test.describe('Point-and-click tests', () => {
await test.step('verify at the end of the test that final code is what is expected', async () => { await test.step('verify at the end of the test that final code is what is expected', async () => {
await editor.expectEditor.toContain( await editor.expectEditor.toContain(
`@settings(defaultLengthUnit = in) `sketch001 = startSketchOn(XZ)
sketch001 = startSketchOn(XZ)
|> startProfileAt([75.8, 317.2], %) // [$startCapTag, $EndCapTag] |> startProfileAt([75.8, 317.2], %) // [$startCapTag, $EndCapTag]
|> angledLine([0, 268.43], %, $rectangleSegmentA001) |> angledLine([0, 268.43], %, $rectangleSegmentA001)
|> angledLine([ |> angledLine([
@ -370,7 +369,7 @@ profile001 = startProfileAt([205.96, 254.59], sketch002)
}) })
}) })
test('Works on chamfers that are not in a pipeExpression can break up multi edges in a chamfer array', async ({ test('Works on chamfers that are non in a pipeExpression can break up multi edges in a chamfer array', async ({
context, context,
page, page,
homePage, homePage,
@ -419,8 +418,7 @@ profile001 = startProfileAt([205.96, 254.59], sketch002)
|>close()`, |>close()`,
}) })
await editor.expectEditor.toContain( await editor.expectEditor.toContain(
`@settings(defaultLengthUnit = in) `sketch001 = startSketchOn(XZ)
sketch001 = startSketchOn(XZ)
|> startProfileAt([75.8, 317.2], %) |> startProfileAt([75.8, 317.2], %)
|> angledLine([0, 268.43], %, $rectangleSegmentA001) |> angledLine([0, 268.43], %, $rectangleSegmentA001)
|> angledLine([ |> angledLine([
@ -1099,6 +1097,7 @@ openSketch = startSketchOn(XY)
Mode: '', Mode: '',
AngleStart: '', AngleStart: '',
Revolutions: '', Revolutions: '',
Length: '',
Radius: '', Radius: '',
CounterClockWise: '', CounterClockWise: '',
}, },
@ -1195,14 +1194,14 @@ openSketch = startSketchOn(XY)
{ {
selectionType: 'segment', selectionType: 'segment',
testPoint: { x: 513, y: 221 }, testPoint: { x: 513, y: 221 },
expectedOutput: `helix001 = helix( axis = seg01, radius = 1, revolutions = 20, angleStart = 0, ccw = false,)`, expectedOutput: `helix001 = helix( axis = seg01, radius = 1, length = 100, revolutions = 20, angleStart = 0, ccw = false,)`,
expectedEditedOutput: `helix001 = helix( axis = seg01, radius = 5, revolutions = 20, angleStart = 0, ccw = false,)`, expectedEditedOutput: `helix001 = helix( axis = seg01, radius = 1, length = 50, revolutions = 20, angleStart = 0, ccw = false,)`,
}, },
{ {
selectionType: 'sweepEdge', selectionType: 'sweepEdge',
testPoint: { x: 564, y: 364 }, testPoint: { x: 564, y: 364 },
expectedOutput: `helix001 = helix( axis = getOppositeEdge(seg01), radius = 1, revolutions = 20, angleStart = 0, ccw = false,)`, expectedOutput: `helix001 = helix( axis = getOppositeEdge(seg01), radius = 1, length = 100, revolutions = 20, angleStart = 0, ccw = false,)`,
expectedEditedOutput: `helix001 = helix( axis = getOppositeEdge(seg01), radius = 5, revolutions = 20, angleStart = 0, ccw = false,)`, expectedEditedOutput: `helix001 = helix( axis = getOppositeEdge(seg01), radius = 1, length = 50, revolutions = 20, angleStart = 0, ccw = false,)`,
}, },
] ]
helixCases.map( helixCases.map(
@ -1245,6 +1244,7 @@ openSketch = startSketchOn(XY)
AngleStart: '', AngleStart: '',
Mode: '', Mode: '',
CounterClockWise: '', CounterClockWise: '',
Length: '',
Radius: '', Radius: '',
Revolutions: '', Revolutions: '',
}, },
@ -1261,6 +1261,8 @@ openSketch = startSketchOn(XY)
await cmdBar.progressCmdBar() await cmdBar.progressCmdBar()
await page.keyboard.insertText('1') await page.keyboard.insertText('1')
await cmdBar.progressCmdBar() await cmdBar.progressCmdBar()
await page.keyboard.insertText('100')
await cmdBar.progressCmdBar()
await cmdBar.expectState({ await cmdBar.expectState({
stage: 'review', stage: 'review',
headerArguments: { headerArguments: {
@ -1269,6 +1271,7 @@ openSketch = startSketchOn(XY)
AngleStart: '0', AngleStart: '0',
Revolutions: '20', Revolutions: '20',
Radius: '1', Radius: '1',
Length: '100',
CounterClockWise: '', CounterClockWise: '',
}, },
commandName: 'Helix', commandName: 'Helix',
@ -1289,8 +1292,8 @@ openSketch = startSketchOn(XY)
0 0
) )
await operationButton.dblclick() await operationButton.dblclick()
const initialInput = '1' const initialInput = '100'
const newInput = '5' const newInput = '50'
await cmdBar.expectState({ await cmdBar.expectState({
commandName: 'Helix', commandName: 'Helix',
stage: 'arguments', stage: 'arguments',
@ -1299,14 +1302,13 @@ openSketch = startSketchOn(XY)
headerArguments: { headerArguments: {
AngleStart: '0', AngleStart: '0',
Revolutions: '20', Revolutions: '20',
Radius: initialInput, Radius: '1',
Length: initialInput,
CounterClockWise: '', CounterClockWise: '',
}, },
highlightedHeaderArg: 'CounterClockWise', highlightedHeaderArg: 'CounterClockWise',
}) })
await page await page.keyboard.press('Shift+Backspace')
.getByRole('button', { name: 'radius', exact: false })
.click()
await expect(cmdBar.currentArgumentInput).toBeVisible() await expect(cmdBar.currentArgumentInput).toBeVisible()
await cmdBar.currentArgumentInput await cmdBar.currentArgumentInput
.locator('.cm-content') .locator('.cm-content')
@ -1317,7 +1319,8 @@ openSketch = startSketchOn(XY)
headerArguments: { headerArguments: {
AngleStart: '0', AngleStart: '0',
Revolutions: '20', Revolutions: '20',
Radius: newInput, Radius: '1',
Length: newInput,
CounterClockWise: '', CounterClockWise: '',
}, },
commandName: 'Helix', commandName: 'Helix',
@ -1388,6 +1391,7 @@ extrude001 = extrude(profile001, length = 100)
Mode: '', Mode: '',
AngleStart: '', AngleStart: '',
Revolutions: '', Revolutions: '',
Length: '',
Radius: '', Radius: '',
CounterClockWise: '', CounterClockWise: '',
}, },
@ -1641,10 +1645,9 @@ loft001 = loft([sketch001, sketch002])
{ {
targetType: 'circle', targetType: 'circle',
testPoint: { x: 700, y: 250 }, testPoint: { x: 700, y: 250 },
initialCode: `@settings(defaultLengthUnit = in) initialCode: `sketch001 = startSketchOn('YZ')
sketch001 = startSketchOn(YZ)
profile001 = circle(sketch001, center = [0, 0], radius = 500) profile001 = circle(sketch001, center = [0, 0], radius = 500)
sketch002 = startSketchOn(XZ) sketch002 = startSketchOn('XZ')
|> startProfileAt([0, 0], %) |> startProfileAt([0, 0], %)
|> xLine(length = -500) |> xLine(length = -500)
|> tangentialArcTo([-2000, 500], %)`, |> tangentialArcTo([-2000, 500], %)`,
@ -1652,8 +1655,7 @@ sketch002 = startSketchOn(XZ)
{ {
targetType: 'rectangle', targetType: 'rectangle',
testPoint: { x: 710, y: 255 }, testPoint: { x: 710, y: 255 },
initialCode: `@settings(defaultLengthUnit = in) initialCode: `sketch001 = startSketchOn('YZ')
sketch001 = startSketchOn(YZ)
profile001 = startProfileAt([-400, -400], sketch001) profile001 = startProfileAt([-400, -400], sketch001)
|> angledLine([0, 800], %, $rectangleSegmentA001) |> angledLine([0, 800], %, $rectangleSegmentA001)
|> angledLine([ |> angledLine([
@ -1666,7 +1668,7 @@ profile001 = startProfileAt([-400, -400], sketch001)
], %) ], %)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)]) |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close() |> close()
sketch002 = startSketchOn(XZ) sketch002 = startSketchOn('XZ')
|> startProfileAt([0, 0], %) |> startProfileAt([0, 0], %)
|> xLine(length = -500) |> xLine(length = -500)
|> tangentialArcTo([-2000, 500], %)`, |> tangentialArcTo([-2000, 500], %)`,
@ -1810,8 +1812,7 @@ sketch002 = startSketchOn(XZ)
toolbar, toolbar,
cmdBar, cmdBar,
}) => { }) => {
const initialCode = `@settings(defaultLengthUnit = in) const initialCode = `sketch001 = startSketchOn(YZ)
sketch001 = startSketchOn(YZ)
|> circle( |> circle(
center = [0, 0], center = [0, 0],
radius = 500 radius = 500
@ -2480,8 +2481,7 @@ extrude001 = extrude(profile001, length = 5)
cmdBar, cmdBar,
}) => { }) => {
// Code samples // Code samples
const initialCode = `@settings(defaultLengthUnit = in) const initialCode = `sketch001 = startSketchOn(XY)
sketch001 = startSketchOn(XY)
|> startProfileAt([-12, -6], %) |> startProfileAt([-12, -6], %)
|> line(end = [0, 12]) |> line(end = [0, 12])
|> line(end = [24, 0]) |> line(end = [24, 0])
@ -2773,8 +2773,7 @@ extrude001 = extrude(sketch001, length = -12)
toolbar, toolbar,
}) => { }) => {
// Code samples // Code samples
const initialCode = `@settings(defaultLengthUnit = in) const initialCode = `sketch001 = startSketchOn(XY)
sketch001 = startSketchOn(XY)
|> startProfileAt([-12, -6], %) |> startProfileAt([-12, -6], %)
|> line(end = [0, 12]) |> line(end = [0, 12])
|> line(end = [24, 0], tag = $seg02) |> line(end = [24, 0], tag = $seg02)
@ -2928,8 +2927,7 @@ chamfer04 = chamfer(extrude001, length = 5, tags = [getOppositeEdge(seg02)])
toolbar, toolbar,
cmdBar, cmdBar,
}) => { }) => {
const initialCode = `@settings(defaultLengthUnit = in) const initialCode = `sketch001 = startSketchOn(XZ)
sketch001 = startSketchOn(XZ)
|> circle(center = [0, 0], radius = 30) |> circle(center = [0, 0], radius = 30)
extrude001 = extrude(sketch001, length = 30) extrude001 = extrude(sketch001, length = 30)
` `
@ -3064,8 +3062,7 @@ extrude001 = extrude(sketch001, length = 30)
toolbar, toolbar,
cmdBar, cmdBar,
}) => { }) => {
const initialCode = `@settings(defaultLengthUnit = in) const initialCode = `sketch001 = startSketchOn(XY)
sketch001 = startSketchOn(XY)
|> startProfileAt([-20, 20], %) |> startProfileAt([-20, 20], %)
|> xLine(length = 40) |> xLine(length = 40)
|> yLine(length = -60) |> yLine(length = -60)
@ -3183,8 +3180,7 @@ extrude001 = extrude(sketch001, length = 40)
}) })
const shellSketchOnFacesCases = [ const shellSketchOnFacesCases = [
`@settings(defaultLengthUnit = in) `sketch001 = startSketchOn(XZ)
sketch001 = startSketchOn(XZ)
|> circle(center = [0, 0], radius = 100) |> circle(center = [0, 0], radius = 100)
|> extrude(length = 100) |> extrude(length = 100)
@ -3192,8 +3188,7 @@ sketch002 = startSketchOn(sketch001, 'END')
|> circle(center = [0, 0], radius = 50) |> circle(center = [0, 0], radius = 50)
|> extrude(length = 50) |> extrude(length = 50)
`, `,
`@settings(defaultLengthUnit = in) `sketch001 = startSketchOn(XZ)
sketch001 = startSketchOn(XZ)
|> circle(center = [0, 0], radius = 100) |> circle(center = [0, 0], radius = 100)
extrude001 = extrude(sketch001, length = 100) extrude001 = extrude(sketch001, length = 100)
@ -3474,41 +3469,8 @@ segAng(rectangleSegmentA002),
await cmdBar.progressCmdBar() await cmdBar.progressCmdBar()
await cmdBar.progressCmdBar() await cmdBar.progressCmdBar()
const newCodeToFind = `revolve001 = revolve(sketch002, angle = 360, axis = 'X')` const newCodeToFind = `revolve001 = revolve(sketch002, angle = 360, axis = X)`
expect(editor.expectEditor.toContain(newCodeToFind)).toBeTruthy() expect(editor.expectEditor.toContain(newCodeToFind)).toBeTruthy()
// Edit flow
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.expectEditor.toContain(
newCodeToFind.replace('angle = 360', 'angle = ' + newAngle)
)
}) })
test('revolve surface around edge from an extruded solid2d', async ({ test('revolve surface around edge from an extruded solid2d', async ({
context, context,
@ -3519,22 +3481,26 @@ segAng(rectangleSegmentA002),
toolbar, toolbar,
cmdBar, cmdBar,
}) => { }) => {
const initialCode = `sketch001 = startSketchOn(XZ) const initialCode = `
|> startProfileAt([-102.57, 101.72], %) sketch001 = startSketchOn(XZ)
|> angledLine([0, 202.6], %, $rectangleSegmentA001) |> startProfileAt([-102.57, 101.72], %)
|> angledLine([ |> angledLine([0, 202.6], %, $rectangleSegmentA001)
segAng(rectangleSegmentA001) - 90, |> angledLine([
202.6 segAng(rectangleSegmentA001) - 90,
], %, $rectangleSegmentB001) 202.6
|> angledLine([ ], %, $rectangleSegmentB001)
segAng(rectangleSegmentA001), |> angledLine([
-segLen(rectangleSegmentA001) segAng(rectangleSegmentA001),
], %, $rectangleSegmentC001) -segLen(rectangleSegmentA001)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)]) ], %, $rectangleSegmentC001)
|> close() |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close()
extrude001 = extrude(sketch001, length = 50) extrude001 = extrude(sketch001, length = 50)
sketch002 = startSketchOn(extrude001, rectangleSegmentA001) 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) => { await context.addInitScript((initialCode) => {
localStorage.setItem('persistCode', initialCode) localStorage.setItem('persistCode', initialCode)
@ -3552,49 +3518,9 @@ sketch002 = startSketchOn(extrude001, rectangleSegmentA001)
const lineCodeToSelection = `|> angledLine([0, 202.6], %, $rectangleSegmentA001)` const lineCodeToSelection = `|> angledLine([0, 202.6], %, $rectangleSegmentA001)`
await page.getByText(lineCodeToSelection).click() await page.getByText(lineCodeToSelection).click()
await cmdBar.progressCmdBar() await cmdBar.progressCmdBar()
await cmdBar.progressCmdBar()
await cmdBar.progressCmdBar()
const newCodeToFind = `revolve001 = revolve(sketch002, angle = 360, axis = rectangleSegmentA001)` const newCodeToFind = `revolve001 = revolve(sketch002, angle = 360, axis = getOppositeEdge(rectangleSegmentA001)) `
await editor.expectEditor.toContain(newCodeToFind) expect(editor.expectEditor.toContain(newCodeToFind)).toBeTruthy()
// Edit flow
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 page.getByRole('button', { name: 'Create new variable' }).click()
await expect(page.getByPlaceholder('Variable name')).toHaveValue(
'angle001'
)
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('angle001 = ' + newAngle)
await editor.expectEditor.toContain(
newCodeToFind.replace('angle = 360', 'angle = angle001')
)
}) })
test('revolve sketch circle around line segment from startProfileAt sketch', async ({ test('revolve sketch circle around line segment from startProfileAt sketch', async ({
context, context,
@ -3605,22 +3531,26 @@ sketch002 = startSketchOn(extrude001, rectangleSegmentA001)
toolbar, toolbar,
cmdBar, cmdBar,
}) => { }) => {
const initialCode = `sketch002 = startSketchOn(XY) const initialCode = `
|> startProfileAt([-2.02, 1.79], %) sketch002 = startSketchOn(XY)
|> xLine(length = 2.6) |> startProfileAt([-2.02, 1.79], %)
sketch001 = startSketchOn(-XY) |> xLine(length = 2.6)
|> startProfileAt([-0.48, 1.25], %) sketch001 = startSketchOn('-XY')
|> angledLine([0, 2.38], %, $rectangleSegmentA001) |> startProfileAt([-0.48, 1.25], %)
|> angledLine([segAng(rectangleSegmentA001) - 90, 2.4], %, $rectangleSegmentB001) |> angledLine([0, 2.38], %, $rectangleSegmentA001)
|> angledLine([ |> angledLine([segAng(rectangleSegmentA001) - 90, 2.4], %, $rectangleSegmentB001)
segAng(rectangleSegmentA001), |> angledLine([
-segLen(rectangleSegmentA001) segAng(rectangleSegmentA001),
], %, $rectangleSegmentC001) -segLen(rectangleSegmentA001)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)]) ], %, $rectangleSegmentC001)
|> close() |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
extrude001 = extrude(sketch001, length = 5) |> close()
sketch003 = startSketchOn(extrude001, 'START') extrude001 = extrude(sketch001, length = 5)
|> circle(center = [-0.69, 0.56], radius = 0.28) sketch003 = startSketchOn(extrude001, 'START')
|> circle(
center = [-0.69, 0.56],
radius = 0.28
)
` `
await context.addInitScript((initialCode) => { await context.addInitScript((initialCode) => {
@ -3639,44 +3569,9 @@ sketch003 = startSketchOn(extrude001, 'START')
const lineCodeToSelection = `|> xLine(length = 2.6)` const lineCodeToSelection = `|> xLine(length = 2.6)`
await page.getByText(lineCodeToSelection).click() await page.getByText(lineCodeToSelection).click()
await cmdBar.progressCmdBar() await cmdBar.progressCmdBar()
await cmdBar.progressCmdBar()
await cmdBar.progressCmdBar()
const newCodeToFind = `revolve001 = revolve(sketch003, angle = 360, axis = seg01)` const newCodeToFind = `revolve001 = revolve(sketch003, angle = 360, axis = seg01)`
expect(editor.expectEditor.toContain(newCodeToFind)).toBeTruthy() 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)
)
}) })
}) })
@ -3689,8 +3584,7 @@ sketch003 = startSketchOn(extrude001, 'START')
toolbar, toolbar,
cmdBar, cmdBar,
}) => { }) => {
const initialCode = `@settings(defaultLengthUnit = in) const initialCode = `sketch001 = startSketchOn(XZ)
sketch001 = startSketchOn(XZ)
profile001 = circle( profile001 = circle(
sketch001, sketch001,
center = [0, 0], center = [0, 0],

View File

@ -87,7 +87,7 @@ test(
const bracketDir = path.join(dir, 'bracket') const bracketDir = path.join(dir, 'bracket')
await fsp.mkdir(bracketDir, { recursive: true }) await fsp.mkdir(bracketDir, { recursive: true })
await fsp.copyFile( await fsp.copyFile(
executorInputPath('cylinder-inches.kcl'), executorInputPath('focusrite_scarlett_mounting_braket.kcl'),
path.join(bracketDir, 'main.kcl') path.join(bracketDir, 'main.kcl')
) )
}) })
@ -124,7 +124,7 @@ test(
const bracketDir = path.join(dir, 'bracket') const bracketDir = path.join(dir, 'bracket')
await fsp.mkdir(bracketDir, { recursive: true }) await fsp.mkdir(bracketDir, { recursive: true })
await fsp.copyFile( await fsp.copyFile(
executorInputPath('cylinder-inches.kcl'), executorInputPath('focusrite_scarlett_mounting_braket.kcl'),
path.join(bracketDir, 'main.kcl') path.join(bracketDir, 'main.kcl')
) )
const errorDir = path.join(dir, 'broken-code') const errorDir = path.join(dir, 'broken-code')
@ -162,7 +162,7 @@ test(
// gray at this pixel means the stream has loaded in the most // gray at this pixel means the stream has loaded in the most
// user way we can verify it (pixel color) // user way we can verify it (pixel color)
await expect await expect
.poll(() => u.getGreatestPixDiff(pointOnModel, [110, 110, 110]), { .poll(() => u.getGreatestPixDiff(pointOnModel, [85, 85, 85]), {
timeout: 10_000, timeout: 10_000,
}) })
.toBeLessThan(20) .toBeLessThan(20)
@ -213,7 +213,7 @@ test(
const bracketDir = path.join(dir, 'bracket') const bracketDir = path.join(dir, 'bracket')
await fsp.mkdir(bracketDir, { recursive: true }) await fsp.mkdir(bracketDir, { recursive: true })
await fsp.copyFile( await fsp.copyFile(
executorInputPath('cylinder-inches.kcl'), executorInputPath('focusrite_scarlett_mounting_braket.kcl'),
path.join(bracketDir, 'main.kcl') path.join(bracketDir, 'main.kcl')
) )
const emptyDir = path.join(dir, 'empty') const emptyDir = path.join(dir, 'empty')
@ -248,7 +248,7 @@ test(
// gray at this pixel means the stream has loaded in the most // gray at this pixel means the stream has loaded in the most
// user way we can verify it (pixel color) // user way we can verify it (pixel color)
await expect await expect
.poll(() => u.getGreatestPixDiff(pointOnModel, [125, 125, 125]), { .poll(() => u.getGreatestPixDiff(pointOnModel, [85, 85, 85]), {
timeout: 10_000, timeout: 10_000,
}) })
.toBeLessThan(15) .toBeLessThan(15)
@ -290,7 +290,7 @@ test(
const bracketDir = path.join(dir, 'bracket') const bracketDir = path.join(dir, 'bracket')
await fsp.mkdir(bracketDir, { recursive: true }) await fsp.mkdir(bracketDir, { recursive: true })
await fsp.copyFile( await fsp.copyFile(
executorInputPath('cylinder-inches.kcl'), executorInputPath('focusrite_scarlett_mounting_braket.kcl'),
path.join(bracketDir, 'main.kcl') path.join(bracketDir, 'main.kcl')
) )
@ -319,7 +319,7 @@ test(
// gray at this pixel means the stream has loaded in the most // gray at this pixel means the stream has loaded in the most
// user way we can verify it (pixel color) // user way we can verify it (pixel color)
await expect await expect
.poll(() => u.getGreatestPixDiff(pointOnModel, [125, 125, 125]), { .poll(() => u.getGreatestPixDiff(pointOnModel, [85, 85, 85]), {
timeout: 10_000, timeout: 10_000,
}) })
.toBeLessThan(15) .toBeLessThan(15)
@ -359,7 +359,7 @@ test(
const bracketDir = path.join(dir, 'bracket') const bracketDir = path.join(dir, 'bracket')
await fsp.mkdir(bracketDir, { recursive: true }) await fsp.mkdir(bracketDir, { recursive: true })
await fsp.copyFile( await fsp.copyFile(
executorInputPath('cylinder-inches.kcl'), executorInputPath('focusrite_scarlett_mounting_braket.kcl'),
path.join(bracketDir, 'main.kcl') path.join(bracketDir, 'main.kcl')
) )
await fsp.copyFile( await fsp.copyFile(
@ -393,7 +393,7 @@ test(
// gray at this pixel means the stream has loaded in the most // gray at this pixel means the stream has loaded in the most
// user way we can verify it (pixel color) // user way we can verify it (pixel color)
await expect await expect
.poll(() => u.getGreatestPixDiff(pointOnModel, [125, 125, 125]), { .poll(() => u.getGreatestPixDiff(pointOnModel, [85, 85, 85]), {
timeout: 10_000, timeout: 10_000,
}) })
.toBeLessThan(15) .toBeLessThan(15)
@ -443,6 +443,7 @@ test(
await page.getByText('broken-code').click() await page.getByText('broken-code').click()
// Gotcha: You can not use scene.waitForExecutionDone() since the KCL code is going to fail // Gotcha: You can not use scene.waitForExecutionDone() since the KCL code is going to fail
await expect(page.getByTestId('loading')).toBeAttached()
await expect(page.getByTestId('loading')).not.toBeAttached({ await expect(page.getByTestId('loading')).not.toBeAttached({
timeout: 20_000, timeout: 20_000,
}) })
@ -480,7 +481,7 @@ test.describe('Can export from electron app', () => {
const bracketDir = path.join(dir, 'bracket') const bracketDir = path.join(dir, 'bracket')
await fsp.mkdir(bracketDir, { recursive: true }) await fsp.mkdir(bracketDir, { recursive: true })
await fsp.copyFile( await fsp.copyFile(
executorInputPath('cylinder-inches.kcl'), executorInputPath('focusrite_scarlett_mounting_braket.kcl'),
path.join(bracketDir, 'main.kcl') path.join(bracketDir, 'main.kcl')
) )
}) })
@ -512,7 +513,7 @@ test.describe('Can export from electron app', () => {
// gray at this pixel means the stream has loaded in the most // gray at this pixel means the stream has loaded in the most
// user way we can verify it (pixel color) // user way we can verify it (pixel color)
await expect await expect
.poll(() => u.getGreatestPixDiff(pointOnModel, [125, 125, 125]), { .poll(() => u.getGreatestPixDiff(pointOnModel, [85, 85, 85]), {
timeout: 10_000, timeout: 10_000,
}) })
.toBeLessThan(15) .toBeLessThan(15)
@ -553,7 +554,7 @@ test.describe('Can export from electron app', () => {
}, },
{ timeout: 15_000 } { timeout: 15_000 }
) )
.toBeGreaterThan(50_000) .toBeGreaterThan(300_000)
// clean up exported file // clean up exported file
await fsp.rm(filepath) await fsp.rm(filepath)
@ -1506,12 +1507,7 @@ test(
await u.waitForPageLoad() await u.waitForPageLoad()
// The file should be prepopulated with the user's unit settings. await page.locator('.cm-content').fill(`sketch001 = startSketchOn(XZ)
await expect(page.locator('.cm-content')).toHaveText(
'@settings(defaultLengthUnit = in)'
)
await page.locator('.cm-content').fill(`sketch001 = startSketchOn('XZ')
|> startProfileAt([-87.4, 282.92], %) |> startProfileAt([-87.4, 282.92], %)
|> line(end = [324.07, 27.199], tag = $seg01) |> line(end = [324.07, 27.199], tag = $seg01)
|> line(end = [118.328, -291.754]) |> line(end = [118.328, -291.754])

View File

@ -4,9 +4,9 @@ import path from 'path'
import * as fsp from 'fs/promises' import * as fsp from 'fs/promises'
import { import {
getUtils, getUtils,
executorInputPath,
TEST_COLORS, TEST_COLORS,
TestColor, TestColor,
executorInputPath,
orRunWhenFullSuiteEnabled, orRunWhenFullSuiteEnabled,
} from './test-utils' } from './test-utils'
import { TEST_CODE_TRIGGER_ENGINE_EXPORT_ERROR } from './storageStates' import { TEST_CODE_TRIGGER_ENGINE_EXPORT_ERROR } from './storageStates'
@ -331,7 +331,7 @@ extrude001 = extrude(sketch001, length = 50)
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`@settings(defaultLengthUnit = mm) `@settings(defaultLengthUnit = mm)
sketch002 = startSketchOn(XY) sketch002 = startSketchOn('XY')
profile002 = startProfileAt([72.24, -52.05], sketch002) profile002 = startProfileAt([72.24, -52.05], sketch002)
|> angledLine([0, 181.26], %, $rectangleSegmentA001) |> angledLine([0, 181.26], %, $rectangleSegmentA001)
|> angledLine([ |> angledLine([
@ -582,7 +582,7 @@ extrude002 = extrude(profile002, length = 150)
const bracketDir = path.join(dir, 'bracket') const bracketDir = path.join(dir, 'bracket')
await fsp.mkdir(bracketDir, { recursive: true }) await fsp.mkdir(bracketDir, { recursive: true })
await fsp.copyFile( await fsp.copyFile(
executorInputPath('cylinder-inches.kcl'), executorInputPath('focusrite_scarlett_mounting_braket.kcl'),
path.join(bracketDir, 'main.kcl') path.join(bracketDir, 'main.kcl')
) )
}) })
@ -619,7 +619,6 @@ extrude002 = extrude(profile002, length = 150)
test(`View gizmo stays visible even when zoomed out all the way`, async ({ test(`View gizmo stays visible even when zoomed out all the way`, async ({
page, page,
homePage, homePage,
scene,
}) => { }) => {
const u = await getUtils(page) const u = await getUtils(page)
@ -633,7 +632,7 @@ extrude002 = extrude(profile002, length = 150)
await test.step(`Load an empty file`, async () => { await test.step(`Load an empty file`, async () => {
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem('persistCode', '@settings(defaultLengthUnit = in)') localStorage.setItem('persistCode', '')
}) })
await page.setBodyDimensions({ width: 1200, height: 500 }) await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene() await homePage.goToModelingScene()
@ -647,31 +646,22 @@ extrude002 = extrude(profile002, length = 150)
timeout: 5000, timeout: 5000,
message: 'Plane color is visible', message: 'Plane color is visible',
}) })
.toBeLessThanOrEqual(20) .toBeLessThanOrEqual(15)
await expect(scene.startEditSketchBtn).toBeEnabled()
let maxZoomOuts = 10 let maxZoomOuts = 10
let middlePixelIsBackgroundColor = let middlePixelIsBackgroundColor =
(await middlePixelIsColor(bgColor)) < 10 (await middlePixelIsColor(bgColor)) < 10
console.time('pressing control')
await page.keyboard.down('Control')
while (!middlePixelIsBackgroundColor && maxZoomOuts > 0) { while (!middlePixelIsBackgroundColor && maxZoomOuts > 0) {
await page.waitForTimeout(100) await page.keyboard.down('Control')
await page.mouse.move(650, 460) await page.mouse.move(600, 460)
console.time('moved to start point')
await page.mouse.down({ button: 'right' }) await page.mouse.down({ button: 'right' })
console.time('moused down') await page.mouse.move(600, 50, { steps: 20 })
await page.mouse.move(650, 50, { steps: 20 })
console.time('moved to end point')
await page.waitForTimeout(100)
await page.mouse.up({ button: 'right' }) await page.mouse.up({ button: 'right' })
console.time('moused up') await page.keyboard.up('Control')
await page.waitForTimeout(100)
maxZoomOuts-- maxZoomOuts--
middlePixelIsBackgroundColor = (await middlePixelIsColor(bgColor)) < 15 middlePixelIsBackgroundColor = (await middlePixelIsColor(bgColor)) < 10
} }
await page.keyboard.up('Control')
expect(middlePixelIsBackgroundColor, { expect(middlePixelIsBackgroundColor, {
message: 'We should not see the default planes', message: 'We should not see the default planes',
@ -688,12 +678,13 @@ extrude002 = extrude(profile002, length = 150)
homePage, homePage,
scene, scene,
toolbar, toolbar,
viewport,
}) => { }) => {
await context.folderSetupFn(async (dir) => { await context.folderSetupFn(async (dir) => {
const legoDir = path.join(dir, 'lego') const legoDir = path.join(dir, 'lego')
await fsp.mkdir(legoDir, { recursive: true }) await fsp.mkdir(legoDir, { recursive: true })
await fsp.copyFile( await fsp.copyFile(
executorInputPath('e2e-can-sketch-on-chamfer.kcl'), executorInputPath('lego.kcl'),
path.join(legoDir, 'main.kcl') path.join(legoDir, 'main.kcl')
) )
}) })
@ -706,8 +697,11 @@ extrude002 = extrude(profile002, length = 150)
await scene.loadingIndicator.waitFor({ state: 'detached' }) await scene.loadingIndicator.waitFor({ state: 'detached' })
}) })
await test.step(`The part should start loading quickly, not waiting until execution is complete`, async () => { await test.step(`The part should start loading quickly, not waiting until execution is complete`, async () => {
// TODO: use the viewport size to pick the center point, but the `viewport` fixture's values were wrong. await scene.expectPixelColor(
await scene.expectPixelColor([116, 116, 116], { x: 500, y: 250 }, 15) [143, 143, 143],
{ x: (viewport?.width ?? 1200) / 2, y: (viewport?.height ?? 500) / 2 },
15
)
}) })
}) })

View File

@ -113,8 +113,7 @@ test.describe('Sketch tests', { tag: ['@skipWin'] }, () => {
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`@settings(defaultLengthUnit = in) `sketch001 = startSketchOn(XZ)
sketch001 = startSketchOn(XZ)
|> startProfileAt([2.61, -4.01], %) |> startProfileAt([2.61, -4.01], %)
|> xLine(length = 8.73) |> xLine(length = 8.73)
|> tangentialArcTo([8.33, -1.31], %)` |> tangentialArcTo([8.33, -1.31], %)`
@ -160,10 +159,7 @@ sketch001 = startSketchOn(XZ)
await page.mouse.click(700, 200) await page.mouse.click(700, 200)
await expect.poll(u.normalisedEditorCode, { timeout: 1000 }) await expect.poll(u.normalisedEditorCode, { timeout: 1000 })
.toBe(`@settings(defaultLengthUnit = in) .toBe(`sketch002 = startSketchOn(XZ)
sketch002 = startSketchOn(XZ)
sketch001 = startProfileAt([12.34, -12.34], sketch002) sketch001 = startProfileAt([12.34, -12.34], sketch002)
|> yLine(length = 12.34) |> yLine(length = 12.34)
@ -678,7 +674,7 @@ sketch001 = startProfileAt([12.34, -12.34], sketch002)
|> line(end = [12.73, -0.09]) |> line(end = [12.73, -0.09])
|> tangentialArcTo([24.95, -5.38], %) |> tangentialArcTo([24.95, -5.38], %)
|> close() |> close()
|> revolve(axis = "X")` |> revolve(axis = X)`
) )
}) })
@ -765,7 +761,7 @@ sketch001 = startProfileAt([12.34, -12.34], sketch002)
|> tangentialArcTo([24.95, -5.38], %) |> tangentialArcTo([24.95, -5.38], %)
|> line(end = [1.97, 2.06]) |> line(end = [1.97, 2.06])
|> close() |> close()
|> revolve(axis = "X")`) |> revolve(axis = X)`)
}) })
test('Can add multiple sketches', async ({ page, homePage }) => { test('Can add multiple sketches', async ({ page, homePage }) => {
const u = await getUtils(page) const u = await getUtils(page)
@ -793,8 +789,7 @@ sketch001 = startProfileAt([12.34, -12.34], sketch002)
200 200
) )
let codeStr = let codeStr = 'sketch001 = startSketchOn(XY)'
'@settings(defaultLengthUnit = in)sketch001 = startSketchOn(XY)'
await page.mouse.click(center.x, viewportSize.height * 0.55) await page.mouse.click(center.x, viewportSize.height * 0.55)
await expect(u.codeLocator).toHaveText(codeStr) await expect(u.codeLocator).toHaveText(codeStr)
@ -873,8 +868,7 @@ sketch001 = startProfileAt([12.34, -12.34], sketch002)
await u.openDebugPanel() await u.openDebugPanel()
const code = `@settings(defaultLengthUnit = in) const code = `sketch001 = startSketchOn(-XZ)
sketch001 = startSketchOn(-XZ)
profile001 = startProfileAt([${roundOff(scale * 69.6)}, ${roundOff( profile001 = startProfileAt([${roundOff(scale * 69.6)}, ${roundOff(
scale * 34.8 scale * 34.8
)}], sketch001) )}], sketch001)
@ -904,7 +898,7 @@ profile001 = startProfileAt([${roundOff(scale * 69.6)}, ${roundOff(
await page.mouse.move(700, 200, { steps: 10 }) await page.mouse.move(700, 200, { steps: 10 })
await page.mouse.click(700, 200, { delay: 200 }) await page.mouse.click(700, 200, { delay: 200 })
await expect(page.locator('.cm-content')).toHaveText( await expect(page.locator('.cm-content')).toHaveText(
`@settings(defaultLengthUnit = in)sketch001 = startSketchOn(-XZ)` `sketch001 = startSketchOn(-XZ)`
) )
let prevContent = await page.locator('.cm-content').innerText() let prevContent = await page.locator('.cm-content').innerText()
@ -1215,7 +1209,7 @@ profile001 = startProfileAt([${roundOff(scale * 69.6)}, ${roundOff(
|> xLine(endAbsolute = 0 + .001) |> xLine(endAbsolute = 0 + .001)
|> yLine(endAbsolute = 0) |> yLine(endAbsolute = 0)
|> close() |> close()
|> revolve(axis = "Y") |> revolve(axis = Y)
return lugSketch return lugSketch
} }
@ -1432,8 +1426,7 @@ test.describe(`Sketching with offset planes`, () => {
await context.addInitScript(() => { await context.addInitScript(() => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`@settings(defaultLengthUnit = in) `offsetPlane001 = offsetPlane(XY, offset = 10)`
offsetPlane001 = offsetPlane(XY, offset = 10)`
) )
}) })
@ -1447,7 +1440,7 @@ offsetPlane001 = offsetPlane(XY, offset = 10)`
await test.step(`Hovering should highlight code`, async () => { await test.step(`Hovering should highlight code`, async () => {
await planeHover() await planeHover()
await editor.expectState({ await editor.expectState({
activeLines: [`@settings(defaultLengthUnit = in)`], activeLines: [`offsetPlane001=offsetPlane(XY,offset=10)`],
diagnostics: [], diagnostics: [],
highlightedCode: 'offsetPlane(XY, offset = 10)', highlightedCode: 'offsetPlane(XY, offset = 10)',
}) })
@ -1460,7 +1453,7 @@ offsetPlane001 = offsetPlane(XY, offset = 10)`
await expect(toolbar.lineBtn).toBeEnabled() await expect(toolbar.lineBtn).toBeEnabled()
await editor.expectEditor.toContain('startSketchOn(offsetPlane001)') await editor.expectEditor.toContain('startSketchOn(offsetPlane001)')
await editor.expectState({ await editor.expectState({
activeLines: [`@settings(defaultLengthUnit = in)`], activeLines: [`offsetPlane001=offsetPlane(XY,offset=10)`],
diagnostics: [], diagnostics: [],
highlightedCode: '', highlightedCode: '',
}) })
@ -1611,8 +1604,7 @@ profile002 = startProfileAt([117.2, 56.08], sketch001)
await context.addInitScript(() => { await context.addInitScript(() => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`@settings(defaultLengthUnit = in) `sketch001 = startSketchOn(XZ)
sketch001 = startSketchOn(XZ)
profile002 = startProfileAt([40.68, 87.67], sketch001) profile002 = startProfileAt([40.68, 87.67], sketch001)
|> xLine(length = 239.17) |> xLine(length = 239.17)
profile003 = startProfileAt([206.63, -56.73], sketch001) profile003 = startProfileAt([206.63, -56.73], sketch001)
@ -2180,8 +2172,7 @@ profile003 = startProfileAt([206.63, -56.73], sketch001)
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`@settings(defaultLengthUnit = in) `sketch001 = startSketchOn(XZ)
sketch001 = startSketchOn(XZ)
profile001 = startProfileAt([6.24, 4.54], sketch001) profile001 = startProfileAt([6.24, 4.54], sketch001)
|> line(end = [-0.41, 6.99]) |> line(end = [-0.41, 6.99])
|> line(end = [8.61, 0.74]) |> line(end = [8.61, 0.74])
@ -2326,8 +2317,7 @@ profile004 = circleThreePoint(sketch001, p1 = [13.44, -6.8], p2 = [13.39, -2.07]
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`@settings(defaultLengthUnit = in) `sketch001 = startSketchOn(XZ)
sketch001 = startSketchOn(XZ)
profile001 = startProfileAt([6.24, 4.54], sketch001) profile001 = startProfileAt([6.24, 4.54], sketch001)
|> line(end = [-0.41, 6.99]) |> line(end = [-0.41, 6.99])
|> line(end = [8.61, 0.74]) |> line(end = [8.61, 0.74])
@ -2432,8 +2422,7 @@ profile003 = circle(sketch001, center = [6.92, -4.2], radius = 3.16)
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`@settings(defaultLengthUnit = in) `sketch001 = startSketchOn(XZ)
sketch001 = startSketchOn(XZ)
profile001 = startProfileAt([-63.43, 193.08], sketch001) profile001 = startProfileAt([-63.43, 193.08], sketch001)
|> line(end = [168.52, 149.87]) |> line(end = [168.52, 149.87])
|> line(end = [190.29, -39.18]) |> line(end = [190.29, -39.18])
@ -2497,11 +2486,7 @@ extrude001 = extrude(profile003, length = 5)
page, page,
}) => { }) => {
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem('persistCode', `myVar = 5`)
'persistCode',
`@settings(defaultLengthUnit = in)
myVar = 5`
)
}) })
await page.setBodyDimensions({ width: 1000, height: 500 }) await page.setBodyDimensions({ width: 1000, height: 500 })
@ -2548,8 +2533,7 @@ extrude001 = extrude(profile003, length = 5)
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`@settings(defaultLengthUnit = in) `sketch001 = startSketchOn(XZ)
sketch001 = startSketchOn(XZ)
profile001 = startProfileAt([85.19, 338.59], sketch001) profile001 = startProfileAt([85.19, 338.59], sketch001)
|> line(end = [213.3, -94.52]) |> line(end = [213.3, -94.52])
|> line(end = [-230.09, -55.34]) |> line(end = [-230.09, -55.34])
@ -2591,8 +2575,7 @@ profile002 = startProfileAt([85.81, 52.55], sketch002)
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`@settings(defaultLengthUnit = in) `thePart = startSketchOn(XZ)
thePart = startSketchOn(XZ)
|> startProfileAt([7.53, 10.51], %) |> startProfileAt([7.53, 10.51], %)
|> line(end = [12.54, 1.83]) |> line(end = [12.54, 1.83])
|> line(end = [6.65, -6.91]) |> line(end = [6.65, -6.91])
@ -2653,8 +2636,7 @@ extrude001 = extrude(thePart, length = 75)
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`@settings(defaultLengthUnit = in) `sketch001 = startSketchOn(XZ)
sketch001 = startSketchOn(XZ)
profile001 = startProfileAt([6.71, -3.66], sketch001) profile001 = startProfileAt([6.71, -3.66], sketch001)
|> line(end = [2.65, 9.02], tag = $seg02) |> line(end = [2.65, 9.02], tag = $seg02)
|> line(end = [3.73, -9.36], tag = $seg01) |> line(end = [3.73, -9.36], tag = $seg01)
@ -2827,8 +2809,7 @@ extrude003 = extrude(profile011, length = 2.5)
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`@settings(defaultLengthUnit = in) `sketch001 = startSketchOn(XZ)
sketch001 = startSketchOn(XZ)
profile001 = startProfileAt([34, 42.66], sketch001) profile001 = startProfileAt([34, 42.66], sketch001)
|> line(end = [102.65, 151.99]) |> line(end = [102.65, 151.99])
|> line(end = [76, -138.66]) |> line(end = [76, -138.66])

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 42 KiB

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: 55 KiB

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 142 KiB

After

Width:  |  Height:  |  Size: 143 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 125 KiB

After

Width:  |  Height:  |  Size: 131 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

After

Width:  |  Height:  |  Size: 68 KiB

View File

@ -1,5 +1,5 @@
{ {
"original_source_code": "sketch001 = startSketchOn('XZ')\nprofile001 = startProfileAt([57.81, 250.51], sketch001)\n |> line(end = [121.13, 56.63], tag = $seg02)\n |> line(end = [83.37, -34.61], tag = $seg01)\n |> line(end = [19.66, -116.4])\n |> line(end = [-221.8, -41.69])\n |> line(endAbsolute = [profileStartX(%), profileStartY(%)])\n |> close()\nextrude001 = extrude(profile001, length = 200)\nsketch002 = startSketchOn('XZ')\n |> startProfileAt([-73.64, -42.89], %)\n |> xLine(length = 173.71)\n |> line(end = [-22.12, -94.4])\n |> xLine(length = -156.98)\n |> line(endAbsolute = [profileStartX(%), profileStartY(%)])\n |> close()\nextrude002 = extrude(sketch002, length = 50)\nsketch003 = startSketchOn(XY)\n |> startProfileAt([52.92, 157.81], %)\n |> angledLine([0, 176.4], %, $rectangleSegmentA001)\n |> angledLine([\n segAng(rectangleSegmentA001) - 90,\n 53.4\n ], %, $rectangleSegmentB001)\n |> angledLine([\n segAng(rectangleSegmentA001),\n -segLen(rectangleSegmentA001)\n ], %, $rectangleSegmentC001)\n |> line(endAbsolute = [profileStartX(%), profileStartY(%)])\n |> close()\nextrude003 = extrude(sketch003, length = 20)\n", "original_source_code": "sketch001 = startSketchOn('XZ')\nprofile001 = startProfileAt([57.81, 250.51], sketch001)\n |> line(end = [121.13, 56.63], tag = $seg02)\n |> line(end = [83.37, -34.61], tag = $seg01)\n |> line(end = [19.66, -116.4])\n |> line(end = [-221.8, -41.69])\n |> line(endAbsolute = [profileStartX(%), profileStartY(%)])\n |> close()\nextrude001 = extrude(profile001, length = 200)\nsketch002 = startSketchOn('XZ')\n |> startProfileAt([-73.64, -42.89], %)\n |> xLine(length = 173.71)\n |> line(end = [-22.12, -94.4])\n |> xLine(length = -156.98)\n |> line(endAbsolute = [profileStartX(%), profileStartY(%)])\n |> close()\nextrude002 = extrude(sketch002, length = 50)\nsketch003 = startSketchOn('XY')\n |> startProfileAt([52.92, 157.81], %)\n |> angledLine([0, 176.4], %, $rectangleSegmentA001)\n |> angledLine([\n segAng(rectangleSegmentA001) - 90,\n 53.4\n ], %, $rectangleSegmentB001)\n |> angledLine([\n segAng(rectangleSegmentA001),\n -segLen(rectangleSegmentA001)\n ], %, $rectangleSegmentC001)\n |> line(endAbsolute = [profileStartX(%), profileStartY(%)])\n |> close()\nextrude003 = extrude(sketch003, length = 20)\n",
"prompt": "make this neon green please, use #39FF14", "prompt": "make this neon green please, use #39FF14",
"source_ranges": [ "source_ranges": [
{ {

View File

@ -4,6 +4,7 @@ import {
getUtils, getUtils,
TEST_COLORS, TEST_COLORS,
pollEditorLinesSelectedLength, pollEditorLinesSelectedLength,
executorInputPath,
orRunWhenFullSuiteEnabled, orRunWhenFullSuiteEnabled,
} from './test-utils' } from './test-utils'
import { XOR } from 'lib/utils' import { XOR } from 'lib/utils'
@ -80,8 +81,7 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`@settings(defaultLengthUnit = in) `yo = 79
yo = 79
part001 = startSketchOn(XZ) part001 = startSketchOn(XZ)
|> startProfileAt([-7.54, -26.74], %) |> startProfileAt([-7.54, -26.74], %)
|> line(end = [74.36, 130.4], tag = $seg01) |> line(end = [74.36, 130.4], tag = $seg01)
@ -145,8 +145,7 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`@settings(defaultLengthUnit = in) `yo = 5
yo = 5
part001 = startSketchOn(XZ) part001 = startSketchOn(XZ)
|> startProfileAt([-7.54, -26.74], %) |> startProfileAt([-7.54, -26.74], %)
|> line(end = [74.36, 130.4], tag = $seg01) |> line(end = [74.36, 130.4], tag = $seg01)
@ -160,6 +159,31 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
|> xLine(length = segLen(seg_what)) |> xLine(length = segLen(seg_what))
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])` |> line(endAbsolute = [profileStartX(%), profileStartY(%)])`
) )
const isChecked = await createNewVariableCheckbox.isChecked()
const addVariable = testName === 'Add variable'
XOR(isChecked, addVariable) && // XOR because no need to click the checkbox if the state is already correct
(await createNewVariableCheckbox.click())
await page
.getByRole('button', { name: 'Add constraining value' })
.click()
// Wait for the codemod to take effect
await expect(page.locator('.cm-content')).toContainText(`angle: -57,`)
await expect(page.locator('.cm-content')).toContainText(
`offset: ${offset},`
)
await pollEditorLinesSelectedLength(page, 2)
const activeLinesContent = await page.locator('.cm-activeLine').all()
await expect(activeLinesContent[0]).toHaveText(
`|> line(end = [74.36, 130.4], tag = $seg01)`
)
await expect(activeLinesContent[1]).toHaveText(`}, %)`)
// checking the count of the overlays is a good proxy check that the client sketch scene is in a good state
await expect(page.getByTestId('segment-overlay')).toHaveCount(4)
}) })
const u = await getUtils(page) const u = await getUtils(page)
await page.setBodyDimensions({ width: 1200, height: 500 }) await page.setBodyDimensions({ width: 1200, height: 500 })
@ -253,8 +277,7 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`@settings(defaultLengthUnit = in) `yo = 5
yo = 5
part001 = startSketchOn(XZ) part001 = startSketchOn(XZ)
|> startProfileAt([-7.54, -26.74], %) |> startProfileAt([-7.54, -26.74], %)
|> line(end = [74.36, 130.4]) |> line(end = [74.36, 130.4])
@ -364,8 +387,7 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`@settings(defaultLengthUnit = in) `yo = 5
yo = 5
part001 = startSketchOn(XZ) part001 = startSketchOn(XZ)
|> startProfileAt([-7.54, -26.74], %) |> startProfileAt([-7.54, -26.74], %)
|> line(end = [74.36, 130.4]) |> line(end = [74.36, 130.4])
@ -478,8 +500,7 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`@settings(defaultLengthUnit = in) `yo = 5
yo = 5
part001 = startSketchOn(XZ) part001 = startSketchOn(XZ)
|> startProfileAt([-7.54, -26.74], %) |> startProfileAt([-7.54, -26.74], %)
|> line(end = [74.36, 130.4]) |> line(end = [74.36, 130.4])
@ -581,8 +602,7 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`@settings(defaultLengthUnit = in) `yo = 5
yo = 5
part001 = startSketchOn(XZ) part001 = startSketchOn(XZ)
|> startProfileAt([-7.54, -26.74], %) |> startProfileAt([-7.54, -26.74], %)
|> line(end = [74.36, 130.4]) |> line(end = [74.36, 130.4])
@ -668,8 +688,7 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`@settings(defaultLengthUnit = in) `yo = 5
yo = 5
part001 = startSketchOn(XZ) part001 = startSketchOn(XZ)
|> startProfileAt([-7.54, -26.74], %) |> startProfileAt([-7.54, -26.74], %)
|> line(end = [74.36, 130.4]) |> line(end = [74.36, 130.4])
@ -749,8 +768,7 @@ part002 = startSketchOn(XZ)
await page.addInitScript(async (customCode) => { await page.addInitScript(async (customCode) => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`@settings(defaultLengthUnit = in) `yo = 5
yo = 5
part001 = startSketchOn(XZ) part001 = startSketchOn(XZ)
|> startProfileAt([-7.54, -26.74], %) |> startProfileAt([-7.54, -26.74], %)
|> line(end = [74.36, 130.4]) |> line(end = [74.36, 130.4])
@ -851,8 +869,7 @@ part002 = startSketchOn(XZ)
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`@settings(defaultLengthUnit = in) `yo = 5
yo = 5
part001 = startSketchOn(XZ) part001 = startSketchOn(XZ)
|> startProfileAt([-7.54, -26.74], %) |> startProfileAt([-7.54, -26.74], %)
|> line(end = [74.36, 130.4]) |> line(end = [74.36, 130.4])
@ -933,8 +950,7 @@ part002 = startSketchOn(XZ)
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`@settings(defaultLengthUnit = in) `yo = 5
yo = 5
part001 = startSketchOn(XZ) part001 = startSketchOn(XZ)
|> startProfileAt([-7.54, -26.74], %) |> startProfileAt([-7.54, -26.74], %)
|> line(end = [74.36, 130.4]) |> line(end = [74.36, 130.4])
@ -1101,19 +1117,9 @@ test.describe('Electron constraint tests', () => {
await context.folderSetupFn(async (dir) => { await context.folderSetupFn(async (dir) => {
const bracketDir = path.join(dir, 'test-sample') const bracketDir = path.join(dir, 'test-sample')
await fsp.mkdir(bracketDir, { recursive: true }) await fsp.mkdir(bracketDir, { recursive: true })
await fsp.writeFile( await fsp.copyFile(
path.join(bracketDir, 'main.kcl'), executorInputPath('angled_line.kcl'),
`@settings(defaultLengthUnit = in) path.join(bracketDir, 'main.kcl')
const part001 = startSketchOn(XY)
|> startProfileAt([4.83, 12.56], %)
|> line(end = [15.1, 2.48])
|> line(end = [3.15, -9.85], tag = $seg01)
|> line(end = [-15.17, -4.1])
|> angledLine([segAng(seg01), 12.35], %)
|> line(end = [-13.02, 10.03])
|> close()
|> extrude(length = 4)`,
'utf-8'
) )
}) })

View File

@ -255,7 +255,7 @@ test.describe(`Testing gizmo, fixture-based`, () => {
await context.addInitScript(() => { await context.addInitScript(() => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`@settings(defaultLengthUnit = in) `
const sketch002 = startSketchOn(XZ) const sketch002 = startSketchOn(XZ)
|> startProfileAt([-108.83, -57.48], %) |> startProfileAt([-108.83, -57.48], %)
|> angledLine([0, 105.13], %, $rectangleSegmentA001) |> angledLine([0, 105.13], %, $rectangleSegmentA001)

View File

@ -46,7 +46,7 @@ test.describe('Testing in-app sample loading', () => {
page.getByRole('option', { page.getByRole('option', {
name, name,
}) })
const warningText = page.getByText('Overwrite current file with sample?') const warningText = page.getByText('Overwrite current file and units?')
const confirmButton = page.getByRole('button', { name: 'Submit command' }) const confirmButton = page.getByRole('button', { name: 'Submit command' })
await test.step(`Precondition: check the initial code`, async () => { await test.step(`Precondition: check the initial code`, async () => {
@ -110,9 +110,11 @@ test.describe('Testing in-app sample loading', () => {
const commandMethodOption = page.getByRole('option', { const commandMethodOption = page.getByRole('option', {
name: 'Overwrite', name: 'Overwrite',
}) })
const newFileWarning = page.getByText('Create a new file from sample?') const newFileWarning = page.getByText(
'Create a new file, overwrite project units?'
)
const overwriteWarning = page.getByText( const overwriteWarning = page.getByText(
'Overwrite current file with sample?' 'Overwrite current file and units?'
) )
const confirmButton = page.getByRole('button', { name: 'Submit command' }) const confirmButton = page.getByRole('button', { name: 'Submit command' })
const projectMenuButton = page.getByTestId('project-sidebar-toggle') const projectMenuButton = page.getByTestId('project-sidebar-toggle')

View File

@ -210,8 +210,7 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`@settings(defaultLengthUnit = in) `part001 = startSketchOn(XZ)
part001 = startSketchOn(XZ)
|> startProfileAt([5 + 0, 20 + 0], %) |> startProfileAt([5 + 0, 20 + 0], %)
|> line(end = [0.5, -14 + 0]) |> line(end = [0.5, -14 + 0])
|> angledLine({ angle = 3 + 0, length = 32 + 0 }, %) |> angledLine({ angle = 3 + 0, length = 32 + 0 }, %)
@ -381,8 +380,7 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`@settings(defaultLengthUnit = in) `yRel001 = -14
yRel001 = -14
xRel001 = 0.5 xRel001 = 0.5
angle001 = 3 angle001 = 3
len001 = 32 len001 = 32
@ -461,8 +459,7 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`@settings(defaultLengthUnit = in) `part001 = startSketchOn(XZ)
part001 = startSketchOn(XZ)
|> startProfileAt([0, 0], %) |> startProfileAt([0, 0], %)
|> line(end = [0.5, -14 + 0]) |> line(end = [0.5, -14 + 0])
|> angledLine({ angle = 3 + 0, length = 32 + 0 }, %) |> angledLine({ angle = 3 + 0, length = 32 + 0 }, %)
@ -593,8 +590,7 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`@settings(defaultLengthUnit = in) `part001 = startSketchOn(XZ)
part001 = startSketchOn(XZ)
|> startProfileAt([0, 0], %) |> startProfileAt([0, 0], %)
|> line(end = [0.5, -14 + 0]) |> line(end = [0.5, -14 + 0])
|> angledLine({ angle = 3 + 0, length = 32 + 0 }, %) |> angledLine({ angle = 3 + 0, length = 32 + 0 }, %)
@ -755,8 +751,7 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`@settings(defaultLengthUnit = in) `part001 = startSketchOn(XZ)
part001 = startSketchOn(XZ)
|> startProfileAt([0, 0], %) |> startProfileAt([0, 0], %)
|> line(end = [0.5, -14 + 0]) |> line(end = [0.5, -14 + 0])
|> angledLine({ angle = 3 + 0, length = 32 + 0 }, %) |> angledLine({ angle = 3 + 0, length = 32 + 0 }, %)
@ -836,8 +831,7 @@ test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`@settings(defaultLengthUnit = in) `sketch001 = startSketchOn(XZ)
sketch001 = startSketchOn(XZ)
profile001 = startProfileAt([56.37, 120.33], sketch001) profile001 = startProfileAt([56.37, 120.33], sketch001)
|> line(end = [162.86, 106.48]) |> line(end = [162.86, 106.48])
|> arcTo({ |> arcTo({
@ -963,8 +957,7 @@ profile001 = startProfileAt([56.37, 120.33], sketch001)
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`@settings(defaultLengthUnit = in) `part001 = startSketchOn(XZ)
part001 = startSketchOn(XZ)
|> circle(center = [1 + 0, 0], radius = 8) |> circle(center = [1 + 0, 0], radius = 8)
` `
) )
@ -1084,8 +1077,7 @@ part001 = startSketchOn(XZ)
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`@settings(defaultLengthUnit = in) `part001 = startSketchOn(XZ)
part001 = startSketchOn(XZ)
|>startProfileAt([0, 0], %) |>startProfileAt([0, 0], %)
|> line(end = [0.5, -14 + 0]) |> line(end = [0.5, -14 + 0])
|> angledLine({ angle = 3 + 0, length = 32 + 0 }, %) |> angledLine({ angle = 3 + 0, length = 32 + 0 }, %)
@ -1359,8 +1351,7 @@ part001 = startSketchOn(XZ)
async ({ lineToBeDeleted, extraLine }) => { async ({ lineToBeDeleted, extraLine }) => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`@settings(defaultLengthUnit = in) `part001 = startSketchOn(XZ)
part001 = startSketchOn(XZ)
|> startProfileAt([5, 6], %) |> startProfileAt([5, 6], %)
|> ${lineToBeDeleted} |> ${lineToBeDeleted}
|> line(end = [-10, -15]) |> line(end = [-10, -15])
@ -1525,8 +1516,7 @@ part001 = startSketchOn(XZ)
async ({ lineToBeDeleted }) => { async ({ lineToBeDeleted }) => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`@settings(defaultLengthUnit = in) `part001 = startSketchOn(XZ)
part001 = startSketchOn(XZ)
|> startProfileAt([5, 6], %) |> startProfileAt([5, 6], %)
|> ${lineToBeDeleted} |> ${lineToBeDeleted}
|> line(end = [-10, -15]) |> line(end = [-10, -15])

View File

@ -68,20 +68,20 @@ test.describe('Testing selections', { tag: ['@skipWin'] }, () => {
await u.closeDebugPanel() await u.closeDebugPanel()
await page.mouse.click(startXPx + PUR * 10, 500 - PUR * 10) await page.mouse.click(startXPx + PUR * 10, 500 - PUR * 10)
await expect(page.locator('.cm-content')).toHaveText( await expect(page.locator('.cm-content')).toHaveText(
`@settings(defaultLengthUnit = in)sketch001 = startSketchOn(XZ)profile001 = startProfileAt(${commonPoints.startAt}, sketch001)` `sketch001 = startSketchOn(XZ)profile001 = startProfileAt(${commonPoints.startAt}, sketch001)`
) )
await page.waitForTimeout(100) await page.waitForTimeout(100)
await page.mouse.click(startXPx + PUR * 20, 500 - PUR * 10) await page.mouse.click(startXPx + PUR * 20, 500 - PUR * 10)
await expect(page.locator('.cm-content')) await expect(page.locator('.cm-content'))
.toHaveText(`@settings(defaultLengthUnit = in)sketch001 = startSketchOn(XZ)profile001 = startProfileAt(${commonPoints.startAt}, sketch001) .toHaveText(`sketch001 = startSketchOn(XZ)profile001 = startProfileAt(${commonPoints.startAt}, sketch001)
|> xLine(length = ${commonPoints.num1})`) |> xLine(length = ${commonPoints.num1})`)
await page.waitForTimeout(100) await page.waitForTimeout(100)
await page.mouse.click(startXPx + PUR * 20, 500 - PUR * 20) await page.mouse.click(startXPx + PUR * 20, 500 - PUR * 20)
await expect(page.locator('.cm-content')) await expect(page.locator('.cm-content'))
.toHaveText(`@settings(defaultLengthUnit = in)sketch001 = startSketchOn(XZ)profile001 = startProfileAt(${ .toHaveText(`sketch001 = startSketchOn(XZ)profile001 = startProfileAt(${
commonPoints.startAt commonPoints.startAt
}, sketch001) }, sketch001)
|> xLine(length = ${commonPoints.num1}) |> xLine(length = ${commonPoints.num1})
@ -89,7 +89,7 @@ test.describe('Testing selections', { tag: ['@skipWin'] }, () => {
await page.waitForTimeout(100) await page.waitForTimeout(100)
await page.mouse.click(startXPx, 500 - PUR * 20) await page.mouse.click(startXPx, 500 - PUR * 20)
await expect(page.locator('.cm-content')) await expect(page.locator('.cm-content'))
.toHaveText(`@settings(defaultLengthUnit = in)sketch001 = startSketchOn(XZ)profile001 = startProfileAt(${ .toHaveText(`sketch001 = startSketchOn(XZ)profile001 = startProfileAt(${
commonPoints.startAt commonPoints.startAt
}, sketch001) }, sketch001)
|> xLine(length = ${commonPoints.num1}) |> xLine(length = ${commonPoints.num1})
@ -260,8 +260,7 @@ test.describe('Testing selections', { tag: ['@skipWin'] }, () => {
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`@settings(defaultLengthUnit = in) `sketch001 = startSketchOn(XZ)
sketch001 = startSketchOn(XZ)
|> startProfileAt([-79.26, 95.04], %) |> startProfileAt([-79.26, 95.04], %)
|> line(end = [112.54, 127.64], tag = $seg02) |> line(end = [112.54, 127.64], tag = $seg02)
|> line(end = [170.36, -121.61], tag = $seg01) |> line(end = [170.36, -121.61], tag = $seg01)
@ -320,7 +319,7 @@ part009 = startSketchOn(XY)
|> line(end = [0, pipeLength]) |> line(end = [0, pipeLength])
|> angledLineToX({ angle = 60, to = pipeLargeDia }, %) |> angledLineToX({ angle = 60, to = pipeLargeDia }, %)
|> close() |> close()
rev = revolve(part009, axis = 'y') rev = revolve(part009, axis = Y)
sketch006 = startSketchOn(XY) sketch006 = startSketchOn(XY)
profile001 = circle( profile001 = circle(
sketch006, sketch006,
@ -377,7 +376,7 @@ profile003 = startProfileAt([40.16, -120.48], sketch006)
await page.waitForTimeout(200) await page.waitForTimeout(200)
await expect(u.codeLocator).not.toContainText( await expect(u.codeLocator).not.toContainText(
`rev = revolve(part009, axis: 'y')` `rev = revolve(part009, axis: Y)`
) )
// FIXME (commented section below), this test would select a wall that had a sketch on it, and delete the underlying extrude // FIXME (commented section below), this test would select a wall that had a sketch on it, and delete the underlying extrude
@ -529,8 +528,7 @@ profile001 = startProfileAt([7.49, 9.96], sketch001)
await page.addInitScript(async (KCL_DEFAULT_LENGTH) => { await page.addInitScript(async (KCL_DEFAULT_LENGTH) => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`@settings(defaultLengthUnit = in) `part001 = startSketchOn(XZ)
part001 = startSketchOn(XZ)
|> startProfileAt([20, 0], %) |> startProfileAt([20, 0], %)
|> line(end = [7.13, 4 + 0]) |> line(end = [7.13, 4 + 0])
|> angledLine({ angle = 3 + 0, length = 3.14 + 0 }, %) |> angledLine({ angle = 3 + 0, length = 3.14 + 0 }, %)
@ -749,8 +747,7 @@ part001 = startSketchOn(XZ)
await page.waitForTimeout(200) await page.waitForTimeout(200)
await u.removeCurrentCode() await u.removeCurrentCode()
await u.codeLocator.fill(`@settings(defaultLengthUnit = in) await u.codeLocator.fill(`sketch001 = startSketchOn(XZ)
sketch001 = startSketchOn(XZ)
|> startProfileAt([75.8, 317.2], %) // [$startCapTag, $EndCapTag] |> startProfileAt([75.8, 317.2], %) // [$startCapTag, $EndCapTag]
|> angledLine([0, 268.43], %, $rectangleSegmentA001) |> angledLine([0, 268.43], %, $rectangleSegmentA001)
|> angledLine([ |> angledLine([
@ -968,8 +965,7 @@ part001 = startSketchOn(XZ)
async ({ cases }) => { async ({ cases }) => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`@settings(defaultLengthUnit = in) `yo = 79
yo = 79
part001 = startSketchOn(XZ) part001 = startSketchOn(XZ)
|> startProfileAt([-7.54, -26.74], %) |> startProfileAt([-7.54, -26.74], %)
|> ${cases[0].expectedCode} |> ${cases[0].expectedCode}
@ -1024,8 +1020,7 @@ part001 = startSketchOn(XZ)
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`@settings(defaultLengthUnit = in) `sketch001 = startSketchOn(XZ)
sketch001 = startSketchOn(XZ)
|> startProfileAt([-79.26, 95.04], %) |> startProfileAt([-79.26, 95.04], %)
|> line(end = [112.54, 127.64]) |> line(end = [112.54, 127.64])
|> line(end = [170.36, -121.61], tag = $seg01) |> line(end = [170.36, -121.61], tag = $seg01)
@ -1258,7 +1253,7 @@ part001 = startSketchOn(XZ)
await page.mouse.click(700, 200) await page.mouse.click(700, 200)
await expect(page.locator('.cm-content')).toHaveText( await expect(page.locator('.cm-content')).toHaveText(
`@settings(defaultLengthUnit = in)sketch001 = startSketchOn(XZ)` `sketch001 = startSketchOn(XZ)`
) )
await page.waitForTimeout(600) await page.waitForTimeout(600)

View File

@ -271,7 +271,7 @@ test.describe('Testing settings', () => {
const bracketDir = join(dir, projectName) const bracketDir = join(dir, projectName)
await fsp.mkdir(bracketDir, { recursive: true }) await fsp.mkdir(bracketDir, { recursive: true })
await fsp.copyFile( await fsp.copyFile(
executorInputPath('cylinder-inches.kcl'), executorInputPath('focusrite_scarlett_mounting_braket.kcl'),
join(bracketDir, 'main.kcl') join(bracketDir, 'main.kcl')
) )
} }
@ -699,19 +699,19 @@ test.describe('Testing settings', () => {
name: 'Current units are: ', name: 'Current units are: ',
}) })
await gizmo.click() await gizmo.click()
const button = page.locator('ul').getByRole('button', { const button = page.getByRole('button', {
name: copy, name: copy,
exact: true, exact: true,
}) })
await button.click() await button.click()
const toastMessage = page.getByText( const toastMessage = page.getByText(
`Updated per-file units to ${unitOfMeasure}` `Set default unit to "${unitOfMeasure}" for this project`
) )
await expect(toastMessage).toBeVisible() await expect(toastMessage).toBeVisible()
} }
await changeUnitOfMeasureInGizmo('ft', 'Feet')
await changeUnitOfMeasureInGizmo('in', 'Inches') await changeUnitOfMeasureInGizmo('in', 'Inches')
await changeUnitOfMeasureInGizmo('ft', 'Feet')
await changeUnitOfMeasureInGizmo('yd', 'Yards') await changeUnitOfMeasureInGizmo('yd', 'Yards')
await changeUnitOfMeasureInGizmo('mm', 'Millimeters') await changeUnitOfMeasureInGizmo('mm', 'Millimeters')
await changeUnitOfMeasureInGizmo('cm', 'Centimeters') await changeUnitOfMeasureInGizmo('cm', 'Centimeters')
@ -951,9 +951,9 @@ test.describe('Testing settings', () => {
) )
}) })
await test.step(`Initial units from settings are ignored`, async () => { await test.step(`Initial units from settings`, async () => {
await homePage.openProject('project-000') await homePage.openProject('project-000')
await expect(unitsIndicator).toHaveText('Current units are: mm') await expect(unitsIndicator).toHaveText('Current units are: in')
}) })
await test.step(`Manually write inline settings`, async () => { await test.step(`Manually write inline settings`, async () => {

View File

@ -483,8 +483,7 @@ test('Sketch on face', async ({ page, homePage, scene, cmdBar, toolbar }) => {
await page.addInitScript(async () => { await page.addInitScript(async () => {
localStorage.setItem( localStorage.setItem(
'persistCode', 'persistCode',
`@settings(defaultLengthUnit = in) `sketch001 = startSketchOn(XZ)
sketch001 = startSketchOn(XZ)
|> startProfileAt([3.29, 7.86], %) |> startProfileAt([3.29, 7.86], %)
|> line(end = [2.48, 2.44]) |> line(end = [2.48, 2.44])
|> line(end = [2.66, 1.17]) |> line(end = [2.66, 1.17])

View File

@ -13,20 +13,20 @@
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@codemirror/autocomplete": "^6.18.6", "@codemirror/autocomplete": "^6.18.6",
"@codemirror/commands": "^6.8.1", "@codemirror/commands": "^6.8.0",
"@codemirror/language": "^6.11.0", "@codemirror/language": "^6.11.0",
"@codemirror/lint": "^6.8.5", "@codemirror/lint": "^6.8.4",
"@codemirror/search": "^6.5.10", "@codemirror/search": "^6.5.10",
"@codemirror/state": "^6.5.2", "@codemirror/state": "^6.4.1",
"@codemirror/theme-one-dark": "^6.1.2", "@codemirror/theme-one-dark": "^6.1.2",
"@csstools/postcss-oklab-function": "^4.0.8", "@csstools/postcss-oklab-function": "^4.0.7",
"@fortawesome/fontawesome-svg-core": "^6.7.2", "@fortawesome/fontawesome-svg-core": "^6.7.2",
"@fortawesome/free-brands-svg-icons": "^6.7.2", "@fortawesome/free-brands-svg-icons": "^6.7.2",
"@fortawesome/free-solid-svg-icons": "^6.7.2", "@fortawesome/free-solid-svg-icons": "^6.7.2",
"@fortawesome/react-fontawesome": "^0.2.0", "@fortawesome/react-fontawesome": "^0.2.0",
"@headlessui/react": "^1.7.19", "@headlessui/react": "^1.7.19",
"@headlessui/tailwindcss": "^0.2.2", "@headlessui/tailwindcss": "^0.2.0",
"@kittycad/lib": "2.0.23", "@kittycad/lib": "2.0.21",
"@lezer/highlight": "^1.2.1", "@lezer/highlight": "^1.2.1",
"@lezer/lr": "^1.4.1", "@lezer/lr": "^1.4.1",
"@react-hook/resize-observer": "^2.0.1", "@react-hook/resize-observer": "^2.0.1",
@ -37,11 +37,11 @@
"@xstate/react": "^4.1.1", "@xstate/react": "^4.1.1",
"bonjour-service": "^1.3.0", "bonjour-service": "^1.3.0",
"bson": "^6.10.3", "bson": "^6.10.3",
"chokidar": "^4.0.3", "chokidar": "^4.0.1",
"codemirror": "^6.0.1", "codemirror": "^6.0.1",
"decamelize": "^6.0.0", "decamelize": "^6.0.0",
"diff": "^7.0.0", "diff": "^7.0.0",
"electron-updater": "^6.6.2", "electron-updater": "^6.6.0",
"fuse.js": "^7.1.0", "fuse.js": "^7.1.0",
"html2canvas-pro": "^1.5.8", "html2canvas-pro": "^1.5.8",
"isomorphic-fetch": "^3.0.0", "isomorphic-fetch": "^3.0.0",
@ -94,11 +94,9 @@
"fetch:wasm": "./scripts/get-latest-wasm-bundle.sh", "fetch:wasm": "./scripts/get-latest-wasm-bundle.sh",
"fetch:wasm:windows": "./scripts/get-latest-wasm-bundle.ps1", "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", "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": "./scripts/build-wasm.sh",
"build:wasm:windows": "./scripts/build-wasm.ps1", "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\"", "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-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", "lint": "eslint --max-warnings 0 --ext .ts --ext .tsx src e2e packages/codemirror-lsp-client/src rust/kcl-language-server/client/src",
@ -164,15 +162,15 @@
"@iarna/toml": "^2.2.5", "@iarna/toml": "^2.2.5",
"@lezer/generator": "^1.7.2", "@lezer/generator": "^1.7.2",
"@nabla/vite-plugin-eslint": "^2.0.5", "@nabla/vite-plugin-eslint": "^2.0.5",
"@playwright/test": "^1.51.1", "@playwright/test": "^1.51.0",
"@testing-library/jest-dom": "^5.14.1", "@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^15.0.2", "@testing-library/react": "^15.0.2",
"@types/diff": "^7.0.2", "@types/diff": "^7.0.1",
"@types/electron": "^1.6.10", "@types/electron": "^1.6.10",
"@types/isomorphic-fetch": "^0.0.39", "@types/isomorphic-fetch": "^0.0.39",
"@types/minimist": "^1.2.5", "@types/minimist": "^1.2.5",
"@types/mocha": "^10.0.10", "@types/mocha": "^10.0.10",
"@types/node": "^22.13.14", "@types/node": "^22.13.9",
"@types/pixelmatch": "^5.2.6", "@types/pixelmatch": "^5.2.6",
"@types/pngjs": "^6.0.4", "@types/pngjs": "^6.0.4",
"@types/react": "^18.3.4", "@types/react": "^18.3.4",
@ -182,13 +180,13 @@
"@types/ua-parser-js": "^0.7.39", "@types/ua-parser-js": "^0.7.39",
"@types/uuid": "^9.0.8", "@types/uuid": "^9.0.8",
"@types/wicg-file-system-access": "^2023.10.5", "@types/wicg-file-system-access": "^2023.10.5",
"@types/ws": "^8.18.0", "@types/ws": "^8.5.13",
"@vitejs/plugin-react": "^4.3.4", "@vitejs/plugin-react": "^4.3.0",
"@vitest/web-worker": "^1.5.0", "@vitest/web-worker": "^1.5.0",
"@xstate/cli": "^0.5.17", "@xstate/cli": "^0.5.17",
"autoprefixer": "^10.4.21", "autoprefixer": "^10.4.19",
"electron": "^34.1.1", "electron": "^34.1.1",
"electron-builder": "^26.0.12", "electron-builder": "^26.0.6",
"eslint": "^8.0.1", "eslint": "^8.0.1",
"eslint-plugin-css-modules": "^2.12.0", "eslint-plugin-css-modules": "^2.12.0",
"eslint-plugin-import": "^2.31.0", "eslint-plugin-import": "^2.31.0",
@ -220,7 +218,7 @@
"vite-tsconfig-paths": "^4.3.2", "vite-tsconfig-paths": "^4.3.2",
"vitest": "^1.6.1", "vitest": "^1.6.1",
"vitest-webgl-canvas-mock": "^1.1.0", "vitest-webgl-canvas-mock": "^1.1.0",
"ws": "^8.18.1", "ws": "^8.17.0",
"yarn": "^1.22.22" "yarn": "^1.22.22"
}, },
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e" "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"

View File

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

View File

@ -35,7 +35,7 @@ ballsSketch = startSketchOn(XY)
|> close() |> close()
// Revolve the ball to make a sphere and pattern around the inside wall // Revolve the ball to make a sphere and pattern around the inside wall
balls = revolve(ballsSketch, axis = "X") balls = revolve(ballsSketch, axis = X)
|> patternCircular3d( |> patternCircular3d(
arcDegrees = 360, arcDegrees = 360,
axis = [0, 0, 1], axis = [0, 0, 1],
@ -60,7 +60,7 @@ chainSketch = startSketchOn(XY)
|> close() |> close()
// Revolve the chain sketch // Revolve the chain sketch
chainHead = revolve(chainSketch, axis = "X") chainHead = revolve(chainSketch, axis = X)
|> patternCircular3d( |> patternCircular3d(
arcDegrees = 360, arcDegrees = 360,
axis = [0, 0, 1], axis = [0, 0, 1],
@ -80,7 +80,7 @@ linkSketch = startSketchOn(XZ)
) )
// Revolve the link sketch // Revolve the link sketch
linkRevolve = revolve(linkSketch, axis = 'Y', angle = 360 / nBalls) linkRevolve = revolve(linkSketch, axis = Y, angle = 360 / nBalls)
|> patternCircular3d( |> patternCircular3d(
arcDegrees = 360, arcDegrees = 360,
axis = [0, 0, 1], axis = [0, 0, 1],

View File

@ -80,5 +80,5 @@ brakeCaliperSketch = startSketchOn(XY)
|> close() |> close()
// Revolve the brake caliper sketch // Revolve the brake caliper sketch
revolve(brakeCaliperSketch, axis = "Y", angle = -70) revolve(brakeCaliperSketch, axis = Y, angle = -70)
|> appearance(color = "#c82d2d", metalness = 90, roughness = 90) |> appearance(color = "#c82d2d", metalness = 90, roughness = 90)

View File

@ -41,5 +41,5 @@ tireSketch = startSketchOn(XY)
|> close() |> close()
// Revolve the sketch to create the tire // Revolve the sketch to create the tire
revolve(tireSketch, axis = "Y") revolve(tireSketch, axis = Y)
|> appearance(color = "#0f0f0f", roughness = 80) |> appearance(color = "#0f0f0f", roughness = 80)

View File

@ -54,7 +54,7 @@ wheelCenterInner = startSketchOn(XY)
|> yLine(endAbsolute = 0) |> yLine(endAbsolute = 0)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)]) |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close() |> close()
|> revolve(axis = 'y') |> revolve(axis = Y)
|> appearance(color = "#ffffff", metalness = 0, roughness = 0) |> appearance(color = "#ffffff", metalness = 0, roughness = 0)
wheelCenterOuter = startSketchOn(XY) wheelCenterOuter = startSketchOn(XY)
@ -68,7 +68,7 @@ wheelCenterOuter = startSketchOn(XY)
|> yLine(endAbsolute = -wheelWidth / 20) |> yLine(endAbsolute = -wheelWidth / 20)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)]) |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close() |> close()
|> revolve(axis = 'y') |> revolve(axis = Y)
|> appearance(color = "#ffffff", metalness = 0, roughness = 0) |> appearance(color = "#ffffff", metalness = 0, roughness = 0)
// Write a function that defines the spoke geometry, patterns and extrudes it // Write a function that defines the spoke geometry, patterns and extrudes it
@ -173,5 +173,5 @@ startSketchOn(XY)
|> xLine(length = wheelWidth * 0.03) |> xLine(length = wheelWidth * 0.03)
|> yLine(length = wheelWidth * 0.05) |> yLine(length = wheelWidth * 0.05)
|> close() |> close()
|> revolve(axis = 'y') |> revolve(axis = Y)
|> appearance(color = "#ffffff", metalness = 0, roughness = 0) |> appearance(color = "#ffffff", metalness = 0, roughness = 0)

View File

@ -32,7 +32,7 @@ fn lug(plane, length, diameter) {
|> xLine(endAbsolute = lugThreadDiameter) |> xLine(endAbsolute = lugThreadDiameter)
|> yLine(endAbsolute = 0) |> yLine(endAbsolute = 0)
|> close() |> close()
|> revolve(axis = "Y") |> revolve(axis = Y)
|> appearance(color = "#dbcd70", roughness = 90, metalness = 90) |> appearance(color = "#dbcd70", roughness = 90, metalness = 90)
return lugSketch return lugSketch
} }

View File

@ -12,7 +12,7 @@ import "car-tire.kcl" as carTire
import lugCount from "globals.kcl" import lugCount from "globals.kcl"
carRotor carRotor
|> translate(x = 0, y = 0.5, z = 0) |> translate(translate = [0, 0.5, 0])
carWheel carWheel
lugNut lugNut
|> patternCircular3d( |> patternCircular3d(
@ -23,5 +23,5 @@ lugNut
rotateDuplicates = false, rotateDuplicates = false,
) )
brakeCaliper brakeCaliper
|> translate(x = 0, y = 0.5, z = 0) |> translate(translate = [0, 0.5, 0])
carTire carTire

View File

@ -1,7 +1,6 @@
// Dual-Basin Utility Sink // Dual-Basin Utility Sink
// A stainless steel sink unit with dual rectangular basins and six under-counter storage compartments. // A stainless steel sink unit with dual rectangular basins and six under-counter storage compartments.
// set units
@settings(defaultLengthUnit = mm) @settings(defaultLengthUnit = mm)
// globals // globals
@ -13,7 +12,7 @@ profileThickness = 13
metalThickness = 2 metalThickness = 2
blockCount = 3 blockCount = 3
blockWidth = (tableWidth - profileThickness) / 3 blockWidth = (tableWidth-profileThickness) / 3
blockHeight = tableHeight - metalThickness - 0.5 blockHeight = tableHeight - metalThickness - 0.5
blockDepth = tableDepth - profileThickness blockDepth = tableDepth - profileThickness
@ -28,9 +27,9 @@ legHeight = blockHeight - profileThickness
legCount = blockCount + 1 legCount = blockCount + 1
legBody = startProfileAt([0, 0], floorPlane) legBody = startProfileAt([0, 0], floorPlane)
|> yLine(length = profileThickness) |> yLine(length=profileThickness)
|> xLine(length = profileThickness) |> xLine(length=profileThickness)
|> yLine(length = -profileThickness) |> yLine(length=-profileThickness)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)]) |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close() |> close()
|> patternLinear2d(axis = [1, 0], instances = legCount, distance = blockWidth) |> patternLinear2d(axis = [1, 0], instances = legCount, distance = blockWidth)
@ -43,9 +42,9 @@ lowerBeltLengthX = blockWidth - profileThickness
lowerBeltPlane = startSketchOn(offsetPlane(XY, offset = lowerBeltHeightAboveTheFloor)) lowerBeltPlane = startSketchOn(offsetPlane(XY, offset = lowerBeltHeightAboveTheFloor))
lowerBeltBodyX = startProfileAt([profileThickness, 0], lowerBeltPlane) lowerBeltBodyX = startProfileAt([profileThickness, 0], lowerBeltPlane)
|> yLine(length = profileThickness) |> yLine(length=profileThickness)
|> xLine(length = lowerBeltLengthX) |> xLine(length=lowerBeltLengthX)
|> yLine(length = -profileThickness) |> yLine(length=-profileThickness)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)]) |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close() |> close()
|> patternLinear2d(axis = [1, 0], instances = blockCount, distance = blockWidth) |> patternLinear2d(axis = [1, 0], instances = blockCount, distance = blockWidth)
@ -54,12 +53,12 @@ lowerBeltBodyX = startProfileAt([profileThickness, 0], lowerBeltPlane)
lowerBeltLengthY = blockDepth - profileThickness lowerBeltLengthY = blockDepth - profileThickness
lowerBeltBodyY = startProfileAt([0, profileThickness], lowerBeltPlane) lowerBeltBodyY = startProfileAt([0, profileThickness], lowerBeltPlane)
|> yLine(length = lowerBeltLengthY) |> yLine(length=lowerBeltLengthY)
|> xLine(length = profileThickness) |> xLine(length=profileThickness)
|> yLine(length = -lowerBeltLengthY) |> yLine(length=-lowerBeltLengthY)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)]) |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close() |> close()
|> patternLinear2d(axis = [1, 0], instances = 2, distance = tableWidth - profileThickness) |> patternLinear2d(axis = [1, 0], instances = 2, distance = tableWidth-profileThickness)
|> extrude(length = profileThickness) |> extrude(length = profileThickness)
// pillars // pillars
@ -68,9 +67,9 @@ pillarPlane = startSketchOn(offsetPlane(XY, offset = pillarHeightAboveTheFloor))
pillarTotalHeight = blockHeight - profileThickness - pillarHeightAboveTheFloor pillarTotalHeight = blockHeight - profileThickness - pillarHeightAboveTheFloor
pillarBody = startProfileAt([blockSubdivisionWidth, 0], pillarPlane) pillarBody = startProfileAt([blockSubdivisionWidth, 0], pillarPlane)
|> yLine(length = profileThickness) |> yLine(length=profileThickness)
|> xLine(length = profileThickness) |> xLine(length=profileThickness)
|> yLine(length = -profileThickness) |> yLine(length=-profileThickness)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)]) |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close() |> close()
|> patternLinear2d(axis = [1, 0], instances = blockCount, distance = blockWidth) |> patternLinear2d(axis = [1, 0], instances = blockCount, distance = blockWidth)
@ -81,9 +80,9 @@ pillarBody = startProfileAt([blockSubdivisionWidth, 0], pillarPlane)
upperBeltPlane = startSketchOn(offsetPlane(XY, offset = blockHeight)) upperBeltPlane = startSketchOn(offsetPlane(XY, offset = blockHeight))
upperBeltBodyX = startProfileAt([0, 0], upperBeltPlane) upperBeltBodyX = startProfileAt([0, 0], upperBeltPlane)
|> yLine(length = profileThickness) |> yLine(length=profileThickness)
|> xLine(length = tableWidth) |> xLine(length=tableWidth)
|> yLine(length = -profileThickness) |> yLine(length=-profileThickness)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)]) |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close() |> close()
|> patternLinear2d(axis = [0, 1], instances = 2, distance = blockDepth) |> patternLinear2d(axis = [0, 1], instances = 2, distance = blockDepth)
@ -91,20 +90,20 @@ upperBeltBodyX = startProfileAt([0, 0], upperBeltPlane)
upperBeltLengthY = blockDepth - profileThickness upperBeltLengthY = blockDepth - profileThickness
upperBeltBodyY = startProfileAt([0, profileThickness], upperBeltPlane) upperBeltBodyY = startProfileAt([0, profileThickness], upperBeltPlane)
|> yLine(length = upperBeltLengthY) |> yLine(length=upperBeltLengthY)
|> xLine(length = profileThickness) |> xLine(length=profileThickness)
|> yLine(length = -upperBeltLengthY) |> yLine(length=-upperBeltLengthY)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)]) |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close() |> close()
|> patternLinear2d(axis = [1, 0], instances = 2, distance = tableWidth - profileThickness) |> patternLinear2d(axis = [1, 0], instances = 2, distance = tableWidth-profileThickness)
|> extrude(length = -profileThickness) |> extrude(length = -profileThickness)
// sink // sink
tableTopPlane = startSketchOn(offsetPlane(XY, offset = tableHeight)) tableTopPlane = startSketchOn(offsetPlane(XY, offset = tableHeight))
tableTopBody = startProfileAt([0, 0], tableTopPlane) tableTopBody = startProfileAt([0, 0], tableTopPlane)
|> yLine(length = tableDepth) |> yLine(length=tableDepth)
|> xLine(length = tableWidth) |> xLine(length=tableWidth)
|> yLine(length = -tableDepth) |> yLine(length=-tableDepth)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)]) |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close() |> close()
|> extrude(length = -metalThickness) |> extrude(length = -metalThickness)
@ -115,26 +114,23 @@ sinkLength = 250
sinkDepth = 200 sinkDepth = 200
sinkOffsetFront = 40 sinkOffsetFront = 40
sinkOffsetLeft = 350 sinkOffsetLeft = 350
sinkSpacing = tableWidth - sinkWidth - (sinkOffsetLeft * 2) sinkSpacing = tableWidth - sinkWidth - sinkOffsetLeft*2
sinkPlaneOutside = startSketchOn(tableTopBody, 'START') sinkPlaneOutside = startSketchOn(tableTopBody, 'START')
sinkBodyOutside = startProfileAt([-sinkOffsetLeft, sinkOffsetFront], sinkPlaneOutside) sinkBodyOutside = startProfileAt([-sinkOffsetLeft, sinkOffsetFront], sinkPlaneOutside)
|> yLine(length = sinkLength) |> yLine(length=sinkLength)
|> xLine(length = -sinkWidth) |> xLine(length=-sinkWidth)
|> yLine(length = -sinkLength) |> yLine(length=-sinkLength)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)]) |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close() |> close()
|> patternLinear2d(axis = [-1, 0], instances = sinkCount, distance = sinkSpacing) |> patternLinear2d(axis = [-1, 0], instances = sinkCount, distance = sinkSpacing)
|> extrude(length = sinkDepth) |> extrude(length = sinkDepth)
sinkPlaneInside = startSketchOn(tableTopBody, 'END') sinkPlaneInside = startSketchOn(tableTopBody, 'END')
sinkBodyInside = startProfileAt([ sinkBodyInside = startProfileAt([sinkOffsetLeft+metalThickness, sinkOffsetFront+metalThickness], sinkPlaneInside)
sinkOffsetLeft + metalThickness, |> yLine(length=sinkLength-metalThickness*2)
sinkOffsetFront + metalThickness |> xLine(length=sinkWidth-metalThickness*2)
], sinkPlaneInside) |> yLine(length=-sinkLength+metalThickness*2)
|> yLine(length = sinkLength - (metalThickness * 2))
|> xLine(length = sinkWidth - (metalThickness * 2))
|> yLine(length = -sinkLength + metalThickness * 2)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)]) |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close() |> close()
|> patternLinear2d(axis = [1, 0], instances = sinkCount, distance = sinkSpacing) |> patternLinear2d(axis = [1, 0], instances = sinkCount, distance = sinkSpacing)
@ -142,30 +138,30 @@ sinkBodyInside = startProfileAt([
// door panels // door panels
doorGap = 2 doorGap = 2
doorWidth = blockSubdivisionWidth - profileThickness - (doorGap * 2) doorWidth = blockSubdivisionWidth - profileThickness - doorGap*2
doorStart = profileThickness + doorGap doorStart = profileThickness+doorGap
doorHeightAboveTheFloor = pillarHeightAboveTheFloor + doorGap doorHeightAboveTheFloor = pillarHeightAboveTheFloor + doorGap
doorHeight = blockHeight - doorHeightAboveTheFloor - profileThickness - doorGap doorHeight = blockHeight - doorHeightAboveTheFloor - profileThickness - doorGap
doorCount = blockCount * blockSubdivisionCount doorCount = blockCount * blockSubdivisionCount
doorPlane = startSketchOn(offsetPlane(XY, offset = doorHeightAboveTheFloor)) doorPlane = startSketchOn(offsetPlane(XY, offset = doorHeightAboveTheFloor))
doorBody = startProfileAt([doorStart, 0], doorPlane) doorBody = startProfileAt([doorStart, 0], doorPlane)
|> yLine(length = profileThickness) |> yLine(length=profileThickness)
|> xLine(length = doorWidth) |> xLine(length=doorWidth)
|> yLine(length = -profileThickness) |> yLine(length=-profileThickness)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)]) |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close() |> close()
|> patternLinear2d(axis = [1, 0], instances = doorCount, distance = blockSubdivisionWidth) |> patternLinear2d(axis = [1, 0], instances = doorCount, distance = blockSubdivisionWidth)
|> extrude(length = doorHeight) |> extrude(length = doorHeight)
// side panels // side panels
panelWidth = blockDepth - profileThickness - (doorGap * 2) panelWidth = blockDepth - profileThickness - doorGap*2
panelCount = doorCount + 1 panelCount = doorCount + 1
panelSpacing = tableWidth - profileThickness panelSpacing = tableWidth - profileThickness
panelBody = startProfileAt([0, doorStart], doorPlane) panelBody = startProfileAt([0, doorStart], doorPlane)
|> yLine(length = panelWidth) |> yLine(length=panelWidth)
|> xLine(length = profileThickness) |> xLine(length=profileThickness)
|> yLine(length = -panelWidth) |> yLine(length=-panelWidth)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)]) |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close() |> close()
|> patternLinear2d(axis = [1, 0], instances = 2, distance = panelSpacing) |> patternLinear2d(axis = [1, 0], instances = 2, distance = panelSpacing)
@ -183,25 +179,22 @@ handleLengthSegmentB = handleWidth - (handleFillet * 2)
handlePlane = startSketchOn(offsetPlane(XY, offset = handleHeightAboveTheFloor)) handlePlane = startSketchOn(offsetPlane(XY, offset = handleHeightAboveTheFloor))
handleProfilePath = startProfileAt([0 + handleOffset, 0], handlePlane) handleProfilePath = startProfileAt([0 + handleOffset, 0], handlePlane)
|> yLine(length = -handleLengthSegmentA) |> yLine(length=-handleLengthSegmentA)
|> tangentialArcTo([ |> tangentialArcTo([
handleFillet + handleOffset, handleFillet + handleOffset,
-handleDepth -handleDepth
], %) ], %)
|> xLine(length = handleLengthSegmentB) |> xLine(length=handleLengthSegmentB)
|> tangentialArcTo([ |> tangentialArcTo([
handleOffset + handleWidth, handleOffset + handleWidth,
-handleLengthSegmentA -handleLengthSegmentA
], %) ], %)
|> yLine(length = handleLengthSegmentA) |> yLine(length=handleLengthSegmentA)
handleSectionPlane = startSketchOn(XZ) handleSectionPlane = startSketchOn(XZ)
handleProfileSection = circle( handleProfileSection = circle(
handleSectionPlane, handleSectionPlane,
center = [ center = [handleOffset, handleHeightAboveTheFloor],
handleOffset, radius = 2)
handleHeightAboveTheFloor
],
radius = 2,
)
handleBody = sweep(handleProfileSection, path = handleProfilePath) handleBody = sweep(handleProfileSection, path = handleProfilePath)
|> patternLinear3d(axis = [1, 0, 0], instances = doorCount, distance = blockSubdivisionWidth) |> patternLinear3d(axis = [1, 0, 0], instances = doorCount, distance = blockSubdivisionWidth)

View File

@ -23,7 +23,7 @@ sketch001 = startSketchOn(XZ)
], %, $rectangleSegmentC001) ], %, $rectangleSegmentC001)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)]) |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close() |> close()
|> revolve(angle = 360, axis = 'Y') |> revolve(angle = 360, axis = Y)
// Create an angled plane to sketch the supports // Create an angled plane to sketch the supports
plane001 = { plane001 = {
@ -132,7 +132,7 @@ sketch005 = startSketchOn(XZ)
|> xLine(endAbsolute = 0.15) |> xLine(endAbsolute = 0.15)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)]) |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close() |> close()
|> revolve(axis = 'y') |> revolve(axis = Y)
// Plunger and stem // Plunger and stem
sketch006 = startSketchOn(XZ) sketch006 = startSketchOn(XZ)
@ -145,7 +145,7 @@ sketch006 = startSketchOn(XZ)
|> tangentialArc({ radius = 0.6, offset = -90 }, %) |> tangentialArc({ radius = 0.6, offset = -90 }, %)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)]) |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close() |> close()
|> revolve(axis = 'y') |> revolve(axis = Y)
// Spiral plate // Spiral plate
sketch007 = startSketchOn(offsetPlane(XY, offset = 1.12)) sketch007 = startSketchOn(offsetPlane(XY, offset = 1.12))
@ -201,7 +201,7 @@ sketch011 = startSketchOn(XZ)
}, %) }, %)
|> line(endAbsolute = [profileStartX(%), profileStartY(%)]) |> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|> close() |> close()
|> revolve(axis = 'y') |> revolve(axis = Y)
// Draw and extrude handle // Draw and extrude handle
sketch012 = startSketchOn(offsetPlane(XZ, offset = handleThickness / 2)) sketch012 = startSketchOn(offsetPlane(XZ, offset = handleThickness / 2))

View File

@ -48,10 +48,8 @@ sides = patternCircular3d(
// define an axis axis000 // define an axis axis000
axis000 = { axis000 = {
custom = { direction = [0.0, 1.0],
axis = [0.0, 1.0], origin = [cornerRadius, cornerRadius]
origin = [cornerRadius, cornerRadius]
}
} }
// create a single corner of the bin // create a single corner of the bin

View File

@ -45,10 +45,8 @@ sides = patternCircular3d(
// define an axis axis000 // define an axis axis000
axis000 = { axis000 = {
custom = { direction = [0.0, 1.0],
axis = [0.0, 1.0], origin = [cornerRadius, cornerRadius]
origin = [cornerRadius, cornerRadius]
}
} }
// create a single corner of the bin // create a single corner of the bin

View File

@ -65,13 +65,11 @@ sides = patternCircular3d(
// define an axis axis000 // define an axis axis000
axis000 = { axis000 = {
custom = { direction = [0.0, 1.0],
axis = [0.0, 1.0], origin = [
origin = [ cornerRadius + binTol,
cornerRadius + binTol, cornerRadius + binTol
cornerRadius + binTol ]
]
}
} }
// create a single corner of the bin // create a single corner of the bin
@ -272,10 +270,8 @@ lipWidths = patternCircular3d(
// define an axis axis000 // define an axis axis000
axis001 = { axis001 = {
custom = { direction = [0.0, 1.0],
axis = [0.0, 1.0], origin = [cornerRadius, cornerRadius]
origin = [cornerRadius, cornerRadius]
}
} }
// create a single corner of the bin // create a single corner of the bin

View File

@ -58,13 +58,11 @@ sides = patternCircular3d(
// define an axis axis000 // define an axis axis000
axis000 = { axis000 = {
custom = { direction = [0.0, 1.0],
axis = [0.0, 1.0], origin = [
origin = [ cornerRadius + binTol,
cornerRadius + binTol, cornerRadius + binTol
cornerRadius + binTol ]
]
}
} }
// create a single corner of the bin // create a single corner of the bin

View File

@ -5,7 +5,7 @@
@settings(defaultLengthUnit = in) @settings(defaultLengthUnit = in)
// Define Beam Dimensions // Define Beam Dimensions
beamLength = 6 * ft() beamLength = 6*ft()
beamHeight = 4 beamHeight = 4
flangeWidth = 2.663 flangeWidth = 2.663
flangeThickness = 0.293 flangeThickness = 0.293
@ -20,6 +20,6 @@ sketch001 = startSketchOn(-XZ)
|> xLine(endAbsolute = webThickness / 2 + rootRadius) |> xLine(endAbsolute = webThickness / 2 + rootRadius)
|> tangentialArc({ radius = rootRadius, offset = 90 }, %) |> tangentialArc({ radius = rootRadius, offset = 90 }, %)
|> yLine(endAbsolute = 0) |> yLine(endAbsolute = 0)
|> mirror2d({ axis = 'X' }, %) |> mirror2d(axis = X)
|> mirror2d({ axis = 'Y' }, %) |> mirror2d(axis = Y)
|> extrude(length = beamLength) |> extrude(length = beamLength)

View File

@ -52,22 +52,19 @@ armPartB = armFn(XZ, armLength, hingeHeight * 2.5 + hingeGap * 2)
// mirror // mirror
fn mirrorFn(plane, offsetX, offsetY, altitude, radius, tiefe, gestellR, gestellD) { fn mirrorFn(plane, offsetX, offsetY, altitude, radius, tiefe, gestellR, gestellD) {
armPlane = startSketchOn( offsetPlane(plane, offset = offsetY - (tiefe / 2))) armPlane = startSketchOn(offsetPlane(plane, offset = offsetY - (tiefe / 2)))
armBody = circle(armPlane, center = [offsetX, altitude], radius = radius) armBody = circle(armPlane, center = [offsetX, altitude], radius = radius)
|> extrude(length = tiefe) |> extrude(length = tiefe)
archBody = startProfileAt([offsetX - gestellR, altitude], armPlane) archBody = startProfileAt([offsetX-gestellR, altitude], armPlane)
|> xLine(length = gestellD) |> xLine(length = gestellD)
|> arcTo({ |> arcTo({
interior = [offsetX, altitude - gestellR], interior = [offsetX, altitude-gestellR],
end = [offsetX + gestellR, altitude] end = [offsetX+gestellR, altitude]
}, %) }, %)
|> xLine(length = gestellD) |> xLine(length = gestellD)
|> arcTo({ |> arcTo({
interior = [ interior = [offsetX, altitude-gestellR-gestellD],
offsetX,
altitude - gestellR - gestellD
],
end = [profileStartX(%), profileStartY(%)] end = [profileStartX(%), profileStartY(%)]
}, %) }, %)
|> close() |> close()
@ -75,4 +72,4 @@ fn mirrorFn(plane, offsetX, offsetY, altitude, radius, tiefe, gestellR, gestellD
return armBody return armBody
} }
mirror = mirrorFn(XZ, armLength, armLength, hingeHeight * 4 + hingeGap * 3 + mirrorRadius + archToMirrorGap + archThickness, mirrorRadius, mirrorThickness, archRadius, archThickness) mirror = mirrorFn(XZ, armLength, armLength, hingeHeight * 4 + hingeGap * 3 + mirrorRadius+archToMirrorGap+archThickness, mirrorRadius, mirrorThickness, archRadius, archThickness)

View File

@ -4,6 +4,7 @@
// set units // set units
@settings(defaultLengthUnit = in) @settings(defaultLengthUnit = in)
// import constants // import constants
import boltDiameter, boltLength, boltHeadLength, boltHeadDiameter, boltHexDrive, boltHexFlatLength, boltThreadLength from "globals.kcl" import boltDiameter, boltLength, boltHeadLength, boltHeadDiameter, boltHexDrive, boltHexFlatLength, boltThreadLength from "globals.kcl"

View File

@ -19,15 +19,27 @@ import pipe from "1120t74-pipe.kcl"
flange() flange()
flange() flange()
|> rotate(axis = [0, 1, 0], angle = 180) |> rotate(axis = [0, 1, 0], angle = 180)
|> translate(x = 0, y = 0, z = flangeBackHeight * 2 + gasketThickness) |> translate(translate = [
0,
0,
flangeBackHeight * 2 + gasketThickness
])
// place gasket between the flanges // place gasket between the flanges
gasket() gasket()
|> translate(x = 0, y = 0, z = -flangeBackHeight - gasketThickness) |> translate(translate = [
0,
0,
-flangeBackHeight - gasketThickness
])
// place eight washers (four front, four back) // place eight washers (four front, four back)
washer() washer()
|> translate(x = mountingHolePlacementDiameter / 2, y = 0, z = flangeBaseThickness) |> translate(translate = [
mountingHolePlacementDiameter / 2,
0,
flangeBaseThickness
])
|> patternCircular3d( |> patternCircular3d(
%, %,
instances = 4, instances = 4,
@ -45,7 +57,11 @@ washer()
// place four bolts // place four bolts
bolt() bolt()
|> translate(x = mountingHolePlacementDiameter / 2, y = 0, z = flangeBaseThickness + washerThickness) |> translate(translate = [
mountingHolePlacementDiameter / 2,
0,
flangeBaseThickness + washerThickness
])
|> rotate(roll = 90, pitch = 0, yaw = 0) |> rotate(roll = 90, pitch = 0, yaw = 0)
|> patternCircular3d( |> patternCircular3d(
%, %,
@ -58,7 +74,11 @@ bolt()
// place four hex nuts // place four hex nuts
hexNut() hexNut()
|> translate(x = mountingHolePlacementDiameter / 2, y = 0, z = -(flangeBackHeight * 2 + gasketThickness + flangeBaseThickness + washerThickness + hexNutThickness)) |> translate(translate = [
mountingHolePlacementDiameter / 2,
0,
-(flangeBackHeight * 2 + gasketThickness + flangeBaseThickness + washerThickness + hexNutThickness)
])
|> patternCircular3d( |> patternCircular3d(
%, %,
instances = 4, instances = 4,
@ -78,9 +98,11 @@ pipe()
) )
|> translate( |> translate(
%, %,
x = 0, translate = [
y = 0, 0,
z = flangeBaseThickness + flangeFrontHeight - 0.5, 0,
flangeBaseThickness + flangeFrontHeight - 0.5
],
global = true, global = true,
) )
@ -93,8 +115,10 @@ pipe()
) )
|> translate( |> translate(
%, %,
x = 0, translate = [
y = 0, 0,
z = -(flangeBackHeight * 2 + gasketThickness + flangeBaseThickness + flangeFrontHeight - 0.5), 0,
-(flangeBackHeight * 2 + gasketThickness + flangeBaseThickness + flangeFrontHeight - 0.5)
],
global = true, global = true,
) )

View File

@ -24,4 +24,4 @@ pipeProfile = outerProfile
|> hole(innerProfile, %) |> hole(innerProfile, %)
// revolve the pipe profile at the desired angle // revolve the pipe profile at the desired angle
pipe = revolve(pipeProfile, axis = 'Y', angle = bendAngle) pipe = revolve(pipeProfile, axis = Y, angle = bendAngle)

View File

@ -33,4 +33,4 @@ pipeSketch = startSketchOn(XY)
|> close() |> close()
// Revolve the sketch to create the pipe // Revolve the sketch to create the pipe
pipe = revolve(pipeSketch, axis = 'y') pipe = revolve(pipeSketch, axis = Y)

View File

@ -34,10 +34,8 @@ part001 = revolve(
sketch001, sketch001,
angle = 90, angle = 90,
axis = { axis = {
custom = { direction = [1.0, 0.0],
axis = [1.0, 0.0], origin = [0.0, height + .0001]
origin = [0.0, height + .0001]
}
}, },
) )

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