Compare commits

..

39 Commits

Author SHA1 Message Date
239ab6850e Cut release v0.26.2 (#4322)
* Cut release v0.26.2

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest)

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-10-26 03:06:01 -04:00
4a7dd6e650 update env vars to match other repos, make dry (#4321)
* update env vars to match other repos, make dry

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* bump

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2024-10-26 03:06:32 +00:00
af2609e678 Fix NetworkMachineIndicator and machines dynamically showing in CommandBar (#4311) 2024-10-25 16:28:10 -07:00
30909dedda Bump kittycad from 0.3.23 to 0.3.25 in /src/wasm-lib (#4316)
Bumps [kittycad](https://github.com/KittyCAD/kittycad.rs) from 0.3.23 to 0.3.25.
- [Release notes](https://github.com/KittyCAD/kittycad.rs/releases)
- [Commits](https://github.com/KittyCAD/kittycad.rs/compare/v0.3.23...v0.3.25)

---
updated-dependencies:
- dependency-name: kittycad
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-25 22:58:59 +00:00
39d76ed54f Bugfix: arc paths were stored as straight line paths (#4310)
Problem 1 of https://github.com/KittyCAD/modeling-app/issues/4297
2024-10-25 22:49:30 +00:00
4925251c29 Make application aware it saved the buffer and not something else (#4314)
Make application aware it saved the buffer and something else
2024-10-25 18:07:50 -04:00
9772869545 Add a radius length indicator to the circle sketch tool (#4304)
* Add a radius length indicator to the circle sketch tool

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest)

* Revert "A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest)"

This reverts commit 15b078f641.

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: 49fl <ircsurfer33@gmail.com>
2024-10-25 17:42:27 -04:00
a7e830cd02 Update machine-api spec (#4305)
YOYO NEW API SPEC!

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-10-25 20:53:08 +00:00
ca102116b6 Bump kittycad-modeling-cmds from 0.2.70 to 0.2.71 in /src/wasm-lib (#4302)
Bumps [kittycad-modeling-cmds](https://github.com/KittyCAD/modeling-api) from 0.2.70 to 0.2.71.
- [Commits](https://github.com/KittyCAD/modeling-api/compare/kittycad-modeling-cmds-0.2.70...kittycad-modeling-cmds-0.2.71)

---
updated-dependencies:
- dependency-name: kittycad-modeling-cmds
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Adam Chalmers <adam.chalmers@zoo.dev>
2024-10-25 20:52:22 +00:00
c2fba89e77 Bump regex from 1.11.0 to 1.11.1 in /src/wasm-lib (#4301)
Bumps [regex](https://github.com/rust-lang/regex) from 1.11.0 to 1.11.1.
- [Release notes](https://github.com/rust-lang/regex/releases)
- [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/regex/compare/1.11.0...1.11.1)

---
updated-dependencies:
- dependency-name: regex
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-25 13:50:21 -07:00
7e31678ba2 Chore: Don't let draft lines receive mouseEnter/Leave events, or create invalid overlays (#4306) 2024-10-25 15:34:53 -04:00
1140ced121 Tags should refer to full paths, not just base paths. (#4299)
See "Problem 2" in https://github.com/KittyCAD/modeling-app/issues/4297

This is a pure refactor, it should not change any behaviour at all.
It adds more information into the tag system, but nothing reads that
extra information yet. It will be used to address problem 3 of the above
issue.
2024-10-25 10:27:40 -04:00
32b7ddaa7c Update circular pattern snapshots (#4303)
Engine changed (Serena fixed a bug with circular patterns), so snapshots need to be updated.
2024-10-25 08:28:46 -04:00
2525f99515 Move more KCL tests into files (#4260) 2024-10-25 01:52:43 +00:00
4b8ce34b31 Fix release notes (#4295) 2024-10-24 17:07:12 -04:00
6617f72373 Fix docs for how to patch kcmc (#4294) 2024-10-24 20:14:38 +00:00
e9033e1754 Cut release v0.26.1 (#4289) 2024-10-24 14:08:29 -04:00
9b697e30cf Revert "Separate debug/release electron-builder to help mac job (#4270)" (#4293)
This reverts commit 19d01c563e.
2024-10-24 13:07:43 -04:00
a70facdab4 Disable rotate on start new sketch (#4287)
disable rotate on start new sketch

Co-authored-by: Frank Noirot <frank@zoo.dev>
2024-10-24 10:18:41 -04:00
4083f9f3dd Fix release notes in last_download.json (#4247)
* Fix release notes in last_download.json
Fixes #4246

* Fix job output

* Clean up, ready for merge
2024-10-24 09:47:44 -04:00
7ead2bb875 Stop propagation of camera clicks after drags (#4257)
* Update CameraControls.ts

* fix static analyzer error

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest)

* Revert "A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest)"

This reverts commit 0b63016217.

* Don't perform sketch click operations if a camera movement interaction also matches

* Don't `stopPropogation`, make selection listener early return if `wasDragging`
+ consolidate `wasDragging` set statements, add comments

* Codespell

---------

Co-authored-by: 49fl <ircsurfer33@gmail.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Frank Noirot <frank@kittycad.io>
Co-authored-by: Frank Noirot <frank@zoo.dev>
2024-10-24 09:26:33 -04:00
19d01c563e Separate debug/release electron-builder to help mac job (#4270)
* Separate debug/release electron-builder to help mac job
Will attempt to fix #4199

* Test BUILD_RELEASE: true

* Revert "Test BUILD_RELEASE: true"

This reverts commit f2c0c24432.
2024-10-24 08:10:16 -04:00
dfe7cfc91c Bump syn from 2.0.82 to 2.0.85 in /src/wasm-lib (#4283)
Bumps [syn](https://github.com/dtolnay/syn) from 2.0.82 to 2.0.85.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/2.0.82...2.0.85)

---
updated-dependencies:
- dependency-name: syn
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-24 05:52:18 +00:00
01443e445d Bump kittycad-modeling-cmds from 0.2.68 to 0.2.70 in /src/wasm-lib (#4284)
Bumps [kittycad-modeling-cmds](https://github.com/KittyCAD/modeling-api) from 0.2.68 to 0.2.70.
- [Commits](https://github.com/KittyCAD/modeling-api/compare/kittycad-modeling-cmds-0.2.68...kittycad-modeling-cmds-0.2.70)

---
updated-dependencies:
- dependency-name: kittycad-modeling-cmds
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-24 03:53:07 +00:00
e16eb49f51 Bump serde from 1.0.210 to 1.0.213 in /src/wasm-lib (#4285)
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.210 to 1.0.213.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.210...v1.0.213)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-24 03:50:38 +00:00
5d5138e8e6 Bump syn from 2.0.79 to 2.0.82 in /src/wasm-lib (#4252)
Bumps [syn](https://github.com/dtolnay/syn) from 2.0.79 to 2.0.82.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/2.0.79...2.0.82)

---
updated-dependencies:
- dependency-name: syn
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jess Frazelle <jessfraz@users.noreply.github.com>
2024-10-23 23:48:18 +00:00
e1d6e29523 Update machine-api spec (#4241)
* YOYO NEW API SPEC!

* New machine-api types

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Jess Frazelle <jessfraz@users.noreply.github.com>
2024-10-23 23:41:48 +00:00
49657ad2e5 Bump @types/node from 22.5.0 to 22.7.8 (#4258)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 22.5.0 to 22.7.8.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-23 15:12:40 -07:00
b40d353994 Bump thiserror from 1.0.64 to 1.0.65 in /src/wasm-lib (#4268)
Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.64 to 1.0.65.
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/1.0.64...1.0.65)

---
updated-dependencies:
- dependency-name: thiserror
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-23 21:47:08 +00:00
62ffa53add Bump proc-macro2 from 1.0.88 to 1.0.89 in /src/wasm-lib (#4266)
Bumps [proc-macro2](https://github.com/dtolnay/proc-macro2) from 1.0.88 to 1.0.89.
- [Release notes](https://github.com/dtolnay/proc-macro2/releases)
- [Commits](https://github.com/dtolnay/proc-macro2/compare/1.0.88...1.0.89)

---
updated-dependencies:
- dependency-name: proc-macro2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-23 21:46:23 +00:00
64dce4d8b1 Bump anyhow from 1.0.89 to 1.0.91 in /src/wasm-lib (#4269)
Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.89 to 1.0.91.
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.89...1.0.91)

---
updated-dependencies:
- dependency-name: anyhow
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-23 21:41:00 +00:00
02588b2672 Rename Sketch.value to Sketch.paths (#4272)
'value' is not a useful name
2024-10-23 17:42:54 +00:00
3d1ac2ac0b Fix engine connection break when starting onboarding from a fresh install (#4263)
* Make electron test setting overrides not entirely replace default settings

* Add failing test

* Fix test by checking for healthy engine connection before executing demo code

* Fix one electron test that assumed all settings got wiped if you override any.

* 🤷🏻‍♂️ an engine-side camera position in one of the E2E tests changed by 0.01 randomly
2024-10-22 20:22:52 -04:00
ff5ce29fd7 Delete ..env.development.local.swp (#4259) 2024-10-22 18:33:28 -04:00
4bd7e02271 Support negative start and end in ranges (#4249)
Signed-off-by: Nick Cameron <nrc@ncameron.org>
2024-10-22 14:28:48 +13:00
26042790b6 Remove setInterval implementations from camera controls (#4255)
* remove setInterval implementations from camera controls

* fmt
2024-10-21 16:46:47 -07:00
af74f3bb05 Upgrade to rust toolchain 1.82.0 (#4245)
* Upgrade to rust toolchain 1.82.0

* Fix lint about variant being too large

* Fix lint about Err variant being too large
2024-10-21 16:35:04 -05:00
0bdedf5854 fix job name for printers (#4234)
Signed-off-by: Jess Frazelle <github@jessfraz.com>
Co-authored-by: Paul Tagliamonte <paul@zoo.dev>
2024-10-21 21:27:32 +00:00
d2c6b5cf3a Buffer file writes, because writing to file after every keypress has bad consequences (#4242)
* Buffer file writes, because writing to file after every keypress does bad things

* fix: kevin -- added timeouts for the time being since the workflow for saving data to disk is now changed

---------

Co-authored-by: Kevin Nadro <kevin@zoo.dev>
2024-10-21 15:07:20 -05:00
235 changed files with 43255 additions and 30663 deletions

View File

@ -15,6 +15,7 @@ on:
env: env:
CUT_RELEASE_PR: ${{ github.event_name == 'pull_request' && (contains(github.event.pull_request.title, 'Cut release v')) }} CUT_RELEASE_PR: ${{ github.event_name == 'pull_request' && (contains(github.event.pull_request.title, 'Cut release v')) }}
BUILD_RELEASE: ${{ github.event_name == 'release' || github.event_name == 'schedule' || github.event_name == 'pull_request' && (contains(github.event.pull_request.title, 'Cut release v')) }} BUILD_RELEASE: ${{ github.event_name == 'release' || github.event_name == 'schedule' || github.event_name == 'pull_request' && (contains(github.event.pull_request.title, 'Cut release v')) }}
NOTES: ${{ github.event_name == 'release' && github.event.release.body || format('Non-release build, commit {0}', github.sha) }}
concurrency: concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
@ -25,7 +26,6 @@ jobs:
runs-on: ubuntu-22.04 # seperate job on Ubuntu for easy string manipulations (compared to Windows) runs-on: ubuntu-22.04 # seperate job on Ubuntu for easy string manipulations (compared to Windows)
outputs: outputs:
version: ${{ steps.export_version.outputs.version }} version: ${{ steps.export_version.outputs.version }}
notes: ${{ steps.export_version.outputs.notes }}
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
@ -55,8 +55,6 @@ jobs:
# TODO: see if we need to inject updater nightly URL here https://dl.zoo.dev/releases/modeling-app/nightly/last_update.json # TODO: see if we need to inject updater nightly URL here https://dl.zoo.dev/releases/modeling-app/nightly/last_update.json
- name: Generate release notes - name: Generate release notes
env:
NOTES: ${{ github.event_name == 'release' && github.event.release.body || format('Non-release build, commit {0}', github.sha) }}
run: | run: |
echo "$NOTES" > release-notes.md echo "$NOTES" > release-notes.md
cat release-notes.md cat release-notes.md
@ -84,9 +82,6 @@ jobs:
path: | path: |
electron-builder.yml electron-builder.yml
- id: export_notes
run: echo "notes=`cat release-notes.md'`" >> "$GITHUB_OUTPUT"
- name: Prepare electron-builder.yml file for updater test - name: Prepare electron-builder.yml file for updater test
if: ${{ env.CUT_RELEASE_PR == 'true' }} if: ${{ env.CUT_RELEASE_PR == 'true' }}
run: | run: |
@ -262,7 +257,6 @@ jobs:
VERSION_NO_V: ${{ needs.prepare-files.outputs.version }} VERSION_NO_V: ${{ needs.prepare-files.outputs.version }}
VERSION: ${{ github.event_name == 'schedule' && needs.prepare-files.outputs.version || format('v{0}', needs.prepare-files.outputs.version) }} VERSION: ${{ github.event_name == 'schedule' && needs.prepare-files.outputs.version || format('v{0}', needs.prepare-files.outputs.version) }}
PUB_DATE: ${{ github.event_name == 'release' && github.event.release.created_at || github.event.repository.updated_at }} PUB_DATE: ${{ github.event_name == 'release' && github.event.release.created_at || github.event.repository.updated_at }}
NOTES: ${{ needs.prepare-files.outputs.notes }}
BUCKET_DIR: ${{ github.event_name == 'schedule' && 'dl.kittycad.io/releases/modeling-app/nightly' || 'dl.kittycad.io/releases/modeling-app' }} BUCKET_DIR: ${{ github.event_name == 'schedule' && 'dl.kittycad.io/releases/modeling-app/nightly' || 'dl.kittycad.io/releases/modeling-app' }}
WEBSITE_DIR: ${{ github.event_name == 'schedule' && 'dl.zoo.dev/releases/modeling-app/nightly' || 'dl.zoo.dev/releases/modeling-app' }} WEBSITE_DIR: ${{ github.event_name == 'schedule' && 'dl.zoo.dev/releases/modeling-app/nightly' || 'dl.zoo.dev/releases/modeling-app' }}
URL_CODED_NAME: ${{ github.event_name == 'schedule' && 'Zoo%20Modeling%20App%20%28Nightly%29' || 'Zoo%20Modeling%20App' }} URL_CODED_NAME: ${{ github.event_name == 'schedule' && 'Zoo%20Modeling%20App%20%28Nightly%29' || 'Zoo%20Modeling%20App' }}

View File

@ -62,7 +62,7 @@ jobs:
shell: bash shell: bash
run: |- run: |-
cd "${{ matrix.dir }}" cd "${{ matrix.dir }}"
cargo llvm-cov nextest --all --lcov --output-path lcov.info --test-threads=1 --no-fail-fast -P ci 2>&1 | tee /tmp/github-actions.log cargo llvm-cov nextest --workspace --lcov --output-path lcov.info --test-threads=1 --no-fail-fast -P ci 2>&1 | tee /tmp/github-actions.log
env: env:
KITTYCAD_API_TOKEN: ${{secrets.KITTYCAD_API_TOKEN}} KITTYCAD_API_TOKEN: ${{secrets.KITTYCAD_API_TOKEN}}
RUST_MIN_STACK: 10485760000 RUST_MIN_STACK: 10485760000

View File

@ -9,7 +9,7 @@ Draw a line segment relative to the current origin using the polar
measure of some angle and distance. measure of some angle and distance.
```js ```js
angledLine(data: AngledLineData, sketch: Sketch, tag?: TagNode) -> Sketch angledLine(data: AngledLineData, sketch: Sketch, tag?: TagDeclarator) -> Sketch
``` ```
@ -19,7 +19,7 @@ angledLine(data: AngledLineData, sketch: Sketch, tag?: TagNode) -> Sketch
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `data` | [`AngledLineData`](/docs/kcl/types/AngledLineData) | Data to draw an angled line. | Yes | | `data` | [`AngledLineData`](/docs/kcl/types/AngledLineData) | Data to draw an angled line. | Yes |
| `sketch` | [`Sketch`](/docs/kcl/types/Sketch) | A sketch is a collection of paths. | Yes | | `sketch` | [`Sketch`](/docs/kcl/types/Sketch) | A sketch is a collection of paths. | Yes |
| `tag` | [`TagNode`](/docs/kcl/types/TagNode) | | No | | `tag` | [`TagDeclarator`](/docs/kcl/types#tag-declaration) | | No |
### Returns ### Returns

View File

@ -9,7 +9,7 @@ Create a line segment from the current 2-dimensional sketch origin
along some angle (in degrees) for some relative length in the 'x' dimension. along some angle (in degrees) for some relative length in the 'x' dimension.
```js ```js
angledLineOfXLength(data: AngledLineData, sketch: Sketch, tag?: TagNode) -> Sketch angledLineOfXLength(data: AngledLineData, sketch: Sketch, tag?: TagDeclarator) -> Sketch
``` ```
@ -19,7 +19,7 @@ angledLineOfXLength(data: AngledLineData, sketch: Sketch, tag?: TagNode) -> Sket
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `data` | [`AngledLineData`](/docs/kcl/types/AngledLineData) | Data to draw an angled line. | Yes | | `data` | [`AngledLineData`](/docs/kcl/types/AngledLineData) | Data to draw an angled line. | Yes |
| `sketch` | [`Sketch`](/docs/kcl/types/Sketch) | A sketch is a collection of paths. | Yes | | `sketch` | [`Sketch`](/docs/kcl/types/Sketch) | A sketch is a collection of paths. | Yes |
| `tag` | [`TagNode`](/docs/kcl/types/TagNode) | | No | | `tag` | [`TagDeclarator`](/docs/kcl/types#tag-declaration) | | No |
### Returns ### Returns

View File

@ -9,7 +9,7 @@ Create a line segment from the current 2-dimensional sketch origin
along some angle (in degrees) for some relative length in the 'y' dimension. along some angle (in degrees) for some relative length in the 'y' dimension.
```js ```js
angledLineOfYLength(data: AngledLineData, sketch: Sketch, tag?: TagNode) -> Sketch angledLineOfYLength(data: AngledLineData, sketch: Sketch, tag?: TagDeclarator) -> Sketch
``` ```
@ -19,7 +19,7 @@ angledLineOfYLength(data: AngledLineData, sketch: Sketch, tag?: TagNode) -> Sket
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `data` | [`AngledLineData`](/docs/kcl/types/AngledLineData) | Data to draw an angled line. | Yes | | `data` | [`AngledLineData`](/docs/kcl/types/AngledLineData) | Data to draw an angled line. | Yes |
| `sketch` | [`Sketch`](/docs/kcl/types/Sketch) | A sketch is a collection of paths. | Yes | | `sketch` | [`Sketch`](/docs/kcl/types/Sketch) | A sketch is a collection of paths. | Yes |
| `tag` | [`TagNode`](/docs/kcl/types/TagNode) | | No | | `tag` | [`TagDeclarator`](/docs/kcl/types#tag-declaration) | | No |
### Returns ### Returns

View File

@ -9,7 +9,7 @@ Draw an angled line from the current origin, constructing a line segment
such that the newly created line intersects the desired target line segment. such that the newly created line intersects the desired target line segment.
```js ```js
angledLineThatIntersects(data: AngledLineThatIntersectsData, sketch: Sketch, tag?: TagNode) -> Sketch angledLineThatIntersects(data: AngledLineThatIntersectsData, sketch: Sketch, tag?: TagDeclarator) -> Sketch
``` ```
@ -19,7 +19,7 @@ angledLineThatIntersects(data: AngledLineThatIntersectsData, sketch: Sketch, tag
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `data` | [`AngledLineThatIntersectsData`](/docs/kcl/types/AngledLineThatIntersectsData) | Data for drawing an angled line that intersects with a given line. | Yes | | `data` | [`AngledLineThatIntersectsData`](/docs/kcl/types/AngledLineThatIntersectsData) | Data for drawing an angled line that intersects with a given line. | Yes |
| `sketch` | [`Sketch`](/docs/kcl/types/Sketch) | A sketch is a collection of paths. | Yes | | `sketch` | [`Sketch`](/docs/kcl/types/Sketch) | A sketch is a collection of paths. | Yes |
| `tag` | [`TagNode`](/docs/kcl/types/TagNode) | | No | | `tag` | [`TagDeclarator`](/docs/kcl/types#tag-declaration) | | No |
### Returns ### Returns

View File

@ -9,7 +9,7 @@ Create a line segment from the current 2-dimensional sketch origin
along some angle (in degrees) for some length, ending at the provided value in the 'x' dimension. along some angle (in degrees) for some length, ending at the provided value in the 'x' dimension.
```js ```js
angledLineToX(data: AngledLineToData, sketch: Sketch, tag?: TagNode) -> Sketch angledLineToX(data: AngledLineToData, sketch: Sketch, tag?: TagDeclarator) -> Sketch
``` ```
@ -19,7 +19,7 @@ angledLineToX(data: AngledLineToData, sketch: Sketch, tag?: TagNode) -> Sketch
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `data` | [`AngledLineToData`](/docs/kcl/types/AngledLineToData) | Data to draw an angled line to a point. | Yes | | `data` | [`AngledLineToData`](/docs/kcl/types/AngledLineToData) | Data to draw an angled line to a point. | Yes |
| `sketch` | [`Sketch`](/docs/kcl/types/Sketch) | A sketch is a collection of paths. | Yes | | `sketch` | [`Sketch`](/docs/kcl/types/Sketch) | A sketch is a collection of paths. | Yes |
| `tag` | [`TagNode`](/docs/kcl/types/TagNode) | | No | | `tag` | [`TagDeclarator`](/docs/kcl/types#tag-declaration) | | No |
### Returns ### Returns

View File

@ -9,7 +9,7 @@ Create a line segment from the current 2-dimensional sketch origin
along some angle (in degrees) for some length, ending at the provided value in the 'y' dimension. along some angle (in degrees) for some length, ending at the provided value in the 'y' dimension.
```js ```js
angledLineToY(data: AngledLineToData, sketch: Sketch, tag?: TagNode) -> Sketch angledLineToY(data: AngledLineToData, sketch: Sketch, tag?: TagDeclarator) -> Sketch
``` ```
@ -19,7 +19,7 @@ angledLineToY(data: AngledLineToData, sketch: Sketch, tag?: TagNode) -> Sketch
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `data` | [`AngledLineToData`](/docs/kcl/types/AngledLineToData) | Data to draw an angled line to a point. | Yes | | `data` | [`AngledLineToData`](/docs/kcl/types/AngledLineToData) | Data to draw an angled line to a point. | Yes |
| `sketch` | [`Sketch`](/docs/kcl/types/Sketch) | A sketch is a collection of paths. | Yes | | `sketch` | [`Sketch`](/docs/kcl/types/Sketch) | A sketch is a collection of paths. | Yes |
| `tag` | [`TagNode`](/docs/kcl/types/TagNode) | | No | | `tag` | [`TagDeclarator`](/docs/kcl/types#tag-declaration) | | No |
### Returns ### Returns

View File

@ -11,7 +11,7 @@ The arc is constructed such that the current position of the sketch is placed al
Unless this makes a lot of sense and feels like what you're looking for to construct your shape, you're likely looking for tangentialArc. Unless this makes a lot of sense and feels like what you're looking for to construct your shape, you're likely looking for tangentialArc.
```js ```js
arc(data: ArcData, sketch: Sketch, tag?: TagNode) -> Sketch arc(data: ArcData, sketch: Sketch, tag?: TagDeclarator) -> Sketch
``` ```
@ -21,7 +21,7 @@ arc(data: ArcData, sketch: Sketch, tag?: TagNode) -> Sketch
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `data` | [`ArcData`](/docs/kcl/types/ArcData) | Data to draw an arc. | Yes | | `data` | [`ArcData`](/docs/kcl/types/ArcData) | Data to draw an arc. | Yes |
| `sketch` | [`Sketch`](/docs/kcl/types/Sketch) | A sketch is a collection of paths. | Yes | | `sketch` | [`Sketch`](/docs/kcl/types/Sketch) | A sketch is a collection of paths. | Yes |
| `tag` | [`TagNode`](/docs/kcl/types/TagNode) | | No | | `tag` | [`TagDeclarator`](/docs/kcl/types#tag-declaration) | | No |
### Returns ### Returns

View File

@ -9,7 +9,7 @@ Draw a smooth, continuous, curved line segment from the current origin to
the desired (x, y), using a number of control points to shape the curve's shape. the desired (x, y), using a number of control points to shape the curve's shape.
```js ```js
bezierCurve(data: BezierData, sketch: Sketch, tag?: TagNode) -> Sketch bezierCurve(data: BezierData, sketch: Sketch, tag?: TagDeclarator) -> Sketch
``` ```
@ -19,7 +19,7 @@ bezierCurve(data: BezierData, sketch: Sketch, tag?: TagNode) -> Sketch
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `data` | [`BezierData`](/docs/kcl/types/BezierData) | Data to draw a bezier curve. | Yes | | `data` | [`BezierData`](/docs/kcl/types/BezierData) | Data to draw a bezier curve. | Yes |
| `sketch` | [`Sketch`](/docs/kcl/types/Sketch) | A sketch is a collection of paths. | Yes | | `sketch` | [`Sketch`](/docs/kcl/types/Sketch) | A sketch is a collection of paths. | Yes |
| `tag` | [`TagNode`](/docs/kcl/types/TagNode) | | No | | `tag` | [`TagDeclarator`](/docs/kcl/types#tag-declaration) | | No |
### Returns ### Returns

View File

@ -9,7 +9,7 @@ Cut a straight transitional edge along a tagged path.
Chamfer is similar in function and use to a fillet, except a fillet will blend the transition along an edge, rather than cut a sharp, straight transitional edge. Chamfer is similar in function and use to a fillet, except a fillet will blend the transition along an edge, rather than cut a sharp, straight transitional edge.
```js ```js
chamfer(data: ChamferData, solid: Solid, tag?: TagNode) -> Solid chamfer(data: ChamferData, solid: Solid, tag?: TagDeclarator) -> Solid
``` ```
@ -19,7 +19,7 @@ chamfer(data: ChamferData, solid: Solid, tag?: TagNode) -> Solid
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `data` | [`ChamferData`](/docs/kcl/types/ChamferData) | Data for chamfers. | Yes | | `data` | [`ChamferData`](/docs/kcl/types/ChamferData) | Data for chamfers. | Yes |
| `solid` | [`Solid`](/docs/kcl/types/Solid) | An solid is a collection of extrude surfaces. | Yes | | `solid` | [`Solid`](/docs/kcl/types/Solid) | An solid is a collection of extrude surfaces. | Yes |
| `tag` | [`TagNode`](/docs/kcl/types/TagNode) | | No | | `tag` | [`TagDeclarator`](/docs/kcl/types#tag-declaration) | | No |
### Returns ### Returns

View File

@ -9,7 +9,7 @@ Construct a 2-dimensional circle, of the specified radius, centered at
the provided (x, y) origin point. the provided (x, y) origin point.
```js ```js
circle(data: CircleData, sketch_surface_or_group: SketchOrSurface, tag?: TagNode) -> Sketch circle(data: CircleData, sketch_surface_or_group: SketchOrSurface, tag?: TagDeclarator) -> Sketch
``` ```
@ -19,7 +19,7 @@ circle(data: CircleData, sketch_surface_or_group: SketchOrSurface, tag?: TagNode
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `data` | [`CircleData`](/docs/kcl/types/CircleData) | Data for drawing an circle | Yes | | `data` | [`CircleData`](/docs/kcl/types/CircleData) | Data for drawing an circle | Yes |
| `sketch_surface_or_group` | [`SketchOrSurface`](/docs/kcl/types/SketchOrSurface) | A sketch surface or a sketch. | Yes | | `sketch_surface_or_group` | [`SketchOrSurface`](/docs/kcl/types/SketchOrSurface) | A sketch surface or a sketch. | Yes |
| `tag` | [`TagNode`](/docs/kcl/types/TagNode) | | No | | `tag` | [`TagDeclarator`](/docs/kcl/types#tag-declaration) | | No |
### Returns ### Returns

View File

@ -9,7 +9,7 @@ Construct a line segment from the current origin back to the profile's
origin, ensuring the resulting 2-dimensional sketch is not open-ended. origin, ensuring the resulting 2-dimensional sketch is not open-ended.
```js ```js
close(sketch: Sketch, tag?: TagNode) -> Sketch close(sketch: Sketch, tag?: TagDeclarator) -> Sketch
``` ```
@ -18,7 +18,7 @@ close(sketch: Sketch, tag?: TagNode) -> Sketch
| Name | Type | Description | Required | | Name | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `sketch` | [`Sketch`](/docs/kcl/types/Sketch) | A sketch is a collection of paths. | Yes | | `sketch` | [`Sketch`](/docs/kcl/types/Sketch) | A sketch is a collection of paths. | Yes |
| `tag` | [`TagNode`](/docs/kcl/types/TagNode) | | No | | `tag` | [`TagDeclarator`](/docs/kcl/types#tag-declaration) | | No |
### Returns ### Returns

View File

@ -9,7 +9,7 @@ Blend a transitional edge along a tagged path, smoothing the sharp edge.
Fillet is similar in function and use to a chamfer, except a chamfer will cut a sharp transition along an edge while fillet will smoothly blend the transition. Fillet is similar in function and use to a chamfer, except a chamfer will cut a sharp transition along an edge while fillet will smoothly blend the transition.
```js ```js
fillet(data: FilletData, solid: Solid, tag?: TagNode) -> Solid fillet(data: FilletData, solid: Solid, tag?: TagDeclarator) -> Solid
``` ```
@ -19,7 +19,7 @@ fillet(data: FilletData, solid: Solid, tag?: TagNode) -> Solid
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `data` | [`FilletData`](/docs/kcl/types/FilletData) | Data for fillets. | Yes | | `data` | [`FilletData`](/docs/kcl/types/FilletData) | Data for fillets. | Yes |
| `solid` | [`Solid`](/docs/kcl/types/Solid) | An solid is a collection of extrude surfaces. | Yes | | `solid` | [`Solid`](/docs/kcl/types/Solid) | An solid is a collection of extrude surfaces. | Yes |
| `tag` | [`TagNode`](/docs/kcl/types/TagNode) | | No | | `tag` | [`TagDeclarator`](/docs/kcl/types#tag-declaration) | | No |
### Returns ### Returns

View File

@ -9,7 +9,7 @@ Draw a line relative to the current origin to a specified (x, y) away
from the current position. from the current position.
```js ```js
line(delta: [number], sketch: Sketch, tag?: TagNode) -> Sketch line(delta: [number], sketch: Sketch, tag?: TagDeclarator) -> Sketch
``` ```
@ -19,7 +19,7 @@ line(delta: [number], sketch: Sketch, tag?: TagNode) -> Sketch
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `delta` | `[number]` | | Yes | | `delta` | `[number]` | | Yes |
| `sketch` | [`Sketch`](/docs/kcl/types/Sketch) | A sketch is a collection of paths. | Yes | | `sketch` | [`Sketch`](/docs/kcl/types/Sketch) | A sketch is a collection of paths. | Yes |
| `tag` | [`TagNode`](/docs/kcl/types/TagNode) | | No | | `tag` | [`TagDeclarator`](/docs/kcl/types#tag-declaration) | | No |
### Returns ### Returns

View File

@ -9,7 +9,7 @@ Draw a line from the current origin to some absolute (x, y) point.
```js ```js
lineTo(to: [number], sketch: Sketch, tag?: TagNode) -> Sketch lineTo(to: [number], sketch: Sketch, tag?: TagDeclarator) -> Sketch
``` ```
@ -19,7 +19,7 @@ lineTo(to: [number], sketch: Sketch, tag?: TagNode) -> Sketch
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `to` | `[number]` | | Yes | | `to` | `[number]` | | Yes |
| `sketch` | [`Sketch`](/docs/kcl/types/Sketch) | A sketch is a collection of paths. | Yes | | `sketch` | [`Sketch`](/docs/kcl/types/Sketch) | A sketch is a collection of paths. | Yes |
| `tag` | [`TagNode`](/docs/kcl/types/TagNode) | | No | | `tag` | [`TagDeclarator`](/docs/kcl/types#tag-declaration) | | No |
### Returns ### Returns

View File

@ -9,7 +9,7 @@ Start a new profile at a given point.
```js ```js
startProfileAt(to: [number], sketch_surface: SketchSurface, tag?: TagNode) -> Sketch startProfileAt(to: [number], sketch_surface: SketchSurface, tag?: TagDeclarator) -> Sketch
``` ```
@ -19,7 +19,7 @@ startProfileAt(to: [number], sketch_surface: SketchSurface, tag?: TagNode) -> Sk
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `to` | `[number]` | | Yes | | `to` | `[number]` | | Yes |
| `sketch_surface` | [`SketchSurface`](/docs/kcl/types/SketchSurface) | A sketch type. | Yes | | `sketch_surface` | [`SketchSurface`](/docs/kcl/types/SketchSurface) | A sketch type. | Yes |
| `tag` | [`TagNode`](/docs/kcl/types/TagNode) | | No | | `tag` | [`TagDeclarator`](/docs/kcl/types#tag-declaration) | | No |
### Returns ### Returns

File diff suppressed because it is too large Load Diff

View File

@ -9,7 +9,7 @@ Draw a curved line segment along part of an imaginary circle.
The arc is constructed such that the last line segment is placed tangent to the imaginary circle of the specified radius. The resulting arc is the segment of the imaginary circle from that tangent point for 'offset' degrees along the imaginary circle. The arc is constructed such that the last line segment is placed tangent to the imaginary circle of the specified radius. The resulting arc is the segment of the imaginary circle from that tangent point for 'offset' degrees along the imaginary circle.
```js ```js
tangentialArc(data: TangentialArcData, sketch: Sketch, tag?: TagNode) -> Sketch tangentialArc(data: TangentialArcData, sketch: Sketch, tag?: TagDeclarator) -> Sketch
``` ```
@ -19,7 +19,7 @@ tangentialArc(data: TangentialArcData, sketch: Sketch, tag?: TagNode) -> Sketch
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `data` | [`TangentialArcData`](/docs/kcl/types/TangentialArcData) | Data to draw a tangential arc. | Yes | | `data` | [`TangentialArcData`](/docs/kcl/types/TangentialArcData) | Data to draw a tangential arc. | Yes |
| `sketch` | [`Sketch`](/docs/kcl/types/Sketch) | A sketch is a collection of paths. | Yes | | `sketch` | [`Sketch`](/docs/kcl/types/Sketch) | A sketch is a collection of paths. | Yes |
| `tag` | [`TagNode`](/docs/kcl/types/TagNode) | | No | | `tag` | [`TagDeclarator`](/docs/kcl/types#tag-declaration) | | No |
### Returns ### Returns

View File

@ -9,7 +9,7 @@ Starting at the current sketch's origin, draw a curved line segment along
some part of an imaginary circle until it reaches the desired (x, y) coordinates. some part of an imaginary circle until it reaches the desired (x, y) coordinates.
```js ```js
tangentialArcTo(to: [number], sketch: Sketch, tag?: TagNode) -> Sketch tangentialArcTo(to: [number], sketch: Sketch, tag?: TagDeclarator) -> Sketch
``` ```
@ -19,7 +19,7 @@ tangentialArcTo(to: [number], sketch: Sketch, tag?: TagNode) -> Sketch
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `to` | `[number]` | | Yes | | `to` | `[number]` | | Yes |
| `sketch` | [`Sketch`](/docs/kcl/types/Sketch) | A sketch is a collection of paths. | Yes | | `sketch` | [`Sketch`](/docs/kcl/types/Sketch) | A sketch is a collection of paths. | Yes |
| `tag` | [`TagNode`](/docs/kcl/types/TagNode) | | No | | `tag` | [`TagDeclarator`](/docs/kcl/types#tag-declaration) | | No |
### Returns ### Returns

View File

@ -9,7 +9,7 @@ Starting at the current sketch's origin, draw a curved line segment along
some part of an imaginary circle until it reaches a point the given (x, y) distance away. some part of an imaginary circle until it reaches a point the given (x, y) distance away.
```js ```js
tangentialArcToRelative(delta: [number], sketch: Sketch, tag?: TagNode) -> Sketch tangentialArcToRelative(delta: [number], sketch: Sketch, tag?: TagDeclarator) -> Sketch
``` ```
@ -19,7 +19,7 @@ tangentialArcToRelative(delta: [number], sketch: Sketch, tag?: TagNode) -> Sketc
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `delta` | `[number]` | | Yes | | `delta` | `[number]` | | Yes |
| `sketch` | [`Sketch`](/docs/kcl/types/Sketch) | A sketch is a collection of paths. | Yes | | `sketch` | [`Sketch`](/docs/kcl/types/Sketch) | A sketch is a collection of paths. | Yes |
| `tag` | [`TagNode`](/docs/kcl/types/TagNode) | | No | | `tag` | [`TagDeclarator`](/docs/kcl/types#tag-declaration) | | No |
### Returns ### Returns

View File

@ -18,7 +18,7 @@ A base path.
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `from` |`[number, number]`| The from point. | No | | `from` |`[number, number]`| The from point. | No |
| `to` |`[number, number]`| The to point. | No | | `to` |`[number, number]`| The to point. | No |
| `tag` |[`TagNode`](/docs/kcl/types/TagNode)| The tag of the path. | No | | `tag` |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| The tag of the path. | No |
| `__geoMeta` |[`GeoMeta`](/docs/kcl/types/GeoMeta)| Metadata. | No | | `__geoMeta` |[`GeoMeta`](/docs/kcl/types/GeoMeta)| Metadata. | No |

View File

@ -22,10 +22,12 @@ layout: manual
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `type` |enum: [`Literal`](/docs/kcl/types/Literal)| | No | | `type` |enum: `Literal`| | No |
| `kind` |[`Literal`](/docs/kcl/types/Literal)| | No |
| `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `value` |[`LiteralValue`](/docs/kcl/types/LiteralValue)| | No |
| `raw` |`string`| | No |
| `digest` |`[, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`]`| | No |
---- ----
@ -41,9 +43,10 @@ layout: manual
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `type` |enum: [`Identifier`](/docs/kcl/types/Identifier)| | No | | `type` |enum: [`Identifier`](/docs/kcl/types/Identifier)| | No |
| `kind` |[`Identifier`](/docs/kcl/types/Identifier)| | No |
| `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `name` |`string`| | No |
| `digest` |`[, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`]`| | No |
---- ----
@ -58,10 +61,13 @@ layout: manual
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `type` |enum: [`BinaryExpression`](/docs/kcl/types/BinaryExpression)| | No | | `type` |enum: `BinaryExpression`| | No |
| `kind` |[`BinaryExpression`](/docs/kcl/types/BinaryExpression)| | No |
| `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `operator` |[`BinaryOperator`](/docs/kcl/types/BinaryOperator)| | No |
| `left` |[`BinaryPart`](/docs/kcl/types/BinaryPart)| | No |
| `right` |[`BinaryPart`](/docs/kcl/types/BinaryPart)| | No |
| `digest` |`[, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`]`| | No |
---- ----
@ -76,10 +82,13 @@ layout: manual
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `type` |enum: [`CallExpression`](/docs/kcl/types/CallExpression)| | No | | `type` |enum: `CallExpression`| | No |
| `kind` |[`CallExpression`](/docs/kcl/types/CallExpression)| | No |
| `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `callee` |[`Identifier`](/docs/kcl/types/Identifier)| | No |
| `arguments` |`[` [`Expr`](/docs/kcl/types/Expr) `]`| | No |
| `optional` |`boolean`| | No |
| `digest` |`[, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`]`| | No |
---- ----
@ -94,10 +103,12 @@ layout: manual
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `type` |enum: [`UnaryExpression`](/docs/kcl/types/UnaryExpression)| | No | | `type` |enum: `UnaryExpression`| | No |
| `kind` |[`UnaryExpression`](/docs/kcl/types/UnaryExpression)| | No |
| `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `operator` |[`UnaryOperator`](/docs/kcl/types/UnaryOperator)| | No |
| `argument` |[`BinaryPart`](/docs/kcl/types/BinaryPart)| | No |
| `digest` |`[, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`]`| | No |
---- ----
@ -112,10 +123,13 @@ layout: manual
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `type` |enum: [`MemberExpression`](/docs/kcl/types/MemberExpression)| | No | | `type` |enum: `MemberExpression`| | No |
| `kind` |[`MemberExpression`](/docs/kcl/types/MemberExpression)| | No |
| `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `object` |[`MemberObject`](/docs/kcl/types/MemberObject)| | No |
| `property` |[`LiteralIdentifier`](/docs/kcl/types/LiteralIdentifier)| | No |
| `computed` |`boolean`| | No |
| `digest` |`[, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`]`| | No |
---- ----
@ -130,10 +144,14 @@ layout: manual
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `type` |enum: [`IfExpression`](/docs/kcl/types/IfExpression)| | No | | `type` |enum: `IfExpression`| | No |
| `kind` |[`IfExpression`](/docs/kcl/types/IfExpression)| | No |
| `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `cond` |[`Expr`](/docs/kcl/types/Expr)| | No |
| `then_val` |[`Program`](/docs/kcl/types/Program)| | No |
| `else_ifs` |`[` [`ElseIf`](/docs/kcl/types/ElseIf) `]`| | No |
| `final_else` |[`Program`](/docs/kcl/types/Program)| | No |
| `digest` |`[, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`]`| | No |
---- ----

View File

@ -22,10 +22,13 @@ layout: manual
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `type` |enum: [`ImportStatement`](/docs/kcl/types/ImportStatement)| | No | | `type` |enum: `ImportStatement`| | No |
| `kind` |[`ImportStatement`](/docs/kcl/types/ImportStatement)| | No |
| `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `items` |`[` [`ImportItem`](/docs/kcl/types/ImportItem) `]`| | No |
| `path` |`string`| | No |
| `raw_path` |`string`| | No |
| `digest` |`[, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`]`| | No |
---- ----
@ -40,10 +43,11 @@ layout: manual
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `type` |enum: [`ExpressionStatement`](/docs/kcl/types/ExpressionStatement)| | No | | `type` |enum: `ExpressionStatement`| | No |
| `kind` |[`ExpressionStatement`](/docs/kcl/types/ExpressionStatement)| | No |
| `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `expression` |[`Expr`](/docs/kcl/types/Expr)| | No |
| `digest` |`[, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`]`| | No |
---- ----
@ -58,10 +62,13 @@ layout: manual
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `type` |enum: [`VariableDeclaration`](/docs/kcl/types/VariableDeclaration)| | No | | `type` |enum: `VariableDeclaration`| | No |
| `kind` |[`VariableDeclaration`](/docs/kcl/types/VariableDeclaration)| | No |
| `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `declarations` |`[` [`VariableDeclarator`](/docs/kcl/types/VariableDeclarator) `]`| | No |
| `visibility` |[`ItemVisibility`](/docs/kcl/types/ItemVisibility)| | No |
| `kind` |[`VariableKind`](/docs/kcl/types/VariableKind)| | No |
| `digest` |`[, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`]`| | No |
---- ----
@ -76,10 +83,11 @@ layout: manual
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `type` |enum: [`ReturnStatement`](/docs/kcl/types/ReturnStatement)| | No | | `type` |enum: `ReturnStatement`| | No |
| `kind` |[`ReturnStatement`](/docs/kcl/types/ReturnStatement)| | No |
| `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `argument` |[`Expr`](/docs/kcl/types/Expr)| | No |
| `digest` |`[, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`]`| | No |
---- ----

View File

@ -28,7 +28,7 @@ A fillet.
| `id` |`string`| The id of the engine command that called this fillet. | No | | `id` |`string`| The id of the engine command that called this fillet. | No |
| `radius` |`number`| | No | | `radius` |`number`| | No |
| `edgeId` |`string`| The engine id of the edge to fillet. | No | | `edgeId` |`string`| The engine id of the edge to fillet. | No |
| `tag` |[`TagNode`](/docs/kcl/types/TagNode)| | No | | `tag` |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| | No |
---- ----
@ -48,7 +48,7 @@ A chamfer.
| `id` |`string`| The id of the engine command that called this chamfer. | No | | `id` |`string`| The id of the engine command that called this chamfer. | No |
| `length` |`number`| | No | | `length` |`number`| | No |
| `edgeId` |`string`| The engine id of the edge to chamfer. | No | | `edgeId` |`string`| The engine id of the edge to chamfer. | No |
| `tag` |[`TagNode`](/docs/kcl/types/TagNode)| | No | | `tag` |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| | No |
---- ----

View File

@ -15,8 +15,10 @@ layout: manual
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `cond` |[`Expr`](/docs/kcl/types/Expr)| | No | | `cond` |[`Expr`](/docs/kcl/types/Expr)| | No |
| `then_val` |[`UnboxedNode_for_Program`](/docs/kcl/types/UnboxedNode_for_Program)| | No | | `then_val` |[`Program`](/docs/kcl/types/Program)| | No |
| `digest` |`[, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`]`| | No | | `digest` |`[, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`]`| | No |

View File

@ -23,10 +23,12 @@ An expression can be evaluated to yield a single KCL value.
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `type` |enum: [`Literal`](/docs/kcl/types/Literal)| | No | | `type` |enum: `Literal`| | No |
| `kind` |[`Literal`](/docs/kcl/types/Literal)| An expression can be evaluated to yield a single KCL value. | No |
| `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `value` |[`LiteralValue`](/docs/kcl/types/LiteralValue)| An expression can be evaluated to yield a single KCL value. | No |
| `raw` |`string`| | No |
| `digest` |`[, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`]`| | No |
---- ----
@ -42,9 +44,10 @@ An expression can be evaluated to yield a single KCL value.
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `type` |enum: [`Identifier`](/docs/kcl/types/Identifier)| | No | | `type` |enum: [`Identifier`](/docs/kcl/types/Identifier)| | No |
| `kind` |[`Identifier`](/docs/kcl/types/Identifier)| An expression can be evaluated to yield a single KCL value. | No |
| `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `name` |`string`| | No |
| `digest` |`[, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`]`| | No |
---- ----
@ -60,9 +63,10 @@ An expression can be evaluated to yield a single KCL value.
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `type` |enum: [`TagDeclarator`](/docs/kcl/types#tag-declaration)| | No | | `type` |enum: [`TagDeclarator`](/docs/kcl/types#tag-declaration)| | No |
| `kind` |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| An expression can be evaluated to yield a single KCL value. | No |
| `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `value` |`string`| | No |
| `digest` |`[, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`]`| | No |
---- ----
@ -77,10 +81,13 @@ An expression can be evaluated to yield a single KCL value.
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `type` |enum: [`BinaryExpression`](/docs/kcl/types/BinaryExpression)| | No | | `type` |enum: `BinaryExpression`| | No |
| `kind` |[`BinaryExpression`](/docs/kcl/types/BinaryExpression)| An expression can be evaluated to yield a single KCL value. | No |
| `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `operator` |[`BinaryOperator`](/docs/kcl/types/BinaryOperator)| An expression can be evaluated to yield a single KCL value. | No |
| `left` |[`BinaryPart`](/docs/kcl/types/BinaryPart)| An expression can be evaluated to yield a single KCL value. | No |
| `right` |[`BinaryPart`](/docs/kcl/types/BinaryPart)| An expression can be evaluated to yield a single KCL value. | No |
| `digest` |`[, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`]`| | No |
---- ----
@ -96,9 +103,11 @@ An expression can be evaluated to yield a single KCL value.
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `type` |enum: [`FunctionExpression`](/docs/kcl/types/FunctionExpression)| | No | | `type` |enum: [`FunctionExpression`](/docs/kcl/types/FunctionExpression)| | No |
| `kind` |[`FunctionExpression`](/docs/kcl/types/FunctionExpression)| An expression can be evaluated to yield a single KCL value. | No |
| `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `params` |`[` [`Parameter`](/docs/kcl/types/Parameter) `]`| | No |
| `body` |[`Program`](/docs/kcl/types/Program)| An expression can be evaluated to yield a single KCL value. | No |
| `digest` |`[, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`]`| | No |
---- ----
@ -113,10 +122,13 @@ An expression can be evaluated to yield a single KCL value.
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `type` |enum: [`CallExpression`](/docs/kcl/types/CallExpression)| | No | | `type` |enum: `CallExpression`| | No |
| `kind` |[`CallExpression`](/docs/kcl/types/CallExpression)| An expression can be evaluated to yield a single KCL value. | No |
| `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `callee` |[`Identifier`](/docs/kcl/types/Identifier)| An expression can be evaluated to yield a single KCL value. | No |
| `arguments` |`[` [`Expr`](/docs/kcl/types/Expr) `]`| | No |
| `optional` |`boolean`| | No |
| `digest` |`[, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`]`| | No |
---- ----
@ -131,10 +143,12 @@ An expression can be evaluated to yield a single KCL value.
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `type` |enum: [`PipeExpression`](/docs/kcl/types/PipeExpression)| | No | | `type` |enum: `PipeExpression`| | No |
| `kind` |[`PipeExpression`](/docs/kcl/types/PipeExpression)| An expression can be evaluated to yield a single KCL value. | No |
| `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `body` |`[` [`Expr`](/docs/kcl/types/Expr) `]`| | No |
| `nonCodeMeta` |[`NonCodeMeta`](/docs/kcl/types/NonCodeMeta)| An expression can be evaluated to yield a single KCL value. | No |
| `digest` |`[, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`]`| | No |
---- ----
@ -149,10 +163,10 @@ An expression can be evaluated to yield a single KCL value.
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `type` |enum: [`PipeSubstitution`](/docs/kcl/types/PipeSubstitution)| | No | | `type` |enum: `PipeSubstitution`| | No |
| `kind` |[`PipeSubstitution`](/docs/kcl/types/PipeSubstitution)| An expression can be evaluated to yield a single KCL value. | No |
| `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `digest` |`[, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`]`| | No |
---- ----
@ -167,10 +181,12 @@ An expression can be evaluated to yield a single KCL value.
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `type` |enum: [`ArrayExpression`](/docs/kcl/types/ArrayExpression)| | No | | `type` |enum: `ArrayExpression`| | No |
| `kind` |[`ArrayExpression`](/docs/kcl/types/ArrayExpression)| An expression can be evaluated to yield a single KCL value. | No |
| `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `elements` |`[` [`Expr`](/docs/kcl/types/Expr) `]`| | No |
| `nonCodeMeta` |[`NonCodeMeta`](/docs/kcl/types/NonCodeMeta)| An expression can be evaluated to yield a single KCL value. | No |
| `digest` |`[, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`]`| | No |
---- ----
@ -185,10 +201,13 @@ An expression can be evaluated to yield a single KCL value.
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `type` |enum: [`ArrayRangeExpression`](/docs/kcl/types/ArrayRangeExpression)| | No | | `type` |enum: `ArrayRangeExpression`| | No |
| `kind` |[`ArrayRangeExpression`](/docs/kcl/types/ArrayRangeExpression)| An expression can be evaluated to yield a single KCL value. | No |
| `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `startElement` |[`Expr`](/docs/kcl/types/Expr)| An expression can be evaluated to yield a single KCL value. | No |
| `endElement` |[`Expr`](/docs/kcl/types/Expr)| An expression can be evaluated to yield a single KCL value. | No |
| `endInclusive` |`boolean`| Is the `end_element` included in the range? | No |
| `digest` |`[, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`]`| | No |
---- ----
@ -203,10 +222,12 @@ An expression can be evaluated to yield a single KCL value.
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `type` |enum: [`ObjectExpression`](/docs/kcl/types/ObjectExpression)| | No | | `type` |enum: `ObjectExpression`| | No |
| `kind` |[`ObjectExpression`](/docs/kcl/types/ObjectExpression)| An expression can be evaluated to yield a single KCL value. | No |
| `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `properties` |`[` [`ObjectProperty`](/docs/kcl/types/ObjectProperty) `]`| | No |
| `nonCodeMeta` |[`NonCodeMeta`](/docs/kcl/types/NonCodeMeta)| An expression can be evaluated to yield a single KCL value. | No |
| `digest` |`[, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`]`| | No |
---- ----
@ -221,10 +242,13 @@ An expression can be evaluated to yield a single KCL value.
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `type` |enum: [`MemberExpression`](/docs/kcl/types/MemberExpression)| | No | | `type` |enum: `MemberExpression`| | No |
| `kind` |[`MemberExpression`](/docs/kcl/types/MemberExpression)| An expression can be evaluated to yield a single KCL value. | No |
| `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `object` |[`MemberObject`](/docs/kcl/types/MemberObject)| An expression can be evaluated to yield a single KCL value. | No |
| `property` |[`LiteralIdentifier`](/docs/kcl/types/LiteralIdentifier)| An expression can be evaluated to yield a single KCL value. | No |
| `computed` |`boolean`| | No |
| `digest` |`[, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`]`| | No |
---- ----
@ -239,10 +263,12 @@ An expression can be evaluated to yield a single KCL value.
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `type` |enum: [`UnaryExpression`](/docs/kcl/types/UnaryExpression)| | No | | `type` |enum: `UnaryExpression`| | No |
| `kind` |[`UnaryExpression`](/docs/kcl/types/UnaryExpression)| An expression can be evaluated to yield a single KCL value. | No |
| `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `operator` |[`UnaryOperator`](/docs/kcl/types/UnaryOperator)| An expression can be evaluated to yield a single KCL value. | No |
| `argument` |[`BinaryPart`](/docs/kcl/types/BinaryPart)| An expression can be evaluated to yield a single KCL value. | No |
| `digest` |`[, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`]`| | No |
---- ----
@ -257,10 +283,14 @@ An expression can be evaluated to yield a single KCL value.
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `type` |enum: [`IfExpression`](/docs/kcl/types/IfExpression)| | No | | `type` |enum: `IfExpression`| | No |
| `kind` |[`IfExpression`](/docs/kcl/types/IfExpression)| An expression can be evaluated to yield a single KCL value. | No |
| `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `cond` |[`Expr`](/docs/kcl/types/Expr)| An expression can be evaluated to yield a single KCL value. | No |
| `then_val` |[`Program`](/docs/kcl/types/Program)| An expression can be evaluated to yield a single KCL value. | No |
| `else_ifs` |`[` [`ElseIf`](/docs/kcl/types/ElseIf) `]`| | No |
| `final_else` |[`Program`](/docs/kcl/types/Program)| An expression can be evaluated to yield a single KCL value. | No |
| `digest` |`[, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`]`| | No |
---- ----

View File

@ -26,7 +26,7 @@ An extrude plane.
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `type` |enum: `extrudePlane`| | No | | `type` |enum: `extrudePlane`| | No |
| `faceId` |`string`| The face id for the extrude plane. | No | | `faceId` |`string`| The face id for the extrude plane. | No |
| `tag` |[`TagNode`](/docs/kcl/types/TagNode)| The tag. | No | | `tag` |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| The tag. | No |
| `id` |`string`| The id of the geometry. | No | | `id` |`string`| The id of the geometry. | No |
| `sourceRange` |`SourceRange`| The source range. | No | | `sourceRange` |`SourceRange`| The source range. | No |
@ -46,7 +46,7 @@ An extruded arc.
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `type` |enum: `extrudeArc`| | No | | `type` |enum: `extrudeArc`| | No |
| `faceId` |`string`| The face id for the extrude plane. | No | | `faceId` |`string`| The face id for the extrude plane. | No |
| `tag` |[`TagNode`](/docs/kcl/types/TagNode)| The tag. | No | | `tag` |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| The tag. | No |
| `id` |`string`| The id of the geometry. | No | | `id` |`string`| The id of the geometry. | No |
| `sourceRange` |`SourceRange`| The source range. | No | | `sourceRange` |`SourceRange`| The source range. | No |
@ -66,7 +66,7 @@ Geometry metadata.
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `type` |enum: `chamfer`| | No | | `type` |enum: `chamfer`| | No |
| `faceId` |`string`| The id for the chamfer surface. | No | | `faceId` |`string`| The id for the chamfer surface. | No |
| `tag` |[`TagNode`](/docs/kcl/types/TagNode)| The tag. | No | | `tag` |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| The tag. | No |
| `id` |`string`| The id of the geometry. | No | | `id` |`string`| The id of the geometry. | No |
| `sourceRange` |`SourceRange`| The source range. | No | | `sourceRange` |`SourceRange`| The source range. | No |
@ -86,7 +86,7 @@ Geometry metadata.
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `type` |enum: `fillet`| | No | | `type` |enum: `fillet`| | No |
| `faceId` |`string`| The id for the fillet surface. | No | | `faceId` |`string`| The id for the fillet surface. | No |
| `tag` |[`TagNode`](/docs/kcl/types/TagNode)| The tag. | No | | `tag` |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| The tag. | No |
| `id` |`string`| The id of the geometry. | No | | `id` |`string`| The id of the geometry. | No |
| `sourceRange` |`SourceRange`| The source range. | No | | `sourceRange` |`SourceRange`| The source range. | No |

View File

@ -15,8 +15,10 @@ layout: manual
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `params` |`[` [`Parameter`](/docs/kcl/types/Parameter) `]`| | No | | `params` |`[` [`Parameter`](/docs/kcl/types/Parameter) `]`| | No |
| `body` |[`UnboxedNode_for_Program`](/docs/kcl/types/UnboxedNode_for_Program)| | No | | `body` |[`Program`](/docs/kcl/types/Program)| | No |
| `digest` |`[, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`]`| | No | | `digest` |`[, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`]`| | No |

View File

@ -15,6 +15,8 @@ layout: manual
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `name` |`string`| | No | | `name` |`string`| | No |
| `digest` |`[, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`]`| | No | | `digest` |`[, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`]`| | No |

View File

@ -15,8 +15,10 @@ layout: manual
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `name` |[`UnboxedNode_for_Identifier`](/docs/kcl/types/UnboxedNode_for_Identifier)| Name of the item to import. | No | | `name` |[`Identifier`](/docs/kcl/types/Identifier)| Name of the item to import. | No |
| `alias` |[`UnboxedNode_for_Identifier`](/docs/kcl/types/UnboxedNode_for_Identifier)| Rename the item using an identifier after "as". | No | | `alias` |[`Identifier`](/docs/kcl/types/Identifier)| Rename the item using an identifier after "as". | No |
| `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `digest` |`[, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`]`| | No | | `digest` |`[, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`]`| | No |

View File

@ -59,9 +59,10 @@ Any KCL value.
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `type` |enum: [`TagDeclarator`](/docs/kcl/types#tag-declaration)| | No | | `type` |enum: [`TagDeclarator`](/docs/kcl/types#tag-declaration)| | No |
| `kind` |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| Any KCL value. | No |
| `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `value` |`string`| | No |
| `digest` |`[, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`]`| | No |
---- ----
@ -182,7 +183,7 @@ Data for an imported geometry.
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `type` |enum: `Function`| | No | | `type` |enum: `Function`| | No |
| `expression` |[`UnboxedNode_for_FunctionExpression`](/docs/kcl/types/UnboxedNode_for_FunctionExpression)| Any KCL value. | No | | `expression` |[`FunctionExpression`](/docs/kcl/types/FunctionExpression)| Any KCL value. | No |
| `memory` |[`ProgramMemory`](/docs/kcl/types/ProgramMemory)| Any KCL value. | No | | `memory` |[`ProgramMemory`](/docs/kcl/types/ProgramMemory)| Any KCL value. | No |
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No | | `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |

View File

@ -23,9 +23,10 @@ layout: manual
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `type` |enum: [`Identifier`](/docs/kcl/types/Identifier)| | No | | `type` |enum: [`Identifier`](/docs/kcl/types/Identifier)| | No |
| `kind` |[`Identifier`](/docs/kcl/types/Identifier)| | No |
| `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `name` |`string`| | No |
| `digest` |`[, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`]`| | No |
---- ----
@ -40,10 +41,12 @@ layout: manual
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `type` |enum: [`Literal`](/docs/kcl/types/Literal)| | No | | `type` |enum: `Literal`| | No |
| `kind` |[`Literal`](/docs/kcl/types/Literal)| | No |
| `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `value` |[`LiteralValue`](/docs/kcl/types/LiteralValue)| | No |
| `raw` |`string`| | No |
| `digest` |`[, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`]`| | No |
---- ----

View File

@ -22,10 +22,13 @@ layout: manual
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `type` |enum: [`MemberExpression`](/docs/kcl/types/MemberExpression)| | No | | `type` |enum: `MemberExpression`| | No |
| `kind` |[`MemberExpression`](/docs/kcl/types/MemberExpression)| | No |
| `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `object` |[`MemberObject`](/docs/kcl/types/MemberObject)| | No |
| `property` |[`LiteralIdentifier`](/docs/kcl/types/LiteralIdentifier)| | No |
| `computed` |`boolean`| | No |
| `digest` |`[, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`]`| | No |
---- ----
@ -41,9 +44,10 @@ layout: manual
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `type` |enum: [`Identifier`](/docs/kcl/types/Identifier)| | No | | `type` |enum: [`Identifier`](/docs/kcl/types/Identifier)| | No |
| `kind` |[`Identifier`](/docs/kcl/types/Identifier)| | No |
| `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No | | `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `name` |`string`| | No |
| `digest` |`[, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`]`| | No |
---- ----

View File

@ -16,7 +16,7 @@ layout: manual
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `nonCodeNodes` |`object`| | No | | `nonCodeNodes` |`object`| | No |
| `start` |`[` [`UnboxedNode_for_NonCodeNode`](/docs/kcl/types/UnboxedNode_for_NonCodeNode) `]`| | No | | `start` |`[` [`NonCodeNode`](/docs/kcl/types/NonCodeNode) `]`| | No |
| `digest` |`[, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`]`| | No | | `digest` |`[, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`]`| | No |

View File

@ -15,6 +15,8 @@ layout: manual
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `value` |[`NonCodeValue`](/docs/kcl/types/NonCodeValue)| | No | | `value` |[`NonCodeValue`](/docs/kcl/types/NonCodeValue)| | No |
| `digest` |`[, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`]`| | No | | `digest` |`[, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`]`| | No |

View File

@ -15,7 +15,9 @@ layout: manual
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `key` |[`UnboxedNode_for_Identifier`](/docs/kcl/types/UnboxedNode_for_Identifier)| | No | | `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `key` |[`Identifier`](/docs/kcl/types/Identifier)| | No |
| `value` |[`Expr`](/docs/kcl/types/Expr)| | No | | `value` |[`Expr`](/docs/kcl/types/Expr)| | No |
| `digest` |`[, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`]`| | No | | `digest` |`[, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`]`| | No |

View File

@ -16,7 +16,7 @@ Parameter of a KCL function.
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `identifier` |[`UnboxedNode_for_Identifier`](/docs/kcl/types/UnboxedNode_for_Identifier)| The parameter's label or name. | No | | `identifier` |[`Identifier`](/docs/kcl/types/Identifier)| The parameter's label or name. | No |
| `optional` |`boolean`| Is the parameter optional? | No | | `optional` |`boolean`| Is the parameter optional? | No |
| `digest` |`[, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`]`| | No | | `digest` |`[, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`]`| | No |

View File

@ -27,7 +27,7 @@ A path that goes to a point.
| `type` |enum: `ToPoint`| | No | | `type` |enum: `ToPoint`| | No |
| `from` |`[number, number]`| The from point. | No | | `from` |`[number, number]`| The from point. | No |
| `to` |`[number, number]`| The to point. | No | | `to` |`[number, number]`| The to point. | No |
| `tag` |[`TagNode`](/docs/kcl/types/TagNode)| The tag of the path. | No | | `tag` |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| The tag of the path. | No |
| `__geoMeta` |[`GeoMeta`](/docs/kcl/types/GeoMeta)| Metadata. | No | | `__geoMeta` |[`GeoMeta`](/docs/kcl/types/GeoMeta)| Metadata. | No |
@ -49,7 +49,7 @@ A arc that is tangential to the last path segment that goes to a point
| `ccw` |`boolean`| arc's direction | No | | `ccw` |`boolean`| arc's direction | No |
| `from` |`[number, number]`| The from point. | No | | `from` |`[number, number]`| The from point. | No |
| `to` |`[number, number]`| The to point. | No | | `to` |`[number, number]`| The to point. | No |
| `tag` |[`TagNode`](/docs/kcl/types/TagNode)| The tag of the path. | No | | `tag` |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| The tag of the path. | No |
| `__geoMeta` |[`GeoMeta`](/docs/kcl/types/GeoMeta)| Metadata. | No | | `__geoMeta` |[`GeoMeta`](/docs/kcl/types/GeoMeta)| Metadata. | No |
@ -71,7 +71,7 @@ A arc that is tangential to the last path segment
| `ccw` |`boolean`| arc's direction | No | | `ccw` |`boolean`| arc's direction | No |
| `from` |`[number, number]`| The from point. | No | | `from` |`[number, number]`| The from point. | No |
| `to` |`[number, number]`| The to point. | No | | `to` |`[number, number]`| The to point. | No |
| `tag` |[`TagNode`](/docs/kcl/types/TagNode)| The tag of the path. | No | | `tag` |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| The tag of the path. | No |
| `__geoMeta` |[`GeoMeta`](/docs/kcl/types/GeoMeta)| Metadata. | No | | `__geoMeta` |[`GeoMeta`](/docs/kcl/types/GeoMeta)| Metadata. | No |
@ -94,7 +94,7 @@ a complete arc
| `ccw` |`boolean`| arc's direction | No | | `ccw` |`boolean`| arc's direction | No |
| `from` |`[number, number]`| The from point. | No | | `from` |`[number, number]`| The from point. | No |
| `to` |`[number, number]`| The to point. | No | | `to` |`[number, number]`| The to point. | No |
| `tag` |[`TagNode`](/docs/kcl/types/TagNode)| The tag of the path. | No | | `tag` |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| The tag of the path. | No |
| `__geoMeta` |[`GeoMeta`](/docs/kcl/types/GeoMeta)| Metadata. | No | | `__geoMeta` |[`GeoMeta`](/docs/kcl/types/GeoMeta)| Metadata. | No |
@ -115,7 +115,7 @@ A path that is horizontal.
| `x` |`number`| The x coordinate. | No | | `x` |`number`| The x coordinate. | No |
| `from` |`[number, number]`| The from point. | No | | `from` |`[number, number]`| The from point. | No |
| `to` |`[number, number]`| The to point. | No | | `to` |`[number, number]`| The to point. | No |
| `tag` |[`TagNode`](/docs/kcl/types/TagNode)| The tag of the path. | No | | `tag` |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| The tag of the path. | No |
| `__geoMeta` |[`GeoMeta`](/docs/kcl/types/GeoMeta)| Metadata. | No | | `__geoMeta` |[`GeoMeta`](/docs/kcl/types/GeoMeta)| Metadata. | No |
@ -137,7 +137,7 @@ An angled line to.
| `y` |`number`| The y coordinate. | No | | `y` |`number`| The y coordinate. | No |
| `from` |`[number, number]`| The from point. | No | | `from` |`[number, number]`| The from point. | No |
| `to` |`[number, number]`| The to point. | No | | `to` |`[number, number]`| The to point. | No |
| `tag` |[`TagNode`](/docs/kcl/types/TagNode)| The tag of the path. | No | | `tag` |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| The tag of the path. | No |
| `__geoMeta` |[`GeoMeta`](/docs/kcl/types/GeoMeta)| Metadata. | No | | `__geoMeta` |[`GeoMeta`](/docs/kcl/types/GeoMeta)| Metadata. | No |
@ -157,7 +157,29 @@ A base path.
| `type` |enum: `Base`| | No | | `type` |enum: `Base`| | No |
| `from` |`[number, number]`| The from point. | No | | `from` |`[number, number]`| The from point. | No |
| `to` |`[number, number]`| The to point. | No | | `to` |`[number, number]`| The to point. | No |
| `tag` |[`TagNode`](/docs/kcl/types/TagNode)| The tag of the path. | No | | `tag` |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| The tag of the path. | No |
| `__geoMeta` |[`GeoMeta`](/docs/kcl/types/GeoMeta)| Metadata. | No |
----
A circular arc, not necessarily tangential to the current point.
**Type:** `object`
## Properties
| Property | Type | Description | Required |
|----------|------|-------------|----------|
| `type` |enum: `Arc`| | No |
| `center` |`[number, number]`| Center of the circle that this arc is drawn on. | No |
| `radius` |`number`| Radius of the circle that this arc is drawn on. | No |
| `from` |`[number, number]`| The from point. | No |
| `to` |`[number, number]`| The to point. | No |
| `tag` |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| The tag of the path. | No |
| `__geoMeta` |[`GeoMeta`](/docs/kcl/types/GeoMeta)| Metadata. | No | | `__geoMeta` |[`GeoMeta`](/docs/kcl/types/GeoMeta)| Metadata. | No |

View File

@ -16,8 +16,10 @@ A KCL program top level, or function body.
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `start` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `end` |[`EnvironmentRef`](/docs/kcl/types/EnvironmentRef)| | No |
| `body` |`[` [`BodyItem`](/docs/kcl/types/BodyItem) `]`| | No | | `body` |`[` [`BodyItem`](/docs/kcl/types/BodyItem) `]`| | No |
| `nonCodeMeta` |[`UnboxedNode_for_NonCodeMeta`](/docs/kcl/types/UnboxedNode_for_NonCodeMeta)| A KCL program top level, or function body. | No | | `nonCodeMeta` |[`NonCodeMeta`](/docs/kcl/types/NonCodeMeta)| A KCL program top level, or function body. | No |
| `digest` |`[, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`]`| | No | | `digest` |`[, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`, `integer`]`| | No |

View File

@ -16,8 +16,8 @@ A sketch is a collection of paths.
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `id` |`string`| The id of the sketch (this will change when the engine's reference to it changes. | No | | `id` |`string`| The id of the sketch (this will change when the engine's reference to it changes). | No |
| `value` |`[` [`Path`](/docs/kcl/types/Path) `]`| The paths in the sketch. | No | | `paths` |`[` [`Path`](/docs/kcl/types/Path) `]`| The paths in the sketch. | No |
| `on` |[`SketchSurface`](/docs/kcl/types/SketchSurface)| What the sketch is on (can be a plane or a face). | No | | `on` |[`SketchSurface`](/docs/kcl/types/SketchSurface)| What the sketch is on (can be a plane or a face). | No |
| `start` |[`BasePath`](/docs/kcl/types/BasePath)| The starting path. | No | | `start` |[`BasePath`](/docs/kcl/types/BasePath)| The starting path. | No |
| `tags` |`object`| Tag identifiers that have been declared in this sketch. | No | | `tags` |`object`| Tag identifiers that have been declared in this sketch. | No |

View File

@ -25,8 +25,8 @@ A sketch is a collection of paths.
| Property | Type | Description | Required | | Property | Type | Description | Required |
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `type` |enum: `sketch`| | No | | `type` |enum: `sketch`| | No |
| `id` |`string`| The id of the sketch (this will change when the engine's reference to it changes. | No | | `id` |`string`| The id of the sketch (this will change when the engine's reference to it changes). | No |
| `value` |`[` [`Path`](/docs/kcl/types/Path) `]`| The paths in the sketch. | No | | `paths` |`[` [`Path`](/docs/kcl/types/Path) `]`| The paths in the sketch. | No |
| `on` |[`SketchSurface`](/docs/kcl/types/SketchSurface)| What the sketch is on (can be a plane or a face). | No | | `on` |[`SketchSurface`](/docs/kcl/types/SketchSurface)| What the sketch is on (can be a plane or a face). | No |
| `start` |[`BasePath`](/docs/kcl/types/BasePath)| The starting path. | No | | `start` |[`BasePath`](/docs/kcl/types/BasePath)| The starting path. | No |
| `tags` |`object`| Tag identifiers that have been declared in this sketch. | No | | `tags` |`object`| Tag identifiers that have been declared in this sketch. | No |

View File

@ -18,7 +18,7 @@ Engine information for a tag.
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `id` |`string`| The id of the tagged object. | No | | `id` |`string`| The id of the tagged object. | No |
| `sketch` |`string`| The sketch the tag is on. | No | | `sketch` |`string`| The sketch the tag is on. | No |
| `path` |[`BasePath`](/docs/kcl/types/BasePath)| The path the tag is on. | No | | `path` |[`Path`](/docs/kcl/types/Path)| The path the tag is on. | No |
| `surface` |[`ExtrudeSurface`](/docs/kcl/types/ExtrudeSurface)| The surface information for the tag. | No | | `surface` |[`ExtrudeSurface`](/docs/kcl/types/ExtrudeSurface)| The surface information for the tag. | No |

View File

@ -9,7 +9,7 @@ Draw a line relative to the current origin to a specified distance away
from the current position along the 'x' axis. from the current position along the 'x' axis.
```js ```js
xLine(length: number, sketch: Sketch, tag?: TagNode) -> Sketch xLine(length: number, sketch: Sketch, tag?: TagDeclarator) -> Sketch
``` ```
@ -19,7 +19,7 @@ xLine(length: number, sketch: Sketch, tag?: TagNode) -> Sketch
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `length` | `number` | | Yes | | `length` | `number` | | Yes |
| `sketch` | [`Sketch`](/docs/kcl/types/Sketch) | A sketch is a collection of paths. | Yes | | `sketch` | [`Sketch`](/docs/kcl/types/Sketch) | A sketch is a collection of paths. | Yes |
| `tag` | [`TagNode`](/docs/kcl/types/TagNode) | | No | | `tag` | [`TagDeclarator`](/docs/kcl/types#tag-declaration) | | No |
### Returns ### Returns

View File

@ -9,7 +9,7 @@ Draw a line parallel to the X axis, that ends at the given X.
E.g. if the previous line ended at (1, 1), then xLineTo(4) draws a line from (1, 1) to (4, 1) E.g. if the previous line ended at (1, 1), then xLineTo(4) draws a line from (1, 1) to (4, 1)
```js ```js
xLineTo(to: number, sketch: Sketch, tag?: TagNode) -> Sketch xLineTo(to: number, sketch: Sketch, tag?: TagDeclarator) -> Sketch
``` ```
@ -19,7 +19,7 @@ xLineTo(to: number, sketch: Sketch, tag?: TagNode) -> Sketch
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `to` | `number` | | Yes | | `to` | `number` | | Yes |
| `sketch` | [`Sketch`](/docs/kcl/types/Sketch) | A sketch is a collection of paths. | Yes | | `sketch` | [`Sketch`](/docs/kcl/types/Sketch) | A sketch is a collection of paths. | Yes |
| `tag` | [`TagNode`](/docs/kcl/types/TagNode) | | No | | `tag` | [`TagDeclarator`](/docs/kcl/types#tag-declaration) | | No |
### Returns ### Returns

View File

@ -9,7 +9,7 @@ Draw a line relative to the current origin to a specified distance away
from the current position along the 'y' axis. from the current position along the 'y' axis.
```js ```js
yLine(length: number, sketch: Sketch, tag?: TagNode) -> Sketch yLine(length: number, sketch: Sketch, tag?: TagDeclarator) -> Sketch
``` ```
@ -19,7 +19,7 @@ yLine(length: number, sketch: Sketch, tag?: TagNode) -> Sketch
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `length` | `number` | | Yes | | `length` | `number` | | Yes |
| `sketch` | [`Sketch`](/docs/kcl/types/Sketch) | A sketch is a collection of paths. | Yes | | `sketch` | [`Sketch`](/docs/kcl/types/Sketch) | A sketch is a collection of paths. | Yes |
| `tag` | [`TagNode`](/docs/kcl/types/TagNode) | | No | | `tag` | [`TagDeclarator`](/docs/kcl/types#tag-declaration) | | No |
### Returns ### Returns

View File

@ -9,7 +9,7 @@ Draw a line parallel to the Y axis, that ends at the given Y.
E.g. if the previous line ended at (1, 1), then yLineTo(4) draws a line from (1, 1) to (1, 4) E.g. if the previous line ended at (1, 1), then yLineTo(4) draws a line from (1, 1) to (1, 4)
```js ```js
yLineTo(to: number, sketch: Sketch, tag?: TagNode) -> Sketch yLineTo(to: number, sketch: Sketch, tag?: TagDeclarator) -> Sketch
``` ```
@ -19,7 +19,7 @@ yLineTo(to: number, sketch: Sketch, tag?: TagNode) -> Sketch
|----------|------|-------------|----------| |----------|------|-------------|----------|
| `to` | `number` | | Yes | | `to` | `number` | | Yes |
| `sketch` | [`Sketch`](/docs/kcl/types/Sketch) | A sketch is a collection of paths. | Yes | | `sketch` | [`Sketch`](/docs/kcl/types/Sketch) | A sketch is a collection of paths. | Yes |
| `tag` | [`TagNode`](/docs/kcl/types/TagNode) | | No | | `tag` | [`TagDeclarator`](/docs/kcl/types#tag-declaration) | | No |
### Returns ### Returns

View File

@ -136,6 +136,9 @@ test.describe('when using the file tree to', () => {
) )
await pasteCodeInEditor(kclCube) await pasteCodeInEditor(kclCube)
// TODO: We have a timeout of 1s between edits to write to disk. If you reload the page too quickly it won't write to disk.
await tronApp.page.waitForTimeout(2000)
await renameFile(fromFile, toFile) await renameFile(fromFile, toFile)
await tronApp.page.reload() await tronApp.page.reload()
@ -222,9 +225,11 @@ test.describe('when using the file tree to', () => {
) )
await pasteCodeInEditor(kclCube) await pasteCodeInEditor(kclCube)
// TODO: We have a timeout of 1s between edits to write to disk. If you reload the page too quickly it won't write to disk.
await tronApp.page.waitForTimeout(2000)
const kcl1 = 'main.kcl' const kcl1 = 'main.kcl'
const kcl2 = '2.kcl' const kcl2 = '2.kcl'
await createNewFileAndSelect(kcl2) await createNewFileAndSelect(kcl2)
const kclCylinder = await fsp.readFile( const kclCylinder = await fsp.readFile(
'src/wasm-lib/tests/executor/inputs/cylinder.kcl', 'src/wasm-lib/tests/executor/inputs/cylinder.kcl',
@ -232,6 +237,9 @@ test.describe('when using the file tree to', () => {
) )
await pasteCodeInEditor(kclCylinder) await pasteCodeInEditor(kclCylinder)
// TODO: We have a timeout of 1s between edits to write to disk. If you reload the page too quickly it won't write to disk.
await tronApp.page.waitForTimeout(2000)
await renameFile(kcl2, kcl1) await renameFile(kcl2, kcl1)
await test.step(`Postcondition: ${kcl1} still has the original content`, async () => { await test.step(`Postcondition: ${kcl1} still has the original content`, async () => {

View File

@ -55,6 +55,53 @@ test.describe('Onboarding tests', () => {
await expect(page.locator('.cm-content')).toContainText('// Shelf Bracket') await expect(page.locator('.cm-content')).toContainText('// Shelf Bracket')
}) })
test(
'Desktop: fresh onboarding executes and loads',
{ tag: '@electron' },
async ({ browserName: _ }, testInfo) => {
const { electronApp, page } = await setupElectron({
testInfo,
appSettings: {
app: {
onboardingStatus: 'incomplete',
},
},
cleanProjectDir: true,
})
const u = await getUtils(page)
const viewportSize = { width: 1200, height: 500 }
await page.setViewportSize(viewportSize)
// Locators and constants
const newProjectButton = page.getByRole('button', { name: 'New project' })
const projectLink = page.getByTestId('project-link')
await test.step(`Create a project and open to the onboarding`, async () => {
await newProjectButton.click()
await projectLink.click()
await test.step(`Ensure the engine connection works by testing the sketch button`, async () => {
await u.waitForPageLoad()
})
})
await test.step(`Ensure we see the onboarding stuff`, async () => {
// Test that the onboarding pane loaded
await expect(
page.getByText('Welcome to Modeling App! This')
).toBeVisible()
// *and* that the code is shown in the editor
await expect(page.locator('.cm-content')).toContainText(
'// Shelf Bracket'
)
})
await electronApp.close()
}
)
test('Code resets after confirmation', async ({ page }) => { test('Code resets after confirmation', async ({ page }) => {
const initialCode = `sketch001 = startSketchOn('XZ')` const initialCode = `sketch001 = startSketchOn('XZ')`

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 40 KiB

View File

@ -888,7 +888,17 @@ export async function setupElectron({
const tempSettingsFilePath = join(projectDirName, SETTINGS_FILE_NAME) const tempSettingsFilePath = join(projectDirName, SETTINGS_FILE_NAME)
const settingsOverrides = TOML.stringify( const settingsOverrides = TOML.stringify(
appSettings appSettings
? { settings: appSettings } ? {
settings: {
...TEST_SETTINGS,
...appSettings,
app: {
...TEST_SETTINGS.app,
projectDirectory: projectDirName,
...appSettings.app,
},
},
}
: { : {
settings: { settings: {
...TEST_SETTINGS, ...TEST_SETTINGS,

View File

@ -292,7 +292,7 @@ test.describe(`Testing gizmo, fixture-based`, () => {
await test.step(`Verify the camera moved`, async () => { await test.step(`Verify the camera moved`, async () => {
await scene.expectState({ await scene.expectState({
camera: { camera: {
position: [0, -23865.37, 11073.54], position: [0, -23865.37, 11073.53],
target: [0, 0, 0], target: [0, 0, 0],
}, },
}) })

View File

@ -430,7 +430,6 @@ test.describe('Testing settings', () => {
await test.step('Check color of logo changed when in modeling view', async () => { await test.step('Check color of logo changed when in modeling view', async () => {
await page.getByRole('button', { name: 'New project' }).click() await page.getByRole('button', { name: 'New project' }).click()
await page.getByTestId('project-link').first().click() await page.getByTestId('project-link').first().click()
await page.getByRole('button', { name: 'Dismiss' }).click()
await changeColor('58') await changeColor('58')
await expect(logoLink).toHaveCSS('--primary-hue', '58') await expect(logoLink).toHaveCSS('--primary-hue', '58')
}) })

2
interface.d.ts vendored
View File

@ -2,7 +2,7 @@ import fs from 'node:fs/promises'
import fsSync from 'node:fs' import fsSync from 'node:fs'
import path from 'path' import path from 'path'
import { dialog, shell } from 'electron' import { dialog, shell } from 'electron'
import { MachinesListing } from 'lib/machineManager' import { MachinesListing } from 'components/MachineManagerProvider'
type EnvFn = (value?: string) => string type EnvFn = (value?: string) => string

View File

@ -107,6 +107,13 @@
}, },
"type": "array" "type": "array"
}, },
"loaded_filament_idx": {
"description": "The currently loaded filament index.",
"format": "uint",
"minimum": 0,
"nullable": true,
"type": "integer"
},
"nozzle_diameter": { "nozzle_diameter": {
"description": "Diameter of the extrusion nozzle, in mm.", "description": "Diameter of the extrusion nozzle, in mm.",
"format": "double", "format": "double",
@ -285,6 +292,21 @@
"type" "type"
], ],
"type": "object" "type": "object"
},
{
"description": "Unknown material",
"properties": {
"type": {
"enum": [
"unknown"
],
"type": "string"
}
},
"required": [
"type"
],
"type": "object"
} }
] ]
}, },
@ -974,7 +996,7 @@
}, },
"description": "", "description": "",
"title": "machine-api", "title": "machine-api",
"version": "0.1.0" "version": "0.1.1"
}, },
"openapi": "3.0.3", "openapi": "3.0.3",
"paths": { "paths": {

View File

@ -1,6 +1,6 @@
{ {
"name": "zoo-modeling-app", "name": "zoo-modeling-app",
"version": "0.26.0", "version": "0.26.2",
"private": true, "private": true,
"productName": "Zoo Modeling App", "productName": "Zoo Modeling App",
"author": { "author": {
@ -161,7 +161,7 @@
"@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.6", "@types/mocha": "^10.0.6",
"@types/node": "^22.5.0", "@types/node": "^22.7.8",
"@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",

View File

@ -21,6 +21,7 @@ import { WasmErrBanner } from 'components/WasmErrBanner'
import { CommandBar } from 'components/CommandBar/CommandBar' import { CommandBar } from 'components/CommandBar/CommandBar'
import ModelingMachineProvider from 'components/ModelingMachineProvider' import ModelingMachineProvider from 'components/ModelingMachineProvider'
import FileMachineProvider from 'components/FileMachineProvider' import FileMachineProvider from 'components/FileMachineProvider'
import { MachineManagerProvider } from 'components/MachineManagerProvider'
import { PATHS } from 'lib/paths' import { PATHS } from 'lib/paths'
import { import {
fileLoader, fileLoader,
@ -49,6 +50,7 @@ const router = createRouter([
{ {
loader: settingsLoader, loader: settingsLoader,
id: PATHS.INDEX, id: PATHS.INDEX,
// TODO: Re-evaluate if this is true
/* Make sure auth is the outermost provider or else we will have /* Make sure auth is the outermost provider or else we will have
* inefficient re-renders, use the react profiler to see. */ * inefficient re-renders, use the react profiler to see. */
element: ( element: (
@ -57,7 +59,9 @@ const router = createRouter([
<LspProvider> <LspProvider>
<KclContextProvider> <KclContextProvider>
<AppStateProvider> <AppStateProvider>
<MachineManagerProvider>
<Outlet /> <Outlet />
</MachineManagerProvider>
</AppStateProvider> </AppStateProvider>
</KclContextProvider> </KclContextProvider>
</LspProvider> </LspProvider>

View File

@ -64,6 +64,27 @@ export type ReactCameraProperties =
const lastCmdDelay = 50 const lastCmdDelay = 50
class CameraRateLimiter {
lastSend?: Date = undefined
rateLimitMs: number = 16 //60 FPS
send = (f: () => void) => {
let now = new Date()
if (
this.lastSend === undefined ||
now.getTime() - this.lastSend.getTime() > this.rateLimitMs
) {
f()
this.lastSend = now
}
}
reset = () => {
this.lastSend = undefined
}
}
export class CameraControls { export class CameraControls {
engineCommandManager: EngineCommandManager engineCommandManager: EngineCommandManager
syncDirection: 'clientToEngine' | 'engineToClient' = 'engineToClient' syncDirection: 'clientToEngine' | 'engineToClient' = 'engineToClient'
@ -71,15 +92,15 @@ export class CameraControls {
target: Vector3 target: Vector3
domElement: HTMLCanvasElement domElement: HTMLCanvasElement
isDragging: boolean isDragging: boolean
wasDragging: boolean
mouseDownPosition: Vector2 mouseDownPosition: Vector2
mouseNewPosition: Vector2 mouseNewPosition: Vector2
rotationSpeed = 0.3 rotationSpeed = 0.3
enableRotate = true enableRotate = true
enablePan = true enablePan = true
enableZoom = true enableZoom = true
zoomDataFromLastFrame?: number = undefined moveSender: CameraRateLimiter = new CameraRateLimiter()
// holds coordinates, and interaction zoomSender: CameraRateLimiter = new CameraRateLimiter()
moveDataFromLastFrame?: [number, number, string] = undefined
lastPerspectiveFov: number = 45 lastPerspectiveFov: number = 45
pendingZoom: number | null = null pendingZoom: number | null = null
pendingRotation: Vector2 | null = null pendingRotation: Vector2 | null = null
@ -171,6 +192,36 @@ export class CameraControls {
} }
} }
doMove = (interaction: any, coordinates: any) => {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
this.engineCommandManager.sendSceneCommand({
type: 'modeling_cmd_req',
cmd: {
type: 'camera_drag_move',
interaction: interaction,
window: {
x: coordinates[0],
y: coordinates[1],
},
},
cmd_id: uuidv4(),
})
}
doZoom = (zoom: number) => {
this.handleStart()
// eslint-disable-next-line @typescript-eslint/no-floating-promises
this.engineCommandManager.sendSceneCommand({
type: 'modeling_cmd_req',
cmd: {
type: 'default_camera_zoom',
magnitude: (-1 * zoom) / window.devicePixelRatio,
},
cmd_id: uuidv4(),
})
this.handleEnd()
}
constructor( constructor(
isOrtho = false, isOrtho = false,
domElement: HTMLCanvasElement, domElement: HTMLCanvasElement,
@ -183,6 +234,7 @@ export class CameraControls {
this.target = new Vector3() this.target = new Vector3()
this.domElement = domElement this.domElement = domElement
this.isDragging = false this.isDragging = false
this.wasDragging = false
this.mouseDownPosition = new Vector2() this.mouseDownPosition = new Vector2()
this.mouseNewPosition = new Vector2() this.mouseNewPosition = new Vector2()
@ -258,49 +310,6 @@ export class CameraControls {
this.onCameraChange() this.onCameraChange()
} }
// Our stream is never more than 60fps.
// We can get away with capping our "virtual fps" to 60 then.
const FPS_VIRTUAL = 60
const doZoom = () => {
if (this.zoomDataFromLastFrame !== undefined) {
this.handleStart()
// eslint-disable-next-line @typescript-eslint/no-floating-promises
this.engineCommandManager.sendSceneCommand({
type: 'modeling_cmd_req',
cmd: {
type: 'default_camera_zoom',
magnitude:
(-1 * this.zoomDataFromLastFrame) / window.devicePixelRatio,
},
cmd_id: uuidv4(),
})
this.handleEnd()
}
this.zoomDataFromLastFrame = undefined
}
setInterval(doZoom, 1000 / FPS_VIRTUAL)
const doMove = () => {
if (this.moveDataFromLastFrame !== undefined) {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
this.engineCommandManager.sendSceneCommand({
type: 'modeling_cmd_req',
cmd: {
type: 'camera_drag_move',
interaction: this.moveDataFromLastFrame[2] as any,
window: {
x: this.moveDataFromLastFrame[0],
y: this.moveDataFromLastFrame[1],
},
},
cmd_id: uuidv4(),
})
}
this.moveDataFromLastFrame = undefined
}
setInterval(doMove, 1000 / FPS_VIRTUAL)
setTimeout(() => { setTimeout(() => {
this.engineCommandManager.subscribeTo({ this.engineCommandManager.subscribeTo({
event: 'camera_drag_end', event: 'camera_drag_end',
@ -356,6 +365,8 @@ export class CameraControls {
onMouseDown = (event: PointerEvent) => { onMouseDown = (event: PointerEvent) => {
this.domElement.setPointerCapture(event.pointerId) this.domElement.setPointerCapture(event.pointerId)
this.isDragging = true this.isDragging = true
// Reset the wasDragging flag to false when starting a new drag
this.wasDragging = false
this.mouseDownPosition.set(event.clientX, event.clientY) this.mouseDownPosition.set(event.clientX, event.clientY)
let interaction = this.getInteractionType(event) let interaction = this.getInteractionType(event)
if (interaction === 'none') return if (interaction === 'none') return
@ -385,11 +396,18 @@ export class CameraControls {
const interaction = this.getInteractionType(event) const interaction = this.getInteractionType(event)
if (interaction === 'none') return if (interaction === 'none') return
// If there's a valid interaction and the mouse is moving,
// our past (and current) interaction was a drag.
this.wasDragging = true
if (this.syncDirection === 'engineToClient') { if (this.syncDirection === 'engineToClient') {
this.moveDataFromLastFrame = [event.clientX, event.clientY, interaction] this.moveSender.send(() => {
this.doMove(interaction, [event.clientX, event.clientY])
})
return return
} }
// else "clientToEngine" (Sketch Mode) or forceUpdate
// Implement camera movement logic here based on deltaMove // Implement camera movement logic here based on deltaMove
// For example, for rotating the camera around the target: // For example, for rotating the camera around the target:
if (interaction === 'rotate') { if (interaction === 'rotate') {
@ -418,6 +436,9 @@ export class CameraControls {
* under the cursor. This recently moved from being handled in App.tsx. * under the cursor. This recently moved from being handled in App.tsx.
* This might not be the right spot, but it is more consolidated. * This might not be the right spot, but it is more consolidated.
*/ */
// Clear any previous drag state
this.wasDragging = false
if (this.syncDirection === 'engineToClient') { if (this.syncDirection === 'engineToClient') {
const newCmdId = uuidv4() const newCmdId = uuidv4()
@ -459,7 +480,9 @@ export class CameraControls {
if (this.syncDirection === 'engineToClient') { if (this.syncDirection === 'engineToClient') {
if (interaction === 'zoom') { if (interaction === 'zoom') {
this.zoomDataFromLastFrame = event.deltaY this.zoomSender.send(() => {
this.doZoom(event.deltaY)
})
} else { } else {
// This case will get handled when we add pan and rotate using Apple trackpad. // This case will get handled when we add pan and rotate using Apple trackpad.
console.error( console.error(

View File

@ -44,7 +44,6 @@ import {
import { ActionButton } from 'components/ActionButton' import { ActionButton } from 'components/ActionButton'
import { err, reportRejection, trap } from 'lib/trap' import { err, reportRejection, trap } from 'lib/trap'
import { useCommandsContext } from 'hooks/useCommandsContext' import { useCommandsContext } from 'hooks/useCommandsContext'
import { UnboxedNode } from 'wasm-lib/kcl/bindings/UnboxedNode'
function useShouldHideScene(): { hideClient: boolean; hideServer: boolean } { function useShouldHideScene(): { hideClient: boolean; hideServer: boolean } {
const [isCamMoving, setIsCamMoving] = useState(false) const [isCamMoving, setIsCamMoving] = useState(false)
@ -202,7 +201,7 @@ const Overlay = ({
let xAlignment = overlay.angle < 0 ? '0%' : '-100%' let xAlignment = overlay.angle < 0 ? '0%' : '-100%'
let yAlignment = overlay.angle < -90 || overlay.angle >= 90 ? '0%' : '-100%' let yAlignment = overlay.angle < -90 || overlay.angle >= 90 ? '0%' : '-100%'
const _node1 = getNodeFromPath<UnboxedNode<CallExpression>>( const _node1 = getNodeFromPath<CallExpression>(
kclManager.ast, kclManager.ast,
overlay.pathToNode, overlay.pathToNode,
'CallExpression' 'CallExpression'
@ -382,7 +381,7 @@ export async function deleteSegment({
pathToNode: PathToNode pathToNode: PathToNode
sketchDetails: SketchDetails | null sketchDetails: SketchDetails | null
}) { }) {
let modifiedAst: UnboxedNode<Program> | Error = kclManager.ast let modifiedAst: Program | Error = kclManager.ast
const dependentRanges = findUsesOfTagInPipe(modifiedAst, pathToNode) const dependentRanges = findUsesOfTagInPipe(modifiedAst, pathToNode)
const shouldContinueSegDelete = dependentRanges.length const shouldContinueSegDelete = dependentRanges.length

View File

@ -92,7 +92,6 @@ import { err, reportRejection, trap } from 'lib/trap'
import { CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer' import { CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer'
import { Point3d } from 'wasm-lib/kcl/bindings/Point3d' import { Point3d } from 'wasm-lib/kcl/bindings/Point3d'
import { SegmentInputs } from 'lang/std/stdTypes' import { SegmentInputs } from 'lang/std/stdTypes'
import { UnboxedNode } from 'wasm-lib/kcl/bindings/UnboxedNode'
type DraftSegment = 'line' | 'tangentialArcTo' type DraftSegment = 'line' | 'tangentialArcTo'
@ -339,6 +338,11 @@ export class SceneEntities {
sceneInfra.setCallbacks({ sceneInfra.setCallbacks({
onClick: async (args) => { onClick: async (args) => {
if (!args) return if (!args) return
// If there is a valid camera interaction that matches, do that instead
const interaction = sceneInfra.camControls.getInteractionType(
args.mouseEvent
)
if (interaction !== 'none') return
if (args.mouseEvent.which !== 1) return if (args.mouseEvent.which !== 1) return
const { intersectionPoint } = args const { intersectionPoint } = args
if (!intersectionPoint?.twoD || !sketchDetails?.sketchPathToNode) return if (!intersectionPoint?.twoD || !sketchDetails?.sketchPathToNode) return
@ -370,14 +374,14 @@ export class SceneEntities {
selectionRanges, selectionRanges,
}: { }: {
sketchPathToNode: PathToNode sketchPathToNode: PathToNode
maybeModdedAst: UnboxedNode<Program> maybeModdedAst: Program
draftExpressionsIndices?: { start: number; end: number } draftExpressionsIndices?: { start: number; end: number }
forward: [number, number, number] forward: [number, number, number]
up: [number, number, number] up: [number, number, number]
position?: [number, number, number] position?: [number, number, number]
selectionRanges?: Selections selectionRanges?: Selections
}): Promise<{ }): Promise<{
truncatedAst: UnboxedNode<Program> truncatedAst: Program
programMemoryOverride: ProgramMemory programMemoryOverride: ProgramMemory
sketch: Sketch sketch: Sketch
variableDeclarationName: string variableDeclarationName: string
@ -408,7 +412,7 @@ export class SceneEntities {
if (err(sketch)) return Promise.reject(sketch) if (err(sketch)) return Promise.reject(sketch)
if (!sketch) return Promise.reject('sketch not found') if (!sketch) return Promise.reject('sketch not found')
if (!isArray(sketch?.value)) if (!isArray(sketch?.paths))
return { return {
truncatedAst, truncatedAst,
programMemoryOverride, programMemoryOverride,
@ -436,7 +440,7 @@ export class SceneEntities {
maybeModdedAst, maybeModdedAst,
sketch.start.__geoMeta.sourceRange sketch.start.__geoMeta.sourceRange
) )
if (sketch?.value?.[0]?.type !== 'Circle') { if (sketch?.paths?.[0]?.type !== 'Circle') {
const _profileStart = createProfileStartHandle({ const _profileStart = createProfileStartHandle({
from: sketch.start.from, from: sketch.start.from,
id: sketch.start.__geoMeta.id, id: sketch.start.__geoMeta.id,
@ -452,16 +456,16 @@ export class SceneEntities {
this.activeSegments[JSON.stringify(segPathToNode)] = _profileStart this.activeSegments[JSON.stringify(segPathToNode)] = _profileStart
} }
const callbacks: (() => SegmentOverlayPayload | null)[] = [] const callbacks: (() => SegmentOverlayPayload | null)[] = []
sketch.value.forEach((segment, index) => { sketch.paths.forEach((segment, index) => {
let segPathToNode = getNodePathFromSourceRange( let segPathToNode = getNodePathFromSourceRange(
maybeModdedAst, maybeModdedAst,
segment.__geoMeta.sourceRange segment.__geoMeta.sourceRange
) )
if ( if (
draftExpressionsIndices && draftExpressionsIndices &&
(sketch.value[index - 1] || sketch.start) (sketch.paths[index - 1] || sketch.start)
) { ) {
const previousSegment = sketch.value[index - 1] || sketch.start const previousSegment = sketch.paths[index - 1] || sketch.start
const previousSegmentPathToNode = getNodePathFromSourceRange( const previousSegmentPathToNode = getNodePathFromSourceRange(
maybeModdedAst, maybeModdedAst,
previousSegment.__geoMeta.sourceRange previousSegment.__geoMeta.sourceRange
@ -512,7 +516,7 @@ export class SceneEntities {
to: segment.to, to: segment.to,
} }
const result = initSegment({ const result = initSegment({
prevSegment: sketch.value[index - 1], prevSegment: sketch.paths[index - 1],
callExpName, callExpName,
input, input,
id: segment.__geoMeta.id, id: segment.__geoMeta.id,
@ -562,7 +566,7 @@ export class SceneEntities {
} }
updateAstAndRejigSketch = async ( updateAstAndRejigSketch = async (
sketchPathToNode: PathToNode, sketchPathToNode: PathToNode,
modifiedAst: UnboxedNode<Program> | Error, modifiedAst: Program | Error,
forward: [number, number, number], forward: [number, number, number],
up: [number, number, number], up: [number, number, number],
origin: [number, number, number] origin: [number, number, number]
@ -611,9 +615,9 @@ export class SceneEntities {
variableDeclarationName variableDeclarationName
) )
if (err(sg)) return Promise.reject(sg) if (err(sg)) return Promise.reject(sg)
const lastSeg = sg?.value?.slice(-1)[0] || sg.start const lastSeg = sg?.paths?.slice(-1)[0] || sg.start
const index = sg.value.length // because we've added a new segment that's not in the memory yet, no need for `-1` const index = sg.paths.length // because we've added a new segment that's not in the memory yet, no need for `-1`
const mod = addNewSketchLn({ const mod = addNewSketchLn({
node: _ast, node: _ast,
programMemory: kclManager.programMemory, programMemory: kclManager.programMemory,
@ -646,7 +650,13 @@ export class SceneEntities {
sceneInfra.setCallbacks({ sceneInfra.setCallbacks({
onClick: async (args) => { onClick: async (args) => {
if (!args) return if (!args) return
// If there is a valid camera interaction that matches, do that instead
const interaction = sceneInfra.camControls.getInteractionType(
args.mouseEvent
)
if (interaction !== 'none') return
if (args.mouseEvent.which !== 1) return if (args.mouseEvent.which !== 1) return
const { intersectionPoint } = args const { intersectionPoint } = args
let intersection2d = intersectionPoint?.twoD let intersection2d = intersectionPoint?.twoD
const profileStart = args.intersects const profileStart = args.intersects
@ -655,7 +665,7 @@ export class SceneEntities {
let modifiedAst let modifiedAst
if (profileStart) { if (profileStart) {
const lastSegment = sketch.value.slice(-1)[0] const lastSegment = sketch.paths.slice(-1)[0]
modifiedAst = addCallExpressionsToPipe({ modifiedAst = addCallExpressionsToPipe({
node: kclManager.ast, node: kclManager.ast,
programMemory: kclManager.programMemory, programMemory: kclManager.programMemory,
@ -687,7 +697,7 @@ export class SceneEntities {
}) })
if (trap(modifiedAst)) return Promise.reject(modifiedAst) if (trap(modifiedAst)) return Promise.reject(modifiedAst)
} else if (intersection2d) { } else if (intersection2d) {
const lastSegment = sketch.value.slice(-1)[0] const lastSegment = sketch.paths.slice(-1)[0]
const tmp = addNewSketchLn({ const tmp = addNewSketchLn({
node: kclManager.ast, node: kclManager.ast,
programMemory: kclManager.programMemory, programMemory: kclManager.programMemory,
@ -736,7 +746,6 @@ export class SceneEntities {
}, },
}) })
}, },
...this.mouseEnterLeaveCallbacks(),
}) })
} }
setupDraftRectangle = async ( setupDraftRectangle = async (
@ -818,7 +827,7 @@ export class SceneEntities {
variableDeclarationName variableDeclarationName
) )
if (err(sketch)) return Promise.reject(sketch) if (err(sketch)) return Promise.reject(sketch)
const sgPaths = sketch.value const sgPaths = sketch.paths
const orthoFactor = orthoScale(sceneInfra.camControls.camera) const orthoFactor = orthoScale(sceneInfra.camControls.camera)
this.updateSegment(sketch.start, 0, 0, _ast, orthoFactor, sketch) this.updateSegment(sketch.start, 0, 0, _ast, orthoFactor, sketch)
@ -827,6 +836,11 @@ export class SceneEntities {
) )
}, },
onClick: async (args) => { onClick: async (args) => {
// If there is a valid camera interaction that matches, do that instead
const interaction = sceneInfra.camControls.getInteractionType(
args.mouseEvent
)
if (interaction !== 'none') return
// Commit the rectangle to the full AST/code and return to sketch.idle // Commit the rectangle to the full AST/code and return to sketch.idle
const cornerPoint = args.intersectionPoint?.twoD const cornerPoint = args.intersectionPoint?.twoD
if (!cornerPoint || args.mouseEvent.button !== 0) return if (!cornerPoint || args.mouseEvent.button !== 0) return
@ -869,7 +883,7 @@ export class SceneEntities {
variableDeclarationName variableDeclarationName
) )
if (err(sketch)) return if (err(sketch)) return
const sgPaths = sketch.value const sgPaths = sketch.paths
const orthoFactor = orthoScale(sceneInfra.camControls.camera) const orthoFactor = orthoScale(sceneInfra.camControls.camera)
// Update the starting segment of the THREEjs scene // Update the starting segment of the THREEjs scene
@ -986,7 +1000,7 @@ export class SceneEntities {
variableDeclarationName variableDeclarationName
) )
if (err(sketch)) return if (err(sketch)) return
const sgPaths = sketch.value const sgPaths = sketch.paths
const orthoFactor = orthoScale(sceneInfra.camControls.camera) const orthoFactor = orthoScale(sceneInfra.camControls.camera)
this.updateSegment(sketch.start, 0, 0, _ast, orthoFactor, sketch) this.updateSegment(sketch.start, 0, 0, _ast, orthoFactor, sketch)
@ -995,6 +1009,11 @@ export class SceneEntities {
) )
}, },
onClick: async (args) => { onClick: async (args) => {
// If there is a valid camera interaction that matches, do that instead
const interaction = sceneInfra.camControls.getInteractionType(
args.mouseEvent
)
if (interaction !== 'none') return
// Commit the rectangle to the full AST/code and return to sketch.idle // Commit the rectangle to the full AST/code and return to sketch.idle
const cornerPoint = args.intersectionPoint?.twoD const cornerPoint = args.intersectionPoint?.twoD
if (!cornerPoint || args.mouseEvent.button !== 0) return if (!cornerPoint || args.mouseEvent.button !== 0) return
@ -1106,7 +1125,7 @@ export class SceneEntities {
const pipeIndex = pathToNode[pathToNodeIndex + 1][0] as number const pipeIndex = pathToNode[pathToNodeIndex + 1][0] as number
if (addingNewSegmentStatus === 'nothing') { if (addingNewSegmentStatus === 'nothing') {
const prevSegment = sketch.value[pipeIndex - 2] const prevSegment = sketch.paths[pipeIndex - 2]
const mod = addNewSketchLn({ const mod = addNewSketchLn({
node: kclManager.ast, node: kclManager.ast,
programMemory: kclManager.programMemory, programMemory: kclManager.programMemory,
@ -1158,6 +1177,11 @@ export class SceneEntities {
}, },
onMove: () => {}, onMove: () => {},
onClick: (args) => { onClick: (args) => {
// If there is a valid camera interaction that matches, do that instead
const interaction = sceneInfra.camControls.getInteractionType(
args.mouseEvent
)
if (interaction !== 'none') return
if (args?.mouseEvent.which !== 1) return if (args?.mouseEvent.which !== 1) return
if (!args || !args.selected) { if (!args || !args.selected) {
sceneInfra.modelingSend({ sceneInfra.modelingSend({
@ -1178,7 +1202,7 @@ export class SceneEntities {
} }
prepareTruncatedMemoryAndAst = ( prepareTruncatedMemoryAndAst = (
sketchPathToNode: PathToNode, sketchPathToNode: PathToNode,
ast?: UnboxedNode<Program>, ast?: Program,
draftSegment?: DraftSegment draftSegment?: DraftSegment
) => ) =>
prepareTruncatedMemoryAndAst( prepareTruncatedMemoryAndAst(
@ -1199,7 +1223,7 @@ export class SceneEntities {
sketchPathToNode: PathToNode sketchPathToNode: PathToNode
intersects: Intersection<Object3D<Object3DEventMap>>[] intersects: Intersection<Object3D<Object3DEventMap>>[]
draftInfo?: { draftInfo?: {
truncatedAst: UnboxedNode<Program> truncatedAst: Program
programMemoryOverride: ProgramMemory programMemoryOverride: ProgramMemory
variableDeclarationName: string variableDeclarationName: string
} }
@ -1235,7 +1259,7 @@ export class SceneEntities {
const dragTo: [number, number] = [intersection2d.x, intersection2d.y] const dragTo: [number, number] = [intersection2d.x, intersection2d.y]
let modifiedAst = draftInfo ? draftInfo.truncatedAst : { ...kclManager.ast } let modifiedAst = draftInfo ? draftInfo.truncatedAst : { ...kclManager.ast }
const _node = getNodeFromPath<UnboxedNode<CallExpression>>( const _node = getNodeFromPath<CallExpression>(
modifiedAst, modifiedAst,
pathToNode, pathToNode,
'CallExpression' 'CallExpression'
@ -1247,7 +1271,7 @@ export class SceneEntities {
let modded: let modded:
| { | {
modifiedAst: UnboxedNode<Program> modifiedAst: Program
pathToNode: PathToNode pathToNode: PathToNode
} }
| Error | Error
@ -1346,7 +1370,7 @@ export class SceneEntities {
} }
if (!sketch) return if (!sketch) return
const sgPaths = sketch.value const sgPaths = sketch.paths
const orthoFactor = orthoScale(sceneInfra.camControls.camera) const orthoFactor = orthoScale(sceneInfra.camControls.camera)
this.updateSegment( this.updateSegment(
@ -1394,7 +1418,7 @@ export class SceneEntities {
modifiedAst, modifiedAst,
segment.__geoMeta.sourceRange segment.__geoMeta.sourceRange
) )
const sgPaths = sketch.value const sgPaths = sketch.paths
const originalPathToNodeStr = JSON.stringify(segPathToNode) const originalPathToNodeStr = JSON.stringify(segPathToNode)
segPathToNode[1][0] = varDecIndex segPathToNode[1][0] = varDecIndex
const pathToNodeStr = JSON.stringify(segPathToNode) const pathToNodeStr = JSON.stringify(segPathToNode)
@ -1542,7 +1566,7 @@ export class SceneEntities {
if (parent?.userData?.pathToNode) { if (parent?.userData?.pathToNode) {
const updatedAst = parse(recast(kclManager.ast)) const updatedAst = parse(recast(kclManager.ast))
if (trap(updatedAst)) return if (trap(updatedAst)) return
const _node = getNodeFromPath<UnboxedNode<CallExpression>>( const _node = getNodeFromPath<CallExpression>(
updatedAst, updatedAst,
parent.userData.pathToNode, parent.userData.pathToNode,
'CallExpression' 'CallExpression'
@ -1677,12 +1701,12 @@ export type DefaultPlaneStr = 'XY' | 'XZ' | 'YZ' | '-XY' | '-XZ' | '-YZ'
function prepareTruncatedMemoryAndAst( function prepareTruncatedMemoryAndAst(
sketchPathToNode: PathToNode, sketchPathToNode: PathToNode,
ast: UnboxedNode<Program>, ast: Program,
programMemory: ProgramMemory, programMemory: ProgramMemory,
draftSegment?: DraftSegment draftSegment?: DraftSegment
): ):
| { | {
truncatedAst: UnboxedNode<Program> truncatedAst: Program
programMemoryOverride: ProgramMemory programMemoryOverride: ProgramMemory
variableDeclarationName: string variableDeclarationName: string
} }
@ -1690,7 +1714,7 @@ function prepareTruncatedMemoryAndAst(
const bodyIndex = Number(sketchPathToNode?.[1]?.[0]) || 0 const bodyIndex = Number(sketchPathToNode?.[1]?.[0]) || 0
const _ast = structuredClone(ast) const _ast = structuredClone(ast)
const _node = getNodeFromPath<UnboxedNode<VariableDeclaration>>( const _node = getNodeFromPath<VariableDeclaration>(
_ast, _ast,
sketchPathToNode || [], sketchPathToNode || [],
'VariableDeclaration' 'VariableDeclaration'
@ -1702,7 +1726,7 @@ function prepareTruncatedMemoryAndAst(
variableDeclarationName variableDeclarationName
) )
if (err(sg)) return sg if (err(sg)) return sg
const lastSeg = sg?.value.slice(-1)[0] const lastSeg = sg?.paths.slice(-1)[0]
if (draftSegment) { if (draftSegment) {
// truncatedAst needs to setup with another segment at the end // truncatedAst needs to setup with another segment at the end
let newSegment let newSegment
@ -1740,15 +1764,15 @@ function prepareTruncatedMemoryAndAst(
).body.slice(-1)[0].start = lastPipeItem.start ).body.slice(-1)[0].start = lastPipeItem.start
_ast.end = lastPipeItem.end _ast.end = lastPipeItem.end
const varDec = _ast.body[bodyIndex] as UnboxedNode<VariableDeclaration> const varDec = _ast.body[bodyIndex] as VariableDeclaration
varDec.end = lastPipeItem.end varDec.end = lastPipeItem.end
const declarator = varDec.declarations[0] const declarator = varDec.declarations[0]
declarator.end = lastPipeItem.end declarator.end = lastPipeItem.end
const init = declarator.init as UnboxedNode<PipeExpression> const init = declarator.init as PipeExpression
init.end = lastPipeItem.end init.end = lastPipeItem.end
init.body.slice(-1)[0].end = lastPipeItem.end init.body.slice(-1)[0].end = lastPipeItem.end
} }
const truncatedAst: UnboxedNode<Program> = { const truncatedAst: Program = {
..._ast, ..._ast,
body: [structuredClone(_ast.body[bodyIndex])], body: [structuredClone(_ast.body[bodyIndex])],
} }

View File

@ -213,7 +213,7 @@ export class SceneInfra {
to: Coords2d to: Coords2d
angle?: number angle?: number
}): SegmentOverlayPayload | null { }): SegmentOverlayPayload | null {
if (group.userData.pathToNode && arrowGroup) { if (!group.userData.draft && group.userData.pathToNode && arrowGroup) {
const vector = new Vector3(0, 0, 0) const vector = new Vector3(0, 0, 0)
// Get the position of the object3D in world space // Get the position of the object3D in world space

View File

@ -58,7 +58,7 @@ import { err } from 'lib/trap'
interface CreateSegmentArgs { interface CreateSegmentArgs {
input: SegmentInputs input: SegmentInputs
prevSegment: Sketch['value'][number] prevSegment: Sketch['paths'][number]
id: string id: string
pathToNode: PathToNode pathToNode: PathToNode
isDraftSegment?: boolean isDraftSegment?: boolean
@ -72,7 +72,7 @@ interface CreateSegmentArgs {
interface UpdateSegmentArgs { interface UpdateSegmentArgs {
input: SegmentInputs input: SegmentInputs
prevSegment: Sketch['value'][number] prevSegment: Sketch['paths'][number]
group: Group group: Group
sceneInfra: SceneInfra sceneInfra: SceneInfra
scale?: number scale?: number
@ -147,6 +147,7 @@ class StraightSegment implements SegmentUtils {
segmentGroup.name = STRAIGHT_SEGMENT segmentGroup.name = STRAIGHT_SEGMENT
segmentGroup.userData = { segmentGroup.userData = {
type: STRAIGHT_SEGMENT, type: STRAIGHT_SEGMENT,
draft: isDraftSegment,
id, id,
from, from,
to, to,
@ -347,6 +348,7 @@ class TangentialArcToSegment implements SegmentUtils {
mesh.name = meshName mesh.name = meshName
group.userData = { group.userData = {
type: TANGENTIAL_ARC_TO_SEGMENT, type: TANGENTIAL_ARC_TO_SEGMENT,
draft: isDraftSegment,
id, id,
from, from,
to, to,
@ -515,11 +517,18 @@ class CircleSegment implements SegmentUtils {
const meshType = isDraftSegment ? CIRCLE_SEGMENT_DASH : CIRCLE_SEGMENT_BODY const meshType = isDraftSegment ? CIRCLE_SEGMENT_DASH : CIRCLE_SEGMENT_BODY
const arrowGroup = createArrowhead(scale, theme, color) const arrowGroup = createArrowhead(scale, theme, color)
const circleCenterGroup = createCircleCenterHandle(scale, theme, color) const circleCenterGroup = createCircleCenterHandle(scale, theme, color)
// A radius indicator that appears from the center to the perimeter
const radiusIndicatorGroup = createLengthIndicator({
from: center,
to: [center[0] + radius, center[1]],
scale,
})
arcMesh.userData.type = meshType arcMesh.userData.type = meshType
arcMesh.name = meshType arcMesh.name = meshType
group.userData = { group.userData = {
type: CIRCLE_SEGMENT, type: CIRCLE_SEGMENT,
draft: isDraftSegment,
id, id,
from, from,
radius, radius,
@ -532,7 +541,7 @@ class CircleSegment implements SegmentUtils {
} }
group.name = CIRCLE_SEGMENT group.name = CIRCLE_SEGMENT
group.add(arcMesh, arrowGroup, circleCenterGroup) group.add(arcMesh, arrowGroup, circleCenterGroup, radiusIndicatorGroup)
const updateOverlaysCallback = this.update({ const updateOverlaysCallback = this.update({
prevSegment, prevSegment,
input, input,
@ -564,6 +573,9 @@ class CircleSegment implements SegmentUtils {
group.userData.radius = radius group.userData.radius = radius
group.userData.prevSegment = prevSegment group.userData.prevSegment = prevSegment
const arrowGroup = group.getObjectByName(ARROWHEAD) as Group const arrowGroup = group.getObjectByName(ARROWHEAD) as Group
const radiusLengthIndicator = group.getObjectByName(
SEGMENT_LENGTH_LABEL
) as Group
const circleCenterHandle = group.getObjectByName( const circleCenterHandle = group.getObjectByName(
CIRCLE_CENTER_HANDLE CIRCLE_CENTER_HANDLE
) as Group ) as Group
@ -581,11 +593,14 @@ class CircleSegment implements SegmentUtils {
} }
if (arrowGroup) { if (arrowGroup) {
arrowGroup.position.set( // The arrowhead is placed at the perimeter of the circle,
center[0] + Math.cos(Math.PI / 4) * radius, // pointing up and to the right
center[1] + Math.sin(Math.PI / 4) * radius, const arrowPoint = {
0 x: center[0] + Math.cos(Math.PI / 4) * radius,
) y: center[1] + Math.sin(Math.PI / 4) * radius,
}
arrowGroup.position.set(arrowPoint.x, arrowPoint.y, 0)
const arrowheadAngle = Math.PI / 4 const arrowheadAngle = Math.PI / 4
arrowGroup.quaternion.setFromUnitVectors( arrowGroup.quaternion.setFromUnitVectors(
@ -596,6 +611,31 @@ class CircleSegment implements SegmentUtils {
arrowGroup.visible = isHandlesVisible arrowGroup.visible = isHandlesVisible
} }
if (radiusLengthIndicator) {
// The radius indicator is placed at the midpoint of the radius,
// at a 45 degree CCW angle from the positive X-axis
const indicatorPoint = {
x: center[0] + (Math.cos(Math.PI / 4) * radius) / 2,
y: center[1] + (Math.sin(Math.PI / 4) * radius) / 2,
}
const labelWrapper = radiusLengthIndicator.getObjectByName(
SEGMENT_LENGTH_LABEL_TEXT
) as CSS2DObject
const labelWrapperElem = labelWrapper.element as HTMLDivElement
const label = labelWrapperElem.children[0] as HTMLParagraphElement
label.innerText = `${roundOff(radius)}`
label.classList.add(SEGMENT_LENGTH_LABEL_TEXT)
const isPlaneBackFace = center[0] > indicatorPoint.x
label.style.setProperty(
'--degree',
`${isPlaneBackFace ? '45' : '-45'}deg`
)
label.style.setProperty('--x', `0px`)
label.style.setProperty('--y', `0px`)
labelWrapper.position.set(indicatorPoint.x, indicatorPoint.y, 0)
radiusLengthIndicator.visible = isHandlesVisible
}
if (circleCenterHandle) { if (circleCenterHandle) {
circleCenterHandle.position.set(center[0], center[1], 0) circleCenterHandle.position.set(center[0], center[1], 0)
circleCenterHandle.scale.set(scale, scale, scale) circleCenterHandle.scale.set(scale, scale, scale)

View File

@ -140,6 +140,13 @@ const FileTreeItem = ({
async (eventType, path) => { async (eventType, path) => {
// Don't try to read a file that was removed. // Don't try to read a file that was removed.
if (isCurrentFile && eventType !== 'unlink') { if (isCurrentFile && eventType !== 'unlink') {
// Prevents a cyclic read / write causing editor problems such as
// misplaced cursor positions.
if (codeManager.writeCausedByAppCheckedInFileTreeFileSystemWatcher) {
codeManager.writeCausedByAppCheckedInFileTreeFileSystemWatcher = false
return
}
let code = await window.electron.readFile(path, { encoding: 'utf-8' }) let code = await window.electron.readFile(path, { encoding: 'utf-8' })
code = normalizeLineEndings(code) code = normalizeLineEndings(code)
codeManager.updateCodeStateEditor(code) codeManager.updateCodeStateEditor(code)
@ -488,6 +495,12 @@ export const FileTreeInner = ({
// Refresh the file tree when there are changes. // Refresh the file tree when there are changes.
useFileSystemWatcher( useFileSystemWatcher(
async (eventType, path) => { async (eventType, path) => {
// Our other watcher races with this watcher on the current file changes,
// so we need to stop this one from reacting at all, otherwise Bad Things
// Happen™.
const isCurrentFile = loaderData.file?.path === path
const hasChanged = eventType === 'change'
if (isCurrentFile && hasChanged) return
fileSend({ type: 'Refresh' }) fileSend({ type: 'Refresh' })
}, },
[loaderData?.project?.path, fileContext.selectedDirectory.path].filter( [loaderData?.project?.path, fileContext.selectedDirectory.path].filter(

View File

@ -23,6 +23,7 @@ export function LowerRightControls({
}) { }) {
const location = useLocation() const location = useLocation()
const filePath = useAbsoluteFilePath() const filePath = useAbsoluteFilePath()
const linkOverrideClassName = const linkOverrideClassName =
'!text-chalkboard-70 hover:!text-chalkboard-80 dark:!text-chalkboard-40 dark:hover:!text-chalkboard-30' '!text-chalkboard-70 hover:!text-chalkboard-80 dark:!text-chalkboard-40 dark:hover:!text-chalkboard-30'

View File

@ -0,0 +1,123 @@
import { createContext, useEffect, useState } from 'react'
import { engineCommandManager } from 'lib/singletons'
import { CommandsContext } from 'components/CommandBar/CommandBarProvider'
import { isDesktop } from 'lib/isDesktop'
import { components } from 'lib/machine-api'
import { reportRejection } from 'lib/trap'
import { toSync } from 'lib/utils'
export type MachinesListing = Array<
components['schemas']['MachineInfoResponse']
>
export interface MachineManager {
machines: MachinesListing
machineApiIp: string | null
currentMachine: components['schemas']['MachineInfoResponse'] | null
noMachinesReason: () => string | undefined
setCurrentMachine: (
m: components['schemas']['MachineInfoResponse'] | null
) => void
}
export const MachineManagerContext = createContext<MachineManager>({
machines: [],
machineApiIp: null,
currentMachine: null,
setCurrentMachine: (
_: components['schemas']['MachineInfoResponse'] | null
) => {},
noMachinesReason: () => undefined,
})
export const MachineManagerProvider = ({
children,
}: {
children: React.ReactNode
}) => {
const [machines, setMachines] = useState<MachinesListing>([])
const [machineApiIp, setMachineApiIp] = useState<string | null>(null)
const [currentMachine, setCurrentMachine] = useState<
components['schemas']['MachineInfoResponse'] | null
>(null)
const commandBarActor = CommandsContext.useActorRef()
// Get the reason message for why there are no machines.
const noMachinesReason = (): string | undefined => {
if (machines.length > 0) {
return undefined
}
if (machineApiIp === null) {
return 'Machine API server was not discovered'
}
return 'Machine API server was discovered, but no machines are available'
}
useEffect(() => {
if (!isDesktop()) return
const update = async () => {
const _machineApiIp = await window.electron.getMachineApiIp()
if (_machineApiIp === null) return
setMachineApiIp(_machineApiIp)
const _machines = await window.electron.listMachines(_machineApiIp)
setMachines(_machines)
}
// Start a background job to update the machines every ten seconds.
// If MDNS is already watching, this timeout will wait until it's done to trigger the
// finding again.
let timeoutId: ReturnType<typeof setTimeout> | undefined = undefined
const timeoutLoop = () => {
clearTimeout(timeoutId)
timeoutId = setTimeout(
toSync(async () => {
await update()
timeoutLoop()
}, reportRejection),
1000
)
}
timeoutLoop()
update().catch(reportRejection)
}, [])
// Update engineCommandManager's copy of this data.
useEffect(() => {
const machineManagerNext = {
machines,
machineApiIp,
currentMachine,
noMachinesReason,
setCurrentMachine,
}
engineCommandManager.machineManager = machineManagerNext
commandBarActor.send({
type: 'Set machine manager',
data: machineManagerNext,
})
}, [machines, machineApiIp, currentMachine])
return (
<MachineManagerContext.Provider
value={{
machines,
machineApiIp,
currentMachine,
setCurrentMachine,
noMachinesReason,
}}
>
{' '}
{children}{' '}
</MachineManagerContext.Provider>
)
}

View File

@ -1,5 +1,11 @@
import { useMachine } from '@xstate/react' import { useMachine } from '@xstate/react'
import React, { createContext, useEffect, useMemo, useRef } from 'react' import React, {
createContext,
useEffect,
useMemo,
useRef,
useContext,
} from 'react'
import { import {
Actor, Actor,
AnyStateMachine, AnyStateMachine,
@ -28,7 +34,7 @@ import {
editorManager, editorManager,
sceneEntitiesManager, sceneEntitiesManager,
} from 'lib/singletons' } from 'lib/singletons'
import { machineManager } from 'lib/machineManager' import { MachineManagerContext } from 'components/MachineManagerProvider'
import { useHotkeys } from 'react-hotkeys-hook' import { useHotkeys } from 'react-hotkeys-hook'
import { applyConstraintHorzVertDistance } from './Toolbar/SetHorzVertDistance' import { applyConstraintHorzVertDistance } from './Toolbar/SetHorzVertDistance'
import { import {
@ -69,7 +75,7 @@ import { exportFromEngine } from 'lib/exportFromEngine'
import { Models } from '@kittycad/lib/dist/types/src' import { Models } from '@kittycad/lib/dist/types/src'
import toast from 'react-hot-toast' import toast from 'react-hot-toast'
import { EditorSelection, Transaction } from '@codemirror/state' import { EditorSelection, Transaction } from '@codemirror/state'
import { useNavigate, useSearchParams } from 'react-router-dom' import { useLoaderData, useNavigate, useSearchParams } from 'react-router-dom'
import { letEngineAnimateAndSyncCamAfter } from 'clientSideScene/CameraControls' import { letEngineAnimateAndSyncCamAfter } from 'clientSideScene/CameraControls'
import { getVarNameModal } from 'hooks/useToolbarGuards' import { getVarNameModal } from 'hooks/useToolbarGuards'
import { err, reportRejection, trap } from 'lib/trap' import { err, reportRejection, trap } from 'lib/trap'
@ -84,7 +90,7 @@ import {
import { submitAndAwaitTextToKcl } from 'lib/textToCad' import { submitAndAwaitTextToKcl } from 'lib/textToCad'
import { useFileContext } from 'hooks/useFileContext' import { useFileContext } from 'hooks/useFileContext'
import { uuidv4 } from 'lib/utils' import { uuidv4 } from 'lib/utils'
import { UnboxedNode } from 'wasm-lib/kcl/bindings/UnboxedNode' import { IndexLoaderData } from 'lib/types'
type MachineContext<T extends AnyStateMachine> = { type MachineContext<T extends AnyStateMachine> = {
state: StateFrom<T> state: StateFrom<T>
@ -117,6 +123,7 @@ export const ModelingMachineProvider = ({
} = useSettingsAuthContext() } = useSettingsAuthContext()
const navigate = useNavigate() const navigate = useNavigate()
const { context, send: fileMachineSend } = useFileContext() const { context, send: fileMachineSend } = useFileContext()
const { file } = useLoaderData() as IndexLoaderData
const token = auth?.context?.token const token = auth?.context?.token
const streamRef = useRef<HTMLDivElement>(null) const streamRef = useRef<HTMLDivElement>(null)
const persistedContext = useMemo(() => getPersistedContext(), []) const persistedContext = useMemo(() => getPersistedContext(), [])
@ -139,6 +146,8 @@ export const ModelingMachineProvider = ({
// > // >
// ) // )
const machineManager = useContext(MachineManagerContext)
const [modelingState, modelingSend, modelingActor] = useMachine( const [modelingState, modelingSend, modelingActor] = useMachine(
modelingMachine.provide({ modelingMachine.provide({
actions: { actions: {
@ -407,18 +416,35 @@ export const ModelingMachineProvider = ({
return {} return {}
} }
), ),
Make: ({ event }) => { Make: ({ context, event }) => {
if (event.type !== 'Make') return if (event.type !== 'Make') return
// Check if we already have an export intent. // Check if we already have an export intent.
if (engineCommandManager.exportIntent) { if (engineCommandManager.exportInfo) {
toast.error('Already exporting') toast.error('Already exporting')
return return
} }
// Set the export intent. // Set the export intent.
engineCommandManager.exportIntent = ExportIntent.Make engineCommandManager.exportInfo = {
intent: ExportIntent.Make,
name: file?.name || '',
}
// Set the current machine. // Set the current machine.
machineManager.currentMachine = event.data.machine // Due to our use of singeton pattern, we need to do this to reliably
// update this object across React and non-React boundary.
// We need to do this eagerly because of the exportToEngine call below.
if (engineCommandManager.machineManager === null) {
console.warn(
"engineCommandManager.machineManager is null. It shouldn't be at this point. Aborting operation."
)
return
} else {
engineCommandManager.machineManager.currentMachine =
event.data.machine
}
// Update the rest of the UI that needs to know the current machine
context.machineManager.setCurrentMachine(event.data.machine)
const format: Models['OutputFormat_type'] = { const format: Models['OutputFormat_type'] = {
type: 'stl', type: 'stl',
@ -444,12 +470,16 @@ export const ModelingMachineProvider = ({
}, },
'Engine export': ({ event }) => { 'Engine export': ({ event }) => {
if (event.type !== 'Export') return if (event.type !== 'Export') return
if (engineCommandManager.exportIntent) { if (engineCommandManager.exportInfo) {
toast.error('Already exporting') toast.error('Already exporting')
return return
} }
// Set the export intent. // Set the export intent.
engineCommandManager.exportIntent = ExportIntent.Save engineCommandManager.exportInfo = {
intent: ExportIntent.Save,
// This never gets used its only for make.
name: '',
}
const format = { const format = {
...event.data, ...event.data,
@ -636,6 +666,7 @@ export const ModelingMachineProvider = ({
input.plane input.plane
) )
await kclManager.updateAst(modifiedAst, false) await kclManager.updateAst(modifiedAst, false)
sceneInfra.camControls.enableRotate = false
sceneInfra.camControls.syncDirection = 'clientToEngine' sceneInfra.camControls.syncDirection = 'clientToEngine'
await letEngineAnimateAndSyncCamAfter( await letEngineAnimateAndSyncCamAfter(
@ -940,7 +971,7 @@ export const ModelingMachineProvider = ({
}) })
let parsed = parse(recast(kclManager.ast)) let parsed = parse(recast(kclManager.ast))
if (trap(parsed)) return Promise.reject(parsed) if (trap(parsed)) return Promise.reject(parsed)
parsed = parsed as UnboxedNode<Program> parsed = parsed as Program
const { modifiedAst: _modifiedAst, pathToReplacedNode } = const { modifiedAst: _modifiedAst, pathToReplacedNode } =
moveValueIntoNewVariablePath( moveValueIntoNewVariablePath(
@ -951,7 +982,7 @@ export const ModelingMachineProvider = ({
) )
parsed = parse(recast(_modifiedAst)) parsed = parse(recast(_modifiedAst))
if (trap(parsed)) return Promise.reject(parsed) if (trap(parsed)) return Promise.reject(parsed)
parsed = parsed as UnboxedNode<Program> parsed = parsed as Program
if (!pathToReplacedNode) if (!pathToReplacedNode)
return Promise.reject(new Error('No path to replaced node')) return Promise.reject(new Error('No path to replaced node'))
@ -986,6 +1017,7 @@ export const ModelingMachineProvider = ({
...modelingMachineDefaultContext.store, ...modelingMachineDefaultContext.store,
...persistedContext, ...persistedContext,
}, },
machineManager,
}, },
// devTools: true, // devTools: true,
} }

View File

@ -95,7 +95,7 @@ export const processMemory = (programMemory: ProgramMemory) => {
return rest return rest
}) })
} else if (!err(sg)) { } else if (!err(sg)) {
processedMemory[key] = sg.value.map(({ __geoMeta, ...rest }: Path) => { processedMemory[key] = sg.paths.map(({ __geoMeta, ...rest }: Path) => {
return rest return rest
}) })
} else if ((val.type as any) === 'Function') { } else if ((val.type as any) === 'Function') {

View File

@ -1,6 +1,12 @@
import { useSettingsAuthContext } from 'hooks/useSettingsAuthContext' import { useSettingsAuthContext } from 'hooks/useSettingsAuthContext'
import { Resizable } from 're-resizable' import { Resizable } from 're-resizable'
import { MouseEventHandler, useCallback, useEffect, useMemo } from 'react' import {
MouseEventHandler,
useCallback,
useEffect,
useMemo,
useContext,
} from 'react'
import { useHotkeys } from 'react-hotkeys-hook' import { useHotkeys } from 'react-hotkeys-hook'
import { SidebarAction, SidebarType, sidebarPanes } from './ModelingPanes' import { SidebarAction, SidebarType, sidebarPanes } from './ModelingPanes'
import Tooltip from 'components/Tooltip' import Tooltip from 'components/Tooltip'
@ -13,7 +19,7 @@ import { CustomIconName } from 'components/CustomIcon'
import { useCommandsContext } from 'hooks/useCommandsContext' import { useCommandsContext } from 'hooks/useCommandsContext'
import { IconDefinition } from '@fortawesome/free-solid-svg-icons' import { IconDefinition } from '@fortawesome/free-solid-svg-icons'
import { useKclContext } from 'lang/KclProvider' import { useKclContext } from 'lang/KclProvider'
import { machineManager } from 'lib/machineManager' import { MachineManagerContext } from 'components/MachineManagerProvider'
interface ModelingSidebarProps { interface ModelingSidebarProps {
paneOpacity: '' | 'opacity-20' | 'opacity-40' paneOpacity: '' | 'opacity-20' | 'opacity-40'
@ -29,6 +35,7 @@ function getPlatformString(): 'web' | 'desktop' {
} }
export function ModelingSidebar({ paneOpacity }: ModelingSidebarProps) { export function ModelingSidebar({ paneOpacity }: ModelingSidebarProps) {
const machineManager = useContext(MachineManagerContext)
const { commandBarSend } = useCommandsContext() const { commandBarSend } = useCommandsContext()
const kclContext = useKclContext() const kclContext = useKclContext()
const { settings } = useSettingsAuthContext() const { settings } = useSettingsAuthContext()

View File

@ -1,7 +1,9 @@
import { Popover } from '@headlessui/react' import { Popover } from '@headlessui/react'
import { useContext } from 'react'
import Tooltip from './Tooltip' import Tooltip from './Tooltip'
import { machineManager } from 'lib/machineManager'
import { isDesktop } from 'lib/isDesktop' import { isDesktop } from 'lib/isDesktop'
import { components } from 'lib/machine-api'
import { MachineManagerContext } from 'components/MachineManagerProvider'
import { CustomIcon } from './CustomIcon' import { CustomIcon } from './CustomIcon'
export const NetworkMachineIndicator = ({ export const NetworkMachineIndicator = ({
@ -9,9 +11,12 @@ export const NetworkMachineIndicator = ({
}: { }: {
className?: string className?: string
}) => { }) => {
const machineCount = machineManager.machineCount() const {
const reason = machineManager.noMachinesReason() noMachinesReason,
const machines = machineManager.machines machines,
machines: { length: machineCount },
} = useContext(MachineManagerContext)
const reason = noMachinesReason()
return isDesktop() ? ( return isDesktop() ? (
<Popover className="relative"> <Popover className="relative">
@ -47,7 +52,8 @@ export const NetworkMachineIndicator = ({
</div> </div>
{machineCount > 0 && ( {machineCount > 0 && (
<ul className="divide-y divide-chalkboard-20 dark:divide-chalkboard-80"> <ul className="divide-y divide-chalkboard-20 dark:divide-chalkboard-80">
{machines.map((machine) => { {machines.map(
(machine: components['schemas']['MachineInfoResponse']) => {
return ( return (
<li key={machine.id} className={'px-2 py-4 gap-1 last:mb-0 '}> <li key={machine.id} className={'px-2 py-4 gap-1 last:mb-0 '}>
<p className="">{machine.id.toUpperCase()}</p> <p className="">{machine.id.toUpperCase()}</p>
@ -74,7 +80,8 @@ export const NetworkMachineIndicator = ({
</p> </p>
</li> </li>
) )
})} }
)}
</ul> </ul>
)} )}
</Popover.Panel> </Popover.Panel>

View File

@ -4,14 +4,14 @@ import { type IndexLoaderData } from 'lib/types'
import { PATHS } from 'lib/paths' import { PATHS } from 'lib/paths'
import { isDesktop } from '../lib/isDesktop' import { isDesktop } from '../lib/isDesktop'
import { Link, useLocation, useNavigate } from 'react-router-dom' import { Link, useLocation, useNavigate } from 'react-router-dom'
import { Fragment, useMemo } from 'react' import { Fragment, useMemo, useContext } from 'react'
import { Logo } from './Logo' import { Logo } from './Logo'
import { APP_NAME } from 'lib/constants' import { APP_NAME } from 'lib/constants'
import { useCommandsContext } from 'hooks/useCommandsContext' import { useCommandsContext } from 'hooks/useCommandsContext'
import { CustomIcon } from './CustomIcon' import { CustomIcon } from './CustomIcon'
import { useLspContext } from './LspProvider' import { useLspContext } from './LspProvider'
import { engineCommandManager } from 'lib/singletons' import { engineCommandManager } from 'lib/singletons'
import { machineManager } from 'lib/machineManager' import { MachineManagerContext } from 'components/MachineManagerProvider'
import usePlatform from 'hooks/usePlatform' import usePlatform from 'hooks/usePlatform'
import { useAbsoluteFilePath } from 'hooks/useAbsoluteFilePath' import { useAbsoluteFilePath } from 'hooks/useAbsoluteFilePath'
import Tooltip from './Tooltip' import Tooltip from './Tooltip'
@ -96,6 +96,8 @@ function ProjectMenuPopover({
const location = useLocation() const location = useLocation()
const navigate = useNavigate() const navigate = useNavigate()
const filePath = useAbsoluteFilePath() const filePath = useAbsoluteFilePath()
const machineManager = useContext(MachineManagerContext)
const { commandBarState, commandBarSend } = useCommandsContext() const { commandBarState, commandBarSend } = useCommandsContext()
const { onProjectClose } = useLspContext() const { onProjectClose } = useLspContext()
const exportCommandInfo = { name: 'Export', groupId: 'modeling' } const exportCommandInfo = { name: 'Export', groupId: 'modeling' }
@ -106,7 +108,7 @@ function ProjectMenuPopover({
(c) => c.name === obj.name && c.groupId === obj.groupId (c) => c.name === obj.name && c.groupId === obj.groupId
) )
) )
const machineCount = machineManager.machineCount() const machineCount = machineManager.machines.length
// We filter this memoized list so that no orphan "break" elements are rendered. // We filter this memoized list so that no orphan "break" elements are rendered.
const projectMenuItems = useMemo<(ActionButtonProps | 'break')[]>( const projectMenuItems = useMemo<(ActionButtonProps | 'break')[]>(

View File

@ -255,10 +255,14 @@ export const Stream = () => {
}, [mediaStream]) }, [mediaStream])
const handleMouseUp: MouseEventHandler<HTMLDivElement> = (e) => { const handleMouseUp: MouseEventHandler<HTMLDivElement> = (e) => {
// If we've got no stream or connection, don't do anything
if (!isNetworkOkay) return if (!isNetworkOkay) return
if (!videoRef.current) return if (!videoRef.current) return
// If we're in sketch mode, don't send a engine-side select event
if (state.matches('Sketch')) return if (state.matches('Sketch')) return
if (state.matches({ idle: 'showPlanes' })) return if (state.matches({ idle: 'showPlanes' })) return
// If we're mousing up from a camera drag, don't send a select event
if (sceneInfra.camControls.wasDragging === true) return
if (btnName(e.nativeEvent).left) { if (btnName(e.nativeEvent).left) {
// eslint-disable-next-line @typescript-eslint/no-floating-promises // eslint-disable-next-line @typescript-eslint/no-floating-promises

View File

@ -14,7 +14,6 @@ import {
import { TransformInfo } from 'lang/std/stdTypes' import { TransformInfo } from 'lang/std/stdTypes'
import { kclManager } from 'lib/singletons' import { kclManager } from 'lib/singletons'
import { err } from 'lib/trap' import { err } from 'lib/trap'
import { UnboxedNode } from 'wasm-lib/kcl/bindings/UnboxedNode'
export function setEqualLengthInfo({ export function setEqualLengthInfo({
selectionRanges, selectionRanges,
@ -87,7 +86,7 @@ export function applyConstraintEqualLength({
selectionRanges: Selections selectionRanges: Selections
}): }):
| { | {
modifiedAst: UnboxedNode<Program> modifiedAst: Program
pathToNodeMap: PathToNodeMap pathToNodeMap: PathToNodeMap
} }
| Error { | Error {

View File

@ -13,7 +13,6 @@ import {
import { TransformInfo } from 'lang/std/stdTypes' import { TransformInfo } from 'lang/std/stdTypes'
import { kclManager } from 'lib/singletons' import { kclManager } from 'lib/singletons'
import { err } from 'lib/trap' import { err } from 'lib/trap'
import { UnboxedNode } from 'wasm-lib/kcl/bindings/UnboxedNode'
export function horzVertInfo( export function horzVertInfo(
selectionRanges: Selections, selectionRanges: Selections,
@ -56,11 +55,11 @@ export function horzVertInfo(
export function applyConstraintHorzVert( export function applyConstraintHorzVert(
selectionRanges: Selections, selectionRanges: Selections,
horOrVert: 'vertical' | 'horizontal', horOrVert: 'vertical' | 'horizontal',
ast: UnboxedNode<Program>, ast: Program,
programMemory: ProgramMemory programMemory: ProgramMemory
): ):
| { | {
modifiedAst: UnboxedNode<Program> modifiedAst: Program
pathToNodeMap: PathToNodeMap pathToNodeMap: PathToNodeMap
} }
| Error { | Error {

View File

@ -19,7 +19,6 @@ import { createVariableDeclaration } from '../../lang/modifyAst'
import { removeDoubleNegatives } from '../AvailableVarsHelpers' import { removeDoubleNegatives } from '../AvailableVarsHelpers'
import { kclManager } from 'lib/singletons' import { kclManager } from 'lib/singletons'
import { err } from 'lib/trap' import { err } from 'lib/trap'
import { UnboxedNode } from 'wasm-lib/kcl/bindings/UnboxedNode'
const getModalInfo = createInfoModal(GetInfoModal) const getModalInfo = createInfoModal(GetInfoModal)
@ -137,7 +136,7 @@ export async function applyConstraintIntersect({
}: { }: {
selectionRanges: Selections selectionRanges: Selections
}): Promise<{ }): Promise<{
modifiedAst: UnboxedNode<Program> modifiedAst: Program
pathToNodeMap: PathToNodeMap pathToNodeMap: PathToNodeMap
}> { }> {
const info = intersectInfo({ const info = intersectInfo({

View File

@ -13,7 +13,6 @@ import {
import { TransformInfo } from 'lang/std/stdTypes' import { TransformInfo } from 'lang/std/stdTypes'
import { kclManager } from 'lib/singletons' import { kclManager } from 'lib/singletons'
import { err } from 'lib/trap' import { err } from 'lib/trap'
import { UnboxedNode } from 'wasm-lib/kcl/bindings/UnboxedNode'
export function removeConstrainingValuesInfo({ export function removeConstrainingValuesInfo({
selectionRanges, selectionRanges,
@ -78,7 +77,7 @@ export function applyRemoveConstrainingValues({
pathToNodes?: Array<PathToNode> pathToNodes?: Array<PathToNode>
}): }):
| { | {
modifiedAst: UnboxedNode<Program> modifiedAst: Program
pathToNodeMap: PathToNodeMap pathToNodeMap: PathToNodeMap
} }
| Error { | Error {

View File

@ -23,7 +23,6 @@ import {
import { removeDoubleNegatives } from '../AvailableVarsHelpers' import { removeDoubleNegatives } from '../AvailableVarsHelpers'
import { kclManager } from 'lib/singletons' import { kclManager } from 'lib/singletons'
import { err } from 'lib/trap' import { err } from 'lib/trap'
import { UnboxedNode } from 'wasm-lib/kcl/bindings/UnboxedNode'
const getModalInfo = createSetAngleLengthModal(SetAngleLengthModal) const getModalInfo = createSetAngleLengthModal(SetAngleLengthModal)
@ -162,7 +161,7 @@ export function applyConstraintAxisAlign({
constraint: 'snapToYAxis' | 'snapToXAxis' constraint: 'snapToYAxis' | 'snapToXAxis'
}): }):
| { | {
modifiedAst: UnboxedNode<Program> modifiedAst: Program
pathToNodeMap: PathToNodeMap pathToNodeMap: PathToNodeMap
} }
| Error { | Error {

View File

@ -18,7 +18,6 @@ import { removeDoubleNegatives } from '../AvailableVarsHelpers'
import { kclManager } from 'lib/singletons' import { kclManager } from 'lib/singletons'
import { Selections } from 'lib/selections' import { Selections } from 'lib/selections'
import { cleanErrs, err } from 'lib/trap' import { cleanErrs, err } from 'lib/trap'
import { UnboxedNode } from 'wasm-lib/kcl/bindings/UnboxedNode'
const getModalInfo = createInfoModal(GetInfoModal) const getModalInfo = createInfoModal(GetInfoModal)
@ -186,7 +185,7 @@ export function applyConstraintHorzVertAlign({
constraint: 'setHorzDistance' | 'setVertDistance' constraint: 'setHorzDistance' | 'setVertDistance'
}): }):
| { | {
modifiedAst: UnboxedNode<Program> modifiedAst: Program
pathToNodeMap: PathToNodeMap pathToNodeMap: PathToNodeMap
} }
| Error { | Error {

View File

@ -21,10 +21,9 @@ import {
import { getNodeFromPath } from './queryAst' import { getNodeFromPath } from './queryAst'
import { codeManager, editorManager, sceneInfra } from 'lib/singletons' import { codeManager, editorManager, sceneInfra } from 'lib/singletons'
import { Diagnostic } from '@codemirror/lint' import { Diagnostic } from '@codemirror/lint'
import { UnboxedNode } from 'wasm-lib/kcl/bindings/UnboxedNode'
interface ExecuteArgs { interface ExecuteArgs {
ast?: UnboxedNode<Program> ast?: Program
zoomToFit?: boolean zoomToFit?: boolean
executionId?: number executionId?: number
zoomOnRangeAndType?: { zoomOnRangeAndType?: {
@ -34,13 +33,13 @@ interface ExecuteArgs {
} }
export class KclManager { export class KclManager {
private _ast: UnboxedNode<Program> = { private _ast: Program = {
body: [], body: [],
start: 0, start: 0,
end: 0, end: 0,
nonCodeMeta: { nonCodeMeta: {
nonCodeNodes: {}, nonCodeNodes: {},
startNodes: [], start: [],
}, },
} }
private _execState: ExecState = emptyExecState() private _execState: ExecState = emptyExecState()
@ -56,7 +55,7 @@ export class KclManager {
engineCommandManager: EngineCommandManager engineCommandManager: EngineCommandManager
private _isExecutingCallback: (arg: boolean) => void = () => {} private _isExecutingCallback: (arg: boolean) => void = () => {}
private _astCallBack: (arg: UnboxedNode<Program>) => void = () => {} private _astCallBack: (arg: Program) => void = () => {}
private _programMemoryCallBack: (arg: ProgramMemory) => void = () => {} private _programMemoryCallBack: (arg: ProgramMemory) => void = () => {}
private _logsCallBack: (arg: string[]) => void = () => {} private _logsCallBack: (arg: string[]) => void = () => {}
private _kclErrorsCallBack: (arg: KCLError[]) => void = () => {} private _kclErrorsCallBack: (arg: KCLError[]) => void = () => {}
@ -182,7 +181,7 @@ export class KclManager {
setWasmInitFailed, setWasmInitFailed,
}: { }: {
setProgramMemory: (arg: ProgramMemory) => void setProgramMemory: (arg: ProgramMemory) => void
setAst: (arg: UnboxedNode<Program>) => void setAst: (arg: Program) => void
setLogs: (arg: string[]) => void setLogs: (arg: string[]) => void
setKclErrors: (arg: KCLError[]) => void setKclErrors: (arg: KCLError[]) => void
setIsExecuting: (arg: boolean) => void setIsExecuting: (arg: boolean) => void
@ -206,12 +205,12 @@ export class KclManager {
end: 0, end: 0,
nonCodeMeta: { nonCodeMeta: {
nonCodeNodes: {}, nonCodeNodes: {},
startNodes: [], start: [],
}, },
} }
} }
safeParse(code: string): UnboxedNode<Program> | null { safeParse(code: string): Program | null {
const ast = parse(code) const ast = parse(code)
this.lints = [] this.lints = []
this.kclErrors = [] this.kclErrors = []
@ -378,7 +377,7 @@ export class KclManager {
Array.from(this.engineCommandManager.artifactGraph).forEach( Array.from(this.engineCommandManager.artifactGraph).forEach(
([commandId, artifact]) => { ([commandId, artifact]) => {
if (!('codeRef' in artifact)) return if (!('codeRef' in artifact)) return
const _node1 = getNodeFromPath<UnboxedNode<CallExpression>>( const _node1 = getNodeFromPath<CallExpression>(
this.ast, this.ast,
artifact.codeRef.pathToNode, artifact.codeRef.pathToNode,
'CallExpression' 'CallExpression'
@ -442,7 +441,7 @@ export class KclManager {
// but should probably have think about which of the function to keep // but should probably have think about which of the function to keep
// This always updates the code state and editor and writes to the file system. // This always updates the code state and editor and writes to the file system.
async updateAst( async updateAst(
ast: UnboxedNode<Program>, ast: Program,
execute: boolean, execute: boolean,
optionalParams?: { optionalParams?: {
focusPath?: Array<PathToNode> focusPath?: Array<PathToNode>
@ -453,7 +452,7 @@ export class KclManager {
} }
} }
): Promise<{ ): Promise<{
newAst: UnboxedNode<Program> newAst: Program
selections?: Selections selections?: Selections
}> { }> {
const newCode = recast(ast) const newCode = recast(ast)
@ -589,7 +588,7 @@ export class KclManager {
} }
// Determines if there is no KCL code which means it is executing a blank KCL file // Determines if there is no KCL code which means it is executing a blank KCL file
_isAstEmpty(ast: UnboxedNode<Program>) { _isAstEmpty(ast: Program) {
return ast.start === 0 && ast.end === 0 && ast.body.length === 0 return ast.start === 0 && ast.end === 0 && ast.body.length === 0
} }
} }

View File

@ -32,7 +32,7 @@ const mySketch001 = startSketchOn('XY')
sourceRange: [46, 71], sourceRange: [46, 71],
}, },
}, },
value: [ paths: [
{ {
type: 'ToPoint', type: 'ToPoint',
tag: null, tag: null,
@ -96,7 +96,7 @@ const mySketch001 = startSketchOn('XY')
on: expect.any(Object), on: expect.any(Object),
start: expect.any(Object), start: expect.any(Object),
type: 'Sketch', type: 'Sketch',
value: [ paths: [
{ {
type: 'ToPoint', type: 'ToPoint',
from: [0, 0], from: [0, 0],
@ -202,7 +202,7 @@ const sk2 = startSketchOn('XY')
info: expect.any(Object), info: expect.any(Object),
}, },
}, },
value: [ paths: [
{ {
type: 'ToPoint', type: 'ToPoint',
from: [0, 0], from: [0, 0],
@ -294,7 +294,7 @@ const sk2 = startSketchOn('XY')
info: expect.any(Object), info: expect.any(Object),
}, },
}, },
value: [ paths: [
{ {
type: 'ToPoint', type: 'ToPoint',
from: [0, 0], from: [0, 0],

View File

@ -18,6 +18,9 @@ export default class CodeManager {
#updateState: (arg: string) => void = () => {} #updateState: (arg: string) => void = () => {}
private _currentFilePath: string | null = null private _currentFilePath: string | null = null
private _hotkeys: { [key: string]: () => void } = {} private _hotkeys: { [key: string]: () => void } = {}
private timeoutWriter: ReturnType<typeof setTimeout> | undefined = undefined
public writeCausedByAppCheckedInFileTreeFileSystemWatcher = false
constructor() { constructor() {
if (isDesktop()) { if (isDesktop()) {
@ -115,7 +118,12 @@ export default class CodeManager {
async writeToFile() { async writeToFile() {
if (isDesktop()) { if (isDesktop()) {
setTimeout(() => { // Only write our buffer contents to file once per second. Any faster
// and file-system watchers which read, will receive empty data during
// writes.
clearTimeout(this.timeoutWriter)
this.writeCausedByAppCheckedInFileTreeFileSystemWatcher = true
this.timeoutWriter = setTimeout(() => {
// Wait one event loop to give a chance for params to be set // Wait one event loop to give a chance for params to be set
// Save the file to disk // Save the file to disk
this._currentFilePath && this._currentFilePath &&
@ -126,7 +134,7 @@ export default class CodeManager {
console.error('error saving file', err) console.error('error saving file', err)
toast.error('Error saving file, please check file permissions') toast.error('Error saving file, please check file permissions')
}) })
}) }, 1000)
} else { } else {
safeLSSetItem(PERSIST_CODE_KEY, this.code) safeLSSetItem(PERSIST_CODE_KEY, this.code)
} }

View File

@ -58,7 +58,7 @@ const newVar = myVar + 1`
` `
const mem = await exe(code) const mem = await exe(code)
// geo is three js buffer geometry and is very bloated to have in tests // geo is three js buffer geometry and is very bloated to have in tests
const minusGeo = mem.get('mySketch')?.value?.value const minusGeo = mem.get('mySketch')?.value?.paths
expect(minusGeo).toEqual([ expect(minusGeo).toEqual([
{ {
type: 'ToPoint', type: 'ToPoint',
@ -175,7 +175,7 @@ const newVar = myVar + 1`
info: expect.any(Object), info: expect.any(Object),
}, },
}, },
value: [ paths: [
{ {
type: 'ToPoint', type: 'ToPoint',
to: [1, 1], to: [1, 1],
@ -367,7 +367,7 @@ describe('testing math operators', () => {
const mem = await exe(code) const mem = await exe(code)
const sketch = sketchFromKclValue(mem.get('part001'), 'part001') const sketch = sketchFromKclValue(mem.get('part001'), 'part001')
// result of `-legLen(5, min(3, 999))` should be -4 // result of `-legLen(5, min(3, 999))` should be -4
const yVal = (sketch as Sketch).value?.[0]?.to?.[1] const yVal = (sketch as Sketch).paths?.[0]?.to?.[1]
expect(yVal).toBe(-4) expect(yVal).toBe(-4)
}) })
it('test that % substitution feeds down CallExp->ArrExp->UnaryExp->CallExp', async () => { it('test that % substitution feeds down CallExp->ArrExp->UnaryExp->CallExp', async () => {
@ -385,8 +385,8 @@ describe('testing math operators', () => {
const mem = await exe(code) const mem = await exe(code)
const sketch = sketchFromKclValue(mem.get('part001'), 'part001') const sketch = sketchFromKclValue(mem.get('part001'), 'part001')
// expect -legLen(segLen('seg01'), myVar) to equal -4 setting the y value back to 0 // expect -legLen(segLen('seg01'), myVar) to equal -4 setting the y value back to 0
expect((sketch as Sketch).value?.[1]?.from).toEqual([3, 4]) expect((sketch as Sketch).paths?.[1]?.from).toEqual([3, 4])
expect((sketch as Sketch).value?.[1]?.to).toEqual([6, 0]) expect((sketch as Sketch).paths?.[1]?.to).toEqual([6, 0])
const removedUnaryExp = code.replace( const removedUnaryExp = code.replace(
`-legLen(segLen(seg01), myVar)`, `-legLen(segLen(seg01), myVar)`,
`legLen(segLen(seg01), myVar)` `legLen(segLen(seg01), myVar)`
@ -398,7 +398,7 @@ describe('testing math operators', () => {
) )
// without the minus sign, the y value should be 8 // without the minus sign, the y value should be 8
expect((removedUnaryExpMemSketch as Sketch).value?.[1]?.to).toEqual([6, 8]) expect((removedUnaryExpMemSketch as Sketch).paths?.[1]?.to).toEqual([6, 8])
}) })
it('with nested callExpression and binaryExpression', async () => { it('with nested callExpression and binaryExpression', async () => {
const code = 'const myVar = 2 + min(100, -1 + legLen(5, 3))' const code = 'const myVar = 2 + min(100, -1 + legLen(5, 3))'

View File

@ -12,7 +12,6 @@ import { EngineCommandManager } from 'lang/std/engineConnection'
import { KCLError } from 'lang/errors' import { KCLError } from 'lang/errors'
import { Diagnostic } from '@codemirror/lint' import { Diagnostic } from '@codemirror/lint'
import { IdGenerator } from 'wasm-lib/kcl/bindings/IdGenerator' import { IdGenerator } from 'wasm-lib/kcl/bindings/IdGenerator'
import { UnboxedNode } from 'wasm-lib/kcl/bindings/UnboxedNode'
export type ToolTip = export type ToolTip =
| 'lineTo' | 'lineTo'
@ -53,7 +52,7 @@ export async function executeAst({
programMemoryOverride, programMemoryOverride,
idGenerator, idGenerator,
}: { }: {
ast: UnboxedNode<Program> ast: Program
engineCommandManager: EngineCommandManager engineCommandManager: EngineCommandManager
useFakeExecutor?: boolean useFakeExecutor?: boolean
programMemoryOverride?: ProgramMemory programMemoryOverride?: ProgramMemory

View File

@ -21,7 +21,6 @@ import { enginelessExecutor } from '../lib/testHelpers'
import { findUsesOfTagInPipe, getNodePathFromSourceRange } from './queryAst' import { findUsesOfTagInPipe, getNodePathFromSourceRange } from './queryAst'
import { err } from 'lib/trap' import { err } from 'lib/trap'
import { SimplifiedArgDetails } from './std/stdTypes' import { SimplifiedArgDetails } from './std/stdTypes'
import { UnboxedNode } from 'wasm-lib/kcl/bindings/UnboxedNode'
beforeAll(async () => { beforeAll(async () => {
await initPromise await initPromise
@ -110,7 +109,7 @@ describe('Testing findUniqueName', () => {
{ type: 'Identifier', name: 'yo07', start: 0, end: 0 }, { type: 'Identifier', name: 'yo07', start: 0, end: 0 },
{ type: 'Identifier', name: 'yo08', start: 0, end: 0 }, { type: 'Identifier', name: 'yo08', start: 0, end: 0 },
{ type: 'Identifier', name: 'yo09', start: 0, end: 0 }, { type: 'Identifier', name: 'yo09', start: 0, end: 0 },
] satisfies UnboxedNode<Identifier>[]), ] satisfies Identifier[]),
'yo', 'yo',
2 2
) )
@ -124,7 +123,7 @@ describe('Testing addSketchTo', () => {
body: [], body: [],
start: 0, start: 0,
end: 0, end: 0,
nonCodeMeta: { nonCodeNodes: {}, startNodes: [] }, nonCodeMeta: { nonCodeNodes: {}, start: [] },
}, },
'yz' 'yz'
) )

View File

@ -42,13 +42,12 @@ import { SimplifiedArgDetails } from './std/stdTypes'
import { TagDeclarator } from 'wasm-lib/kcl/bindings/TagDeclarator' import { TagDeclarator } from 'wasm-lib/kcl/bindings/TagDeclarator'
import { Models } from '@kittycad/lib' import { Models } from '@kittycad/lib'
import { ExtrudeFacePlane } from 'machines/modelingMachine' import { ExtrudeFacePlane } from 'machines/modelingMachine'
import { UnboxedNode } from 'wasm-lib/kcl/bindings/UnboxedNode'
export function startSketchOnDefault( export function startSketchOnDefault(
node: UnboxedNode<Program>, node: Program,
axis: DefaultPlaneStr, axis: DefaultPlaneStr,
name = '' name = ''
): { modifiedAst: UnboxedNode<Program>; id: string; pathToNode: PathToNode } { ): { modifiedAst: Program; id: string; pathToNode: PathToNode } {
const _node = { ...node } const _node = { ...node }
const _name = const _name =
name || findUniqueName(node, KCL_DEFAULT_CONSTANT_PREFIXES.SKETCH) name || findUniqueName(node, KCL_DEFAULT_CONSTANT_PREFIXES.SKETCH)
@ -77,10 +76,10 @@ export function startSketchOnDefault(
} }
export function addStartProfileAt( export function addStartProfileAt(
node: UnboxedNode<Program>, node: Program,
pathToNode: PathToNode, pathToNode: PathToNode,
at: [number, number] at: [number, number]
): { modifiedAst: UnboxedNode<Program>; pathToNode: PathToNode } | Error { ): { modifiedAst: Program; pathToNode: PathToNode } | Error {
const _node1 = getNodeFromPath<VariableDeclaration>( const _node1 = getNodeFromPath<VariableDeclaration>(
node, node,
pathToNode, pathToNode,
@ -115,7 +114,7 @@ export function addStartProfileAt(
} }
export function addSketchTo( export function addSketchTo(
node: UnboxedNode<Program>, node: Program,
axis: 'xy' | 'xz' | 'yz', axis: 'xy' | 'xz' | 'yz',
name = '' name = ''
): { modifiedAst: Program; id: string; pathToNode: PathToNode } { ): { modifiedAst: Program; id: string; pathToNode: PathToNode } {
@ -211,7 +210,7 @@ export function mutateArrExp(node: Expr, updateWith: ArrayExpression): boolean {
export function mutateObjExpProp( export function mutateObjExpProp(
node: Expr, node: Expr,
updateWith: UnboxedNode<Literal> | UnboxedNode<ArrayExpression>, updateWith: Literal | ArrayExpression,
key: string key: string
): boolean { ): boolean {
if (node.type === 'ObjectExpression') { if (node.type === 'ObjectExpression') {
@ -249,13 +248,13 @@ export function mutateObjExpProp(
} }
export function extrudeSketch( export function extrudeSketch(
node: UnboxedNode<Program>, node: Program,
pathToNode: PathToNode, pathToNode: PathToNode,
shouldPipe = false, shouldPipe = false,
distance: Expr = createLiteral(4) distance: Expr = createLiteral(4)
): ):
| { | {
modifiedAst: UnboxedNode<Program> modifiedAst: Program
pathToNode: PathToNode pathToNode: PathToNode
pathToExtrudeArg: PathToNode pathToExtrudeArg: PathToNode
} }
@ -344,13 +343,13 @@ export function extrudeSketch(
} }
export function revolveSketch( export function revolveSketch(
node: UnboxedNode<Program>, node: Program,
pathToNode: PathToNode, pathToNode: PathToNode,
shouldPipe = false, shouldPipe = false,
angle: Expr = createLiteral(4) angle: Expr = createLiteral(4)
): ):
| { | {
modifiedAst: UnboxedNode<Program> modifiedAst: Program
pathToNode: PathToNode pathToNode: PathToNode
pathToRevolveArg: PathToNode pathToRevolveArg: PathToNode
} }
@ -440,7 +439,7 @@ export function revolveSketch(
} }
export function sketchOnExtrudedFace( export function sketchOnExtrudedFace(
node: UnboxedNode<Program>, node: Program,
sketchPathToNode: PathToNode, sketchPathToNode: PathToNode,
extrudePathToNode: PathToNode, extrudePathToNode: PathToNode,
info: ExtrudeFacePlane['faceInfo'] = { type: 'wall' } info: ExtrudeFacePlane['faceInfo'] = { type: 'wall' }
@ -572,7 +571,7 @@ export function splitPathAtPipeExpression(pathToNode: PathToNode): {
return splitPathAtPipeExpression(pathToNode.slice(0, -1)) return splitPathAtPipeExpression(pathToNode.slice(0, -1))
} }
export function createLiteral(value: string | number): UnboxedNode<Literal> { export function createLiteral(value: string | number): Literal {
return { return {
type: 'Literal', type: 'Literal',
start: 0, start: 0,
@ -582,7 +581,7 @@ export function createLiteral(value: string | number): UnboxedNode<Literal> {
} }
} }
export function createTagDeclarator(value: string): UnboxedNode<TagDeclarator> { export function createTagDeclarator(value: string): TagDeclarator {
return { return {
type: 'TagDeclarator', type: 'TagDeclarator',
start: 0, start: 0,
@ -592,7 +591,7 @@ export function createTagDeclarator(value: string): UnboxedNode<TagDeclarator> {
} }
} }
export function createIdentifier(name: string): UnboxedNode<Identifier> { export function createIdentifier(name: string): Identifier {
return { return {
type: 'Identifier', type: 'Identifier',
start: 0, start: 0,
@ -602,7 +601,7 @@ export function createIdentifier(name: string): UnboxedNode<Identifier> {
} }
} }
export function createPipeSubstitution(): UnboxedNode<PipeSubstitution> { export function createPipeSubstitution(): PipeSubstitution {
return { return {
type: 'PipeSubstitution', type: 'PipeSubstitution',
start: 0, start: 0,
@ -613,7 +612,7 @@ export function createPipeSubstitution(): UnboxedNode<PipeSubstitution> {
export function createCallExpressionStdLib( export function createCallExpressionStdLib(
name: string, name: string,
args: CallExpression['arguments'] args: CallExpression['arguments']
): UnboxedNode<CallExpression> { ): CallExpression {
return { return {
type: 'CallExpression', type: 'CallExpression',
start: 0, start: 0,
@ -633,7 +632,7 @@ export function createCallExpressionStdLib(
export function createCallExpression( export function createCallExpression(
name: string, name: string,
args: CallExpression['arguments'] args: CallExpression['arguments']
): UnboxedNode<CallExpression> { ): CallExpression {
return { return {
type: 'CallExpression', type: 'CallExpression',
start: 0, start: 0,
@ -652,7 +651,7 @@ export function createCallExpression(
export function createArrayExpression( export function createArrayExpression(
elements: ArrayExpression['elements'] elements: ArrayExpression['elements']
): UnboxedNode<ArrayExpression> { ): ArrayExpression {
return { return {
type: 'ArrayExpression', type: 'ArrayExpression',
start: 0, start: 0,
@ -665,7 +664,7 @@ export function createArrayExpression(
export function createPipeExpression( export function createPipeExpression(
body: PipeExpression['body'] body: PipeExpression['body']
): UnboxedNode<PipeExpression> { ): PipeExpression {
return { return {
type: 'PipeExpression', type: 'PipeExpression',
start: 0, start: 0,
@ -681,7 +680,7 @@ export function createVariableDeclaration(
init: VariableDeclarator['init'], init: VariableDeclarator['init'],
visibility: VariableDeclaration['visibility'] = 'default', visibility: VariableDeclaration['visibility'] = 'default',
kind: VariableDeclaration['kind'] = 'const' kind: VariableDeclaration['kind'] = 'const'
): UnboxedNode<VariableDeclaration> { ): VariableDeclaration {
return { return {
type: 'VariableDeclaration', type: 'VariableDeclaration',
start: 0, start: 0,
@ -704,7 +703,7 @@ export function createVariableDeclaration(
export function createObjectExpression(properties: { export function createObjectExpression(properties: {
[key: string]: Expr [key: string]: Expr
}): UnboxedNode<ObjectExpression> { }): ObjectExpression {
return { return {
type: 'ObjectExpression', type: 'ObjectExpression',
start: 0, start: 0,
@ -725,7 +724,7 @@ export function createObjectExpression(properties: {
export function createUnaryExpression( export function createUnaryExpression(
argument: UnaryExpression['argument'], argument: UnaryExpression['argument'],
operator: UnaryExpression['operator'] = '-' operator: UnaryExpression['operator'] = '-'
): UnboxedNode<UnaryExpression> { ): UnaryExpression {
return { return {
type: 'UnaryExpression', type: 'UnaryExpression',
start: 0, start: 0,
@ -740,7 +739,7 @@ export function createBinaryExpression([left, operator, right]: [
BinaryExpression['left'], BinaryExpression['left'],
BinaryExpression['operator'], BinaryExpression['operator'],
BinaryExpression['right'] BinaryExpression['right']
]): UnboxedNode<BinaryExpression> { ]): BinaryExpression {
return { return {
type: 'BinaryExpression', type: 'BinaryExpression',
start: 0, start: 0,
@ -755,19 +754,19 @@ export function createBinaryExpression([left, operator, right]: [
export function createBinaryExpressionWithUnary([left, right]: [ export function createBinaryExpressionWithUnary([left, right]: [
BinaryExpression['left'], BinaryExpression['left'],
BinaryExpression['right'] BinaryExpression['right']
]): UnboxedNode<BinaryExpression> { ]): BinaryExpression {
if (right.type === 'UnaryExpression' && right.operator === '-') if (right.type === 'UnaryExpression' && right.operator === '-')
return createBinaryExpression([left, '-', right.argument]) return createBinaryExpression([left, '-', right.argument])
return createBinaryExpression([left, '+', right]) return createBinaryExpression([left, '+', right])
} }
export function giveSketchFnCallTag( export function giveSketchFnCallTag(
ast: UnboxedNode<Program>, ast: Program,
range: Selection['range'], range: Selection['range'],
tag?: string tag?: string
): ):
| { | {
modifiedAst: UnboxedNode<Program> modifiedAst: Program
tag: string tag: string
isTagExisting: boolean isTagExisting: boolean
pathToNode: PathToNode pathToNode: PathToNode
@ -802,7 +801,7 @@ export function giveSketchFnCallTag(
} }
export function moveValueIntoNewVariablePath( export function moveValueIntoNewVariablePath(
ast: UnboxedNode<Program>, ast: Program,
programMemory: ProgramMemory, programMemory: ProgramMemory,
pathToNode: PathToNode, pathToNode: PathToNode,
variableName: string variableName: string
@ -835,12 +834,12 @@ export function moveValueIntoNewVariablePath(
} }
export function moveValueIntoNewVariable( export function moveValueIntoNewVariable(
ast: UnboxedNode<Program>, ast: Program,
programMemory: ProgramMemory, programMemory: ProgramMemory,
sourceRange: Selection['range'], sourceRange: Selection['range'],
variableName: string variableName: string
): { ): {
modifiedAst: UnboxedNode<Program> modifiedAst: Program
pathToReplacedNode?: PathToNode pathToReplacedNode?: PathToNode
} { } {
const meta = isNodeSafeToReplace(ast, sourceRange) const meta = isNodeSafeToReplace(ast, sourceRange)
@ -873,17 +872,17 @@ export function moveValueIntoNewVariable(
*/ */
export function deleteSegmentFromPipeExpression( export function deleteSegmentFromPipeExpression(
dependentRanges: SourceRange[], dependentRanges: SourceRange[],
modifiedAst: UnboxedNode<Program>, modifiedAst: Program,
programMemory: ProgramMemory, programMemory: ProgramMemory,
code: string, code: string,
pathToNode: PathToNode pathToNode: PathToNode
): UnboxedNode<Program> | Error { ): Program | Error {
let _modifiedAst = structuredClone(modifiedAst) let _modifiedAst = structuredClone(modifiedAst)
dependentRanges.forEach((range) => { dependentRanges.forEach((range) => {
const path = getNodePathFromSourceRange(_modifiedAst, range) const path = getNodePathFromSourceRange(_modifiedAst, range)
const callExp = getNodeFromPath<UnboxedNode<CallExpression>>( const callExp = getNodeFromPath<CallExpression>(
_modifiedAst, _modifiedAst,
path, path,
'CallExpression', 'CallExpression',
@ -929,11 +928,11 @@ export function deleteSegmentFromPipeExpression(
export function removeSingleConstraintInfo( export function removeSingleConstraintInfo(
pathToCallExp: PathToNode, pathToCallExp: PathToNode,
argDetails: SimplifiedArgDetails, argDetails: SimplifiedArgDetails,
ast: UnboxedNode<Program>, ast: Program,
programMemory: ProgramMemory programMemory: ProgramMemory
): ):
| { | {
modifiedAst: UnboxedNode<Program> modifiedAst: Program
pathToNodeMap: PathToNodeMap pathToNodeMap: PathToNodeMap
} }
| false { | false {
@ -955,12 +954,12 @@ export function removeSingleConstraintInfo(
} }
export async function deleteFromSelection( export async function deleteFromSelection(
ast: UnboxedNode<Program>, ast: Program,
selection: Selection, selection: Selection,
programMemory: ProgramMemory, programMemory: ProgramMemory,
getFaceDetails: (id: string) => Promise<Models['FaceIsPlanar_type']> = () => getFaceDetails: (id: string) => Promise<Models['FaceIsPlanar_type']> = () =>
({} as any) ({} as any)
): Promise<UnboxedNode<Program> | Error> { ): Promise<Program | Error> {
const astClone = structuredClone(ast) const astClone = structuredClone(ast)
const range = selection.range const range = selection.range
const path = getNodePathFromSourceRange(ast, range) const path = getNodePathFromSourceRange(ast, range)
@ -1135,5 +1134,5 @@ export async function deleteFromSelection(
} }
const nonCodeMetaEmpty = () => { const nonCodeMetaEmpty = () => {
return { nonCodeNodes: {}, startNodes: [], start: 0, end: 0 } return { nonCodeNodes: {}, start: [] }
} }

View File

@ -36,12 +36,11 @@ import {
getSweepFromSuspectedPath, getSweepFromSuspectedPath,
} from 'lang/std/artifactGraph' } from 'lang/std/artifactGraph'
import { kclManager, engineCommandManager, editorManager } from 'lib/singletons' import { kclManager, engineCommandManager, editorManager } from 'lib/singletons'
import { UnboxedNode } from 'wasm-lib/kcl/bindings/UnboxedNode'
// Apply Fillet To Selection // Apply Fillet To Selection
export function applyFilletToSelection( export function applyFilletToSelection(
ast: UnboxedNode<Program>, ast: Program,
selection: Selections, selection: Selections,
radius: KclCommandValue radius: KclCommandValue
): void | Error { ): void | Error {
@ -56,12 +55,10 @@ export function applyFilletToSelection(
} }
export function modifyAstCloneWithFilletAndTag( export function modifyAstCloneWithFilletAndTag(
ast: UnboxedNode<Program>, ast: Program,
selection: Selections, selection: Selections,
radius: KclCommandValue radius: KclCommandValue
): ): { modifiedAst: Program; pathToFilletNode: Array<PathToNode> } | Error {
| { modifiedAst: UnboxedNode<Program>; pathToFilletNode: Array<PathToNode> }
| Error {
let clonedAst = structuredClone(ast) let clonedAst = structuredClone(ast)
const clonedAstForGetExtrude = structuredClone(ast) const clonedAstForGetExtrude = structuredClone(ast)
@ -249,7 +246,7 @@ export function getPathToExtrudeForSegmentSelection(
} }
async function updateAstAndFocus( async function updateAstAndFocus(
modifiedAst: UnboxedNode<Program>, modifiedAst: Program,
pathToFilletNode: Array<PathToNode> pathToFilletNode: Array<PathToNode>
) { ) {
const updatedAst = await kclManager.updateAst(modifiedAst, true, { const updatedAst = await kclManager.updateAst(modifiedAst, true, {
@ -261,7 +258,7 @@ async function updateAstAndFocus(
} }
function mutateAstWithTagForSketchSegment( function mutateAstWithTagForSketchSegment(
astClone: UnboxedNode<Program>, astClone: Program,
pathToSegmentNode: PathToNode pathToSegmentNode: PathToNode
): { modifiedAst: Program; tag: string } | Error { ): { modifiedAst: Program; tag: string } | Error {
const segmentNode = getNodeFromPath<CallExpression>( const segmentNode = getNodeFromPath<CallExpression>(
@ -295,7 +292,7 @@ function mutateAstWithTagForSketchSegment(
function getEdgeTagCall( function getEdgeTagCall(
tag: string, tag: string,
selectionType: string selectionType: string
): UnboxedNode<Identifier | CallExpression> { ): Identifier | CallExpression {
let tagCall: Expr = createIdentifier(tag) let tagCall: Expr = createIdentifier(tag)
// Modify the tag based on selectionType // Modify the tag based on selectionType
@ -429,7 +426,7 @@ export const hasValidFilletSelection = ({
code, code,
}: { }: {
selectionRanges: Selections selectionRanges: Selections
ast: UnboxedNode<Program> ast: Program
code: string code: string
}) => { }) => {
// check if there is anything filletable in the scene // check if there is anything filletable in the scene
@ -457,7 +454,7 @@ export const hasValidFilletSelection = ({
for (const selection of selectionRanges.codeBasedSelections) { for (const selection of selectionRanges.codeBasedSelections) {
// check if all selections are in sketchLineHelperMap // check if all selections are in sketchLineHelperMap
const path = getNodePathFromSourceRange(ast, selection.range) const path = getNodePathFromSourceRange(ast, selection.range)
const segmentNode = getNodeFromPath<UnboxedNode<CallExpression>>( const segmentNode = getNodeFromPath<CallExpression>(
ast, ast,
path, path,
'CallExpression' 'CallExpression'
@ -537,7 +534,7 @@ export const isTagUsedInFillet = ({
ast, ast,
callExp, callExp,
}: { }: {
ast: UnboxedNode<Program> ast: Program
callExp: CallExpression callExp: CallExpression
}): Array<EdgeTypes> => { }): Array<EdgeTypes> => {
const tag = getTagFromCallExpression(callExp) const tag = getTagFromCallExpression(callExp)

View File

@ -29,7 +29,6 @@ import {
} from './std/sketchcombos' } from './std/sketchcombos'
import { err } from 'lib/trap' import { err } from 'lib/trap'
import { ImportStatement } from 'wasm-lib/kcl/bindings/ImportStatement' import { ImportStatement } from 'wasm-lib/kcl/bindings/ImportStatement'
import { UnboxedNode } from 'wasm-lib/kcl/bindings/UnboxedNode'
/** /**
* Retrieves a node from a given path within a Program node structure, optionally stopping at a specified node type. * Retrieves a node from a given path within a Program node structure, optionally stopping at a specified node type.
@ -122,13 +121,12 @@ export function getNodeFromPathCurry(
} }
function moreNodePathFromSourceRange( function moreNodePathFromSourceRange(
node: UnboxedNode< node:
| Expr | Expr
| ImportStatement | ImportStatement
| ExpressionStatement | ExpressionStatement
| VariableDeclaration | VariableDeclaration
| ReturnStatement | ReturnStatement,
>,
sourceRange: Selection['range'], sourceRange: Selection['range'],
previousPath: PathToNode = [['body', '']] previousPath: PathToNode = [['body', '']]
): PathToNode { ): PathToNode {
@ -346,16 +344,15 @@ export function getNodePathFromSourceRange(
return path return path
} }
type KCLNode = UnboxedNode< type KCLNode =
| Expr | Expr
| ExpressionStatement | ExpressionStatement
| VariableDeclaration | VariableDeclaration
| VariableDeclarator | VariableDeclarator
| ReturnStatement | ReturnStatement
>
export function traverse( export function traverse(
node: KCLNode | UnboxedNode<Program>, node: KCLNode | Program,
option: { option: {
enter?: (node: KCLNode, pathToNode: PathToNode) => void enter?: (node: KCLNode, pathToNode: PathToNode) => void
leave?: (node: KCLNode) => void leave?: (node: KCLNode) => void
@ -515,9 +512,9 @@ export function findAllPreviousVariables(
} }
type ReplacerFn = ( type ReplacerFn = (
_ast: UnboxedNode<Program>, _ast: Program,
varName: string varName: string
) => { modifiedAst: UnboxedNode<Program>; pathToReplaced: PathToNode } | Error ) => { modifiedAst: Program; pathToReplaced: PathToNode } | Error
export function isNodeSafeToReplacePath( export function isNodeSafeToReplacePath(
ast: Program, ast: Program,
@ -586,12 +583,12 @@ export function isNodeSafeToReplacePath(
} }
export function isNodeSafeToReplace( export function isNodeSafeToReplace(
ast: UnboxedNode<Program>, ast: Program,
sourceRange: [number, number] sourceRange: [number, number]
): ):
| { | {
isSafe: boolean isSafe: boolean
value: UnboxedNode<Expr> value: Expr
replacer: ReplacerFn replacer: ReplacerFn
} }
| Error { | Error {
@ -720,7 +717,7 @@ export function isLinesParallelAndConstrained(
constraintType === 'angle' || constraintLevel === 'full' constraintType === 'angle' || constraintLevel === 'full'
// get the previous segment // get the previous segment
const prevSegment = sg.value[secondaryIndex - 1] const prevSegment = sg.paths[secondaryIndex - 1]
const prevSourceRange = prevSegment.__geoMeta.sourceRange const prevSourceRange = prevSegment.__geoMeta.sourceRange
const isParallelAndConstrained = const isParallelAndConstrained =
@ -840,7 +837,7 @@ export function findUsesOfTagInPipe(
? String(thirdParam.value) ? String(thirdParam.value)
: thirdParam.name : thirdParam.name
const varDec = getNodeFromPath<UnboxedNode<VariableDeclaration>>( const varDec = getNodeFromPath<VariableDeclaration>(
ast, ast,
pathToNode, pathToNode,
'VariableDeclaration' 'VariableDeclaration'

View File

@ -28,6 +28,7 @@ import {
} from 'lib/constants' } from 'lib/constants'
import { KclManager } from 'lang/KclSingleton' import { KclManager } from 'lang/KclSingleton'
import { reportRejection } from 'lib/trap' import { reportRejection } from 'lib/trap'
import { MachineManager } from 'components/MachineManagerProvider'
// TODO(paultag): This ought to be tweakable. // TODO(paultag): This ought to be tweakable.
const pingIntervalMs = 5_000 const pingIntervalMs = 5_000
@ -50,6 +51,11 @@ export enum ExportIntent {
Make = 'make', Make = 'make',
} }
export interface ExportInfo {
intent: ExportIntent
name: string
}
type ClientMetrics = Models['ClientMetrics_type'] type ClientMetrics = Models['ClientMetrics_type']
interface WebRTCClientMetrics extends ClientMetrics { interface WebRTCClientMetrics extends ClientMetrics {
@ -1354,7 +1360,7 @@ export class EngineCommandManager extends EventTarget {
* export in progress. Otherwise it is an enum value of the intent. * export in progress. Otherwise it is an enum value of the intent.
* Another export cannot be started if one is already in progress. * Another export cannot be started if one is already in progress.
*/ */
private _exportIntent: ExportIntent | null = null private _exportInfo: ExportInfo | null = null
_commandLogCallBack: (command: CommandLog[]) => void = () => {} _commandLogCallBack: (command: CommandLog[]) => void = () => {}
subscriptions: { subscriptions: {
@ -1410,12 +1416,15 @@ export class EngineCommandManager extends EventTarget {
(() => {}) as any (() => {}) as any
kclManager: null | KclManager = null kclManager: null | KclManager = null
set exportIntent(intent: ExportIntent | null) { // The current "manufacturing machine" aka 3D printer, CNC, etc.
this._exportIntent = intent public machineManager: MachineManager | null = null
set exportInfo(info: ExportInfo | null) {
this._exportInfo = info
} }
get exportIntent() { get exportInfo() {
return this._exportIntent return this._exportInfo
} }
start({ start({
@ -1607,7 +1616,7 @@ export class EngineCommandManager extends EventTarget {
// because in all other cases we send JSON strings. But in the case of // because in all other cases we send JSON strings. But in the case of
// export we send a binary blob. // export we send a binary blob.
// Pass this to our export function. // Pass this to our export function.
if (this.exportIntent === null || this.pendingExport === undefined) { if (this.exportInfo === null || this.pendingExport === undefined) {
toast.error( toast.error(
'Export intent was not set, but export data was received' 'Export intent was not set, but export data was received'
) )
@ -1617,7 +1626,7 @@ export class EngineCommandManager extends EventTarget {
return return
} }
switch (this.exportIntent) { switch (this.exportInfo.intent) {
case ExportIntent.Save: { case ExportIntent.Save: {
exportSave(event.data, this.pendingExport.toastId).then(() => { exportSave(event.data, this.pendingExport.toastId).then(() => {
this.pendingExport?.resolve(null) this.pendingExport?.resolve(null)
@ -1625,21 +1634,28 @@ export class EngineCommandManager extends EventTarget {
break break
} }
case ExportIntent.Make: { case ExportIntent.Make: {
exportMake(event.data, this.pendingExport.toastId).then( if (!this.machineManager) {
(result) => { console.warn('Some how, no manufacturing machine is selected.')
break
}
exportMake(
event.data,
this.exportInfo.name,
this.pendingExport.toastId,
this.machineManager
).then((result) => {
if (result) { if (result) {
this.pendingExport?.resolve(null) this.pendingExport?.resolve(null)
} else { } else {
this.pendingExport?.reject('Failed to make export') this.pendingExport?.reject('Failed to make export')
} }
}, }, this.pendingExport?.reject)
this.pendingExport?.reject
)
break break
} }
} }
// Set the export intent back to null. // Set the export intent back to null.
this.exportIntent = null this.exportInfo = null
return return
} }
@ -1953,15 +1969,15 @@ export class EngineCommandManager extends EventTarget {
return Promise.resolve(null) return Promise.resolve(null)
} else if (cmd.type === 'export') { } else if (cmd.type === 'export') {
const promise = new Promise<null>((resolve, reject) => { const promise = new Promise<null>((resolve, reject) => {
if (this.exportIntent === null) { if (this.exportInfo === null) {
if (this.exportIntent === null) { if (this.exportInfo === null) {
toast.error('Export intent was not set, but export is being sent') toast.error('Export intent was not set, but export is being sent')
console.error('Export intent was not set, but export is being sent') console.error('Export intent was not set, but export is being sent')
return return
} }
} }
const toastId = toast.loading( const toastId = toast.loading(
this.exportIntent === ExportIntent.Save this.exportInfo.intent === ExportIntent.Save
? EXPORT_TOAST_MESSAGES.START ? EXPORT_TOAST_MESSAGES.START
: MAKE_TOAST_MESSAGES.START : MAKE_TOAST_MESSAGES.START
) )
@ -1975,7 +1991,7 @@ export class EngineCommandManager extends EventTarget {
resolve(passThrough) resolve(passThrough)
}, },
reject: (reason: string) => { reject: (reason: string) => {
this.exportIntent = null this.exportInfo = null
reject(reason) reject(reason)
}, },
commandId: command.cmd_id, commandId: command.cmd_id,

View File

@ -17,7 +17,6 @@ import {
import { getNodeFromPath, getNodePathFromSourceRange } from '../queryAst' import { getNodeFromPath, getNodePathFromSourceRange } from '../queryAst'
import { enginelessExecutor } from '../../lib/testHelpers' import { enginelessExecutor } from '../../lib/testHelpers'
import { err } from 'lib/trap' import { err } from 'lib/trap'
import { UnboxedNode } from 'wasm-lib/kcl/bindings/UnboxedNode'
const eachQuad: [number, [number, number]][] = [ const eachQuad: [number, [number, number]][] = [
[-315, [1, 1]], [-315, [1, 1]],
@ -688,7 +687,7 @@ describe('testing getConstraintInfo', () => {
] ]
if (err(ast)) return ast if (err(ast)) return ast
const pathToNode = getNodePathFromSourceRange(ast, sourceRange) const pathToNode = getNodePathFromSourceRange(ast, sourceRange)
const callExp = getNodeFromPath<UnboxedNode<CallExpression>>( const callExp = getNodeFromPath<CallExpression>(
ast, ast,
pathToNode, pathToNode,
'CallExpression' 'CallExpression'
@ -842,7 +841,7 @@ describe('testing getConstraintInfo', () => {
] ]
if (err(ast)) return ast if (err(ast)) return ast
const pathToNode = getNodePathFromSourceRange(ast, sourceRange) const pathToNode = getNodePathFromSourceRange(ast, sourceRange)
const callExp = getNodeFromPath<UnboxedNode<CallExpression>>( const callExp = getNodeFromPath<CallExpression>(
ast, ast,
pathToNode, pathToNode,
'CallExpression' 'CallExpression'
@ -1198,7 +1197,7 @@ describe('testing getConstraintInfo', () => {
] ]
if (err(ast)) return ast if (err(ast)) return ast
const pathToNode = getNodePathFromSourceRange(ast, sourceRange) const pathToNode = getNodePathFromSourceRange(ast, sourceRange)
const callExp = getNodeFromPath<UnboxedNode<CallExpression>>( const callExp = getNodeFromPath<CallExpression>(
ast, ast,
pathToNode, pathToNode,
'CallExpression' 'CallExpression'

View File

@ -55,7 +55,6 @@ import { err } from 'lib/trap'
import { perpendicularDistance } from 'sketch-helpers' import { perpendicularDistance } from 'sketch-helpers'
import { TagDeclarator } from 'wasm-lib/kcl/bindings/TagDeclarator' import { TagDeclarator } from 'wasm-lib/kcl/bindings/TagDeclarator'
import { EdgeCutInfo } from 'machines/modelingMachine' import { EdgeCutInfo } from 'machines/modelingMachine'
import { UnboxedNode } from 'wasm-lib/kcl/bindings/UnboxedNode'
const STRAIGHT_SEGMENT_ERR = new Error( const STRAIGHT_SEGMENT_ERR = new Error(
'Invalid input, expected "straight-segment"' 'Invalid input, expected "straight-segment"'
@ -65,7 +64,7 @@ const ARC_SEGMENT_ERR = new Error('Invalid input, expected "arc-segment"')
export type Coords2d = [number, number] export type Coords2d = [number, number]
export function getCoordsFromPaths(skGroup: Sketch, index = 0): Coords2d { export function getCoordsFromPaths(skGroup: Sketch, index = 0): Coords2d {
const currentPath = skGroup?.value?.[index] const currentPath = skGroup?.paths?.[index]
if (!currentPath && skGroup?.start) { if (!currentPath && skGroup?.start) {
return skGroup.start.to return skGroup.start.to
} else if (!currentPath) { } else if (!currentPath) {
@ -1705,7 +1704,7 @@ export const angledLineThatIntersects: SketchLineHelper = {
varName varName
) )
if (err(sketch)) return sketch if (err(sketch)) return sketch
const intersectPath = sketch.value.find( const intersectPath = sketch.paths.find(
({ tag }: Path) => tag && tag.value === intersectTagName ({ tag }: Path) => tag && tag.value === intersectTagName
) )
let offset = 0 let offset = 0
@ -1786,8 +1785,7 @@ export const angledLineThatIntersects: SketchLineHelper = {
) )
} }
if (intersectTag !== -1) { if (intersectTag !== -1) {
const tag = firstArg.properties[intersectTag] const tag = firstArg.properties[intersectTag]?.value as Identifier
?.value as UnboxedNode<Identifier>
const pathToTagProp: PathToNode = [ const pathToTagProp: PathToNode = [
...pathToObjectExp, ...pathToObjectExp,
[intersectTag, 'index'], [intersectTag, 'index'],
@ -1827,9 +1825,7 @@ export const updateStartProfileAtArgs: SketchLineHelper['updateArgs'] = ({
body: [], body: [],
nonCodeMeta: { nonCodeMeta: {
start: 0, start: [],
end: 0,
startNodes: [],
nonCodeNodes: [], nonCodeNodes: [],
}, },
}, },
@ -1869,7 +1865,7 @@ export const sketchLineHelperMap: { [key: string]: SketchLineHelper } = {
} as const } as const
export function changeSketchArguments( export function changeSketchArguments(
node: UnboxedNode<Program>, node: Program,
programMemory: ProgramMemory, programMemory: ProgramMemory,
sourceRangeOrPath: sourceRangeOrPath:
| { | {
@ -1881,7 +1877,7 @@ export function changeSketchArguments(
pathToNode: PathToNode pathToNode: PathToNode
}, },
input: SegmentInputs input: SegmentInputs
): { modifiedAst: UnboxedNode<Program>; pathToNode: PathToNode } | Error { ): { modifiedAst: Program; pathToNode: PathToNode } | Error {
const _node = { ...node } const _node = { ...node }
const thePath = const thePath =
sourceRangeOrPath.type === 'sourceRange' sourceRangeOrPath.type === 'sourceRange'
@ -1910,7 +1906,7 @@ export function changeSketchArguments(
} }
export function getConstraintInfo( export function getConstraintInfo(
callExpression: UnboxedNode<CallExpression>, callExpression: CallExpression,
code: string, code: string,
pathToNode: PathToNode pathToNode: PathToNode
): ConstrainInfo[] { ): ConstrainInfo[] {
@ -1948,7 +1944,7 @@ export function compareVec2Epsilon2(
} }
interface CreateLineFnCallArgs { interface CreateLineFnCallArgs {
node: UnboxedNode<Program> node: Program
programMemory: ProgramMemory programMemory: ProgramMemory
input: SegmentInputs input: SegmentInputs
fnName: ToolTip fnName: ToolTip
@ -1965,7 +1961,7 @@ export function addNewSketchLn({
spliceBetween = false, spliceBetween = false,
}: CreateLineFnCallArgs): }: CreateLineFnCallArgs):
| { | {
modifiedAst: UnboxedNode<Program> modifiedAst: Program
pathToNode: PathToNode pathToNode: PathToNode
} }
| Error { | Error {
@ -1975,12 +1971,8 @@ export function addNewSketchLn({
return new Error('not a sketch line helper') return new Error('not a sketch line helper')
} }
getNodeFromPath<UnboxedNode<VariableDeclarator>>( getNodeFromPath<VariableDeclarator>(node, pathToNode, 'VariableDeclarator')
node, getNodeFromPath<PipeExpression | CallExpression>(
pathToNode,
'VariableDeclarator'
)
getNodeFromPath<UnboxedNode<PipeExpression | CallExpression>>(
node, node,
pathToNode, pathToNode,
'PipeExpression' 'PipeExpression'
@ -1999,13 +1991,13 @@ export function addCallExpressionsToPipe({
pathToNode, pathToNode,
expressions, expressions,
}: { }: {
node: UnboxedNode<Program> node: Program
programMemory: ProgramMemory programMemory: ProgramMemory
pathToNode: PathToNode pathToNode: PathToNode
expressions: UnboxedNode<CallExpression>[] expressions: CallExpression[]
}) { }) {
const _node = { ...node } const _node = { ...node }
const pipeExpression = getNodeFromPath<UnboxedNode<PipeExpression>>( const pipeExpression = getNodeFromPath<PipeExpression>(
_node, _node,
pathToNode, pathToNode,
'PipeExpression' 'PipeExpression'
@ -2054,7 +2046,7 @@ export function replaceSketchLine({
replaceExistingCallback, replaceExistingCallback,
referencedSegment, referencedSegment,
}: { }: {
node: UnboxedNode<Program> node: Program
programMemory: ProgramMemory programMemory: ProgramMemory
pathToNode: PathToNode pathToNode: PathToNode
fnName: ToolTip fnName: ToolTip
@ -2063,7 +2055,7 @@ export function replaceSketchLine({
referencedSegment?: Path referencedSegment?: Path
}): }):
| { | {
modifiedAst: UnboxedNode<Program> modifiedAst: Program
valueUsedInTransform?: number valueUsedInTransform?: number
pathToNode: PathToNode pathToNode: PathToNode
} }
@ -2115,7 +2107,7 @@ function addTagToChamfer(
edgeCutMeta: EdgeCutInfo | null edgeCutMeta: EdgeCutInfo | null
): ):
| { | {
modifiedAst: UnboxedNode<Program> modifiedAst: Program
tag: string tag: string
} }
| Error { | Error {
@ -2242,7 +2234,7 @@ export function addTagForSketchOnFace(
edgeCutMeta: EdgeCutInfo | null edgeCutMeta: EdgeCutInfo | null
): ):
| { | {
modifiedAst: UnboxedNode<Program> modifiedAst: Program
tag: string tag: string
} }
| Error { | Error {
@ -2280,14 +2272,12 @@ function isAngleLiteral(lineArugement: Expr): boolean {
: false : false
} }
type addTagFn = ( type addTagFn = (a: AddTagInfo) => { modifiedAst: Program; tag: string } | Error
a: AddTagInfo
) => { modifiedAst: UnboxedNode<Program>; tag: string } | Error
function addTag(tagIndex = 2): addTagFn { function addTag(tagIndex = 2): addTagFn {
return ({ node, pathToNode }) => { return ({ node, pathToNode }) => {
const _node = { ...node } const _node = { ...node }
const callExpr = getNodeFromPath<UnboxedNode<CallExpression>>( const callExpr = getNodeFromPath<CallExpression>(
_node, _node,
pathToNode, pathToNode,
'CallExpression' 'CallExpression'

View File

@ -18,7 +18,7 @@ export function getSketchSegmentFromPathToNode(
pathToNode: PathToNode pathToNode: PathToNode
): ):
| { | {
segment: Sketch['value'][number] segment: Sketch['paths'][number]
index: number index: number
} }
| Error { | Error {
@ -39,15 +39,15 @@ export function getSketchSegmentFromSourceRange(
[rangeStart, rangeEnd]: SourceRange [rangeStart, rangeEnd]: SourceRange
): ):
| { | {
segment: Sketch['value'][number] segment: Sketch['paths'][number]
index: number index: number
} }
| Error { | Error {
const lineIndex = sketch.value.findIndex( const lineIndex = sketch.paths.findIndex(
({ __geoMeta: { sourceRange } }: Path) => ({ __geoMeta: { sourceRange } }: Path) =>
sourceRange[0] <= rangeStart && sourceRange[1] >= rangeEnd sourceRange[0] <= rangeStart && sourceRange[1] >= rangeEnd
) )
const line = sketch.value[lineIndex] const line = sketch.paths[lineIndex]
if (line) { if (line) {
return { return {
segment: line, segment: line,

View File

@ -49,7 +49,6 @@ import {
getSketchSegmentFromSourceRange, getSketchSegmentFromSourceRange,
} from './sketchConstraints' } from './sketchConstraints'
import { getAngle, roundOff, normaliseAngle } from '../../lib/utils' import { getAngle, roundOff, normaliseAngle } from '../../lib/utils'
import { UnboxedNode } from 'wasm-lib/kcl/bindings/UnboxedNode'
export type LineInputsType = export type LineInputsType =
| 'xAbsolute' | 'xAbsolute'
@ -326,7 +325,7 @@ const setHorzVertDistanceCreateNode =
if (isUndef(refNum) || err(literalArg)) return REF_NUM_ERR if (isUndef(refNum) || err(literalArg)) return REF_NUM_ERR
const valueUsedInTransform = roundOff(literalArg - refNum, 2) const valueUsedInTransform = roundOff(literalArg - refNum, 2)
let finalValue: UnboxedNode<Expr> = createBinaryExpressionWithUnary([ let finalValue: Expr = createBinaryExpressionWithUnary([
createSegEnd(referenceSegName, !index), createSegEnd(referenceSegName, !index),
forceValueUsedInTransform || createLiteral(valueUsedInTransform), forceValueUsedInTransform || createLiteral(valueUsedInTransform),
]) ])
@ -1542,7 +1541,7 @@ export function transformSecondarySketchLinesTagFirst({
forceSegName, forceSegName,
forceValueUsedInTransform, forceValueUsedInTransform,
}: { }: {
ast: UnboxedNode<Program> ast: Program
selectionRanges: Selections selectionRanges: Selections
transformInfos: TransformInfo[] transformInfos: TransformInfo[]
programMemory: ProgramMemory programMemory: ProgramMemory
@ -1550,7 +1549,7 @@ export function transformSecondarySketchLinesTagFirst({
forceValueUsedInTransform?: BinaryPart forceValueUsedInTransform?: BinaryPart
}): }):
| { | {
modifiedAst: UnboxedNode<Program> modifiedAst: Program
valueUsedInTransform?: number valueUsedInTransform?: number
pathToNodeMap: PathToNodeMap pathToNodeMap: PathToNodeMap
tagInfo: { tagInfo: {
@ -1621,7 +1620,7 @@ export function transformAstSketchLines({
forceValueUsedInTransform, forceValueUsedInTransform,
referencedSegmentRange, referencedSegmentRange,
}: { }: {
ast: UnboxedNode<Program> ast: Program
selectionRanges: Selections | PathToNode[] selectionRanges: Selections | PathToNode[]
transformInfos: TransformInfo[] transformInfos: TransformInfo[]
programMemory: ProgramMemory programMemory: ProgramMemory
@ -1630,7 +1629,7 @@ export function transformAstSketchLines({
referencedSegmentRange?: Selection['range'] referencedSegmentRange?: Selection['range']
}): }):
| { | {
modifiedAst: UnboxedNode<Program> modifiedAst: Program
valueUsedInTransform?: number valueUsedInTransform?: number
pathToNodeMap: PathToNodeMap pathToNodeMap: PathToNodeMap
} }
@ -1648,7 +1647,7 @@ export function transformAstSketchLines({
const getNode = getNodeFromPathCurry(node, _pathToNode) const getNode = getNodeFromPathCurry(node, _pathToNode)
const callExp = getNode<UnboxedNode<CallExpression>>('CallExpression') const callExp = getNode<CallExpression>('CallExpression')
if (err(callExp)) return callExp if (err(callExp)) return callExp
const varDec = getNode<VariableDeclarator>('VariableDeclarator') const varDec = getNode<VariableDeclarator>('VariableDeclarator')
if (err(varDec)) return varDec if (err(varDec)) return varDec
@ -1733,7 +1732,7 @@ export function transformAstSketchLines({
if (err(_segment)) return _segment if (err(_segment)) return _segment
referencedSegment = _segment.segment referencedSegment = _segment.segment
} else { } else {
referencedSegment = sketch.value.find( referencedSegment = sketch.paths.find(
(path) => path.tag?.value === _referencedSegmentName (path) => path.tag?.value === _referencedSegmentName
) )
} }
@ -1807,16 +1806,13 @@ function createSegAngle(referenceSegName: string): BinaryPart {
return createCallExpression('segAng', [createIdentifier(referenceSegName)]) return createCallExpression('segAng', [createIdentifier(referenceSegName)])
} }
function createSegEnd( function createSegEnd(referenceSegName: string, isX: boolean): CallExpression {
referenceSegName: string,
isX: boolean
): UnboxedNode<CallExpression> {
return createCallExpression(isX ? 'segEndX' : 'segEndY', [ return createCallExpression(isX ? 'segEndX' : 'segEndY', [
createIdentifier(referenceSegName), createIdentifier(referenceSegName),
]) ])
} }
function createLastSeg(isX: boolean): UnboxedNode<CallExpression> { function createLastSeg(isX: boolean): CallExpression {
return createCallExpression(isX ? 'lastSegX' : 'lastSegY', [ return createCallExpression(isX ? 'lastSegX' : 'lastSegY', [
createPipeSubstitution(), createPipeSubstitution(),
]) ])
@ -1834,7 +1830,7 @@ export function getConstraintLevelFromSourceRange(
ast: Program | Error ast: Program | Error
): Error | { range: [number, number]; level: ConstraintLevel } { ): Error | { range: [number, number]; level: ConstraintLevel } {
if (err(ast)) return ast if (err(ast)) return ast
const nodeMeta = getNodeFromPath<UnboxedNode<CallExpression>>( const nodeMeta = getNodeFromPath<CallExpression>(
ast, ast,
getNodePathFromSourceRange(ast, cursorRange), getNodePathFromSourceRange(ast, cursorRange),
'CallExpression' 'CallExpression'

View File

@ -11,17 +11,16 @@ import {
BinaryPart, BinaryPart,
} from '../wasm' } from '../wasm'
import { LineInputsType } from './sketchcombos' import { LineInputsType } from './sketchcombos'
import { UnboxedNode } from 'wasm-lib/kcl/bindings/UnboxedNode'
export interface ModifyAstBase { export interface ModifyAstBase {
node: UnboxedNode<Program> node: Program
// TODO #896: Remove ProgramMemory from this interface // TODO #896: Remove ProgramMemory from this interface
previousProgramMemory: ProgramMemory previousProgramMemory: ProgramMemory
pathToNode: PathToNode pathToNode: PathToNode
} }
export interface AddTagInfo { export interface AddTagInfo {
node: UnboxedNode<Program> node: Program
pathToNode: PathToNode pathToNode: PathToNode
} }
@ -135,7 +134,7 @@ type _InputArg<T> =
* Which is why a union type is used that can be type narrowed using the {@link RawArg.type} property * Which is why a union type is used that can be type narrowed using the {@link RawArg.type} property
* {@link RawArg.expr} is common to all of these types * {@link RawArg.expr} is common to all of these types
*/ */
export type InputArg = _InputArg<UnboxedNode<Expr>> export type InputArg = _InputArg<Expr>
/** /**
* {@link RawArg.expr} is the literal equivalent of whatever current expression is * {@link RawArg.expr} is the literal equivalent of whatever current expression is
@ -143,7 +142,7 @@ export type InputArg = _InputArg<UnboxedNode<Expr>>
* but of course works for expressions like myVar + someFn() etc too * but of course works for expressions like myVar + someFn() etc too
* This is useful in cases where we want to "un-constrain" inputs to segments * This is useful in cases where we want to "un-constrain" inputs to segments
*/ */
type RawArg = _InputArg<UnboxedNode<Literal>> type RawArg = _InputArg<Literal>
export type InputArgs = Array<InputArg> export type InputArgs = Array<InputArg>
@ -187,7 +186,7 @@ export type CreateStdLibSketchCallExpr = (args: {
inputs: InputArgs inputs: InputArgs
rawArgs: RawArgs rawArgs: RawArgs
referenceSegName: string referenceSegName: string
tag?: UnboxedNode<Expr> tag?: Expr
forceValueUsedInTransform?: BinaryPart forceValueUsedInTransform?: BinaryPart
referencedSegment?: Path referencedSegment?: Path
}) => CreatedSketchExprResult | Error }) => CreatedSketchExprResult | Error
@ -216,26 +215,26 @@ export interface ConstrainInfo {
export interface SketchLineHelper { export interface SketchLineHelper {
add: (a: addCall) => add: (a: addCall) =>
| { | {
modifiedAst: UnboxedNode<Program> modifiedAst: Program
pathToNode: PathToNode pathToNode: PathToNode
valueUsedInTransform?: number valueUsedInTransform?: number
} }
| Error | Error
updateArgs: (a: updateArgs) => updateArgs: (a: updateArgs) =>
| { | {
modifiedAst: UnboxedNode<Program> modifiedAst: Program
pathToNode: PathToNode pathToNode: PathToNode
} }
| Error | Error
getTag: (a: CallExpression) => string | Error getTag: (a: CallExpression) => string | Error
addTag: (a: AddTagInfo) => addTag: (a: AddTagInfo) =>
| { | {
modifiedAst: UnboxedNode<Program> modifiedAst: Program
tag: string tag: string
} }
| Error | Error
getConstraintInfo: ( getConstraintInfo: (
callExp: UnboxedNode<CallExpression>, callExp: CallExpression,
code: string, code: string,
pathToNode: PathToNode pathToNode: PathToNode
) => ConstrainInfo[] ) => ConstrainInfo[]

View File

@ -1,13 +0,0 @@
import { err } from 'lib/trap'
import { parse } from './wasm'
import { enginelessExecutor } from 'lib/testHelpers'
it('can execute parsed AST', async () => {
const code = `x = 1
// A comment.`
const ast = parse(code)
expect(err(ast)).toEqual(false)
const execState = await enginelessExecutor(ast)
expect(err(ast)).toEqual(false)
expect(execState.memory.get('x')).toEqual(1)
})

View File

@ -42,7 +42,6 @@ import { ExecState as RawExecState } from '../wasm-lib/kcl/bindings/ExecState'
import { ProgramMemory as RawProgramMemory } from '../wasm-lib/kcl/bindings/ProgramMemory' import { ProgramMemory as RawProgramMemory } from '../wasm-lib/kcl/bindings/ProgramMemory'
import { EnvironmentRef } from '../wasm-lib/kcl/bindings/EnvironmentRef' import { EnvironmentRef } from '../wasm-lib/kcl/bindings/EnvironmentRef'
import { Environment } from '../wasm-lib/kcl/bindings/Environment' import { Environment } from '../wasm-lib/kcl/bindings/Environment'
import { UnboxedNode } from 'wasm-lib/kcl/bindings/UnboxedNode'
export type { Program } from '../wasm-lib/kcl/bindings/Program' export type { Program } from '../wasm-lib/kcl/bindings/Program'
export type { Expr } from '../wasm-lib/kcl/bindings/Expr' export type { Expr } from '../wasm-lib/kcl/bindings/Expr'
@ -123,11 +122,11 @@ export const initPromise = initialise()
export const rangeTypeFix = (ranges: number[][]): [number, number][] => export const rangeTypeFix = (ranges: number[][]): [number, number][] =>
ranges.map(([start, end]) => [start, end]) ranges.map(([start, end]) => [start, end])
export const parse = (code: string | Error): UnboxedNode<Program> | Error => { export const parse = (code: string | Error): Program | Error => {
if (err(code)) return code if (err(code)) return code
try { try {
const program: UnboxedNode<Program> = parse_wasm(code) const program: Program = parse_wasm(code)
return program return program
} catch (e: any) { } catch (e: any) {
// throw e // throw e
@ -379,7 +378,7 @@ export function sketchFromKclValue(
} }
export const executor = async ( export const executor = async (
node: UnboxedNode<Program>, node: Program,
programMemory: ProgramMemory | Error = ProgramMemory.empty(), programMemory: ProgramMemory | Error = ProgramMemory.empty(),
idGenerator: IdGenerator = defaultIdGenerator(), idGenerator: IdGenerator = defaultIdGenerator(),
engineCommandManager: EngineCommandManager, engineCommandManager: EngineCommandManager,
@ -403,7 +402,7 @@ export const executor = async (
} }
export const _executor = async ( export const _executor = async (
node: UnboxedNode<Program>, node: Program,
programMemory: ProgramMemory | Error = ProgramMemory.empty(), programMemory: ProgramMemory | Error = ProgramMemory.empty(),
idGenerator: IdGenerator = defaultIdGenerator(), idGenerator: IdGenerator = defaultIdGenerator(),
engineCommandManager: EngineCommandManager, engineCommandManager: EngineCommandManager,
@ -494,13 +493,13 @@ export function lexer(str: string): Token[] | Error {
export const modifyAstForSketch = async ( export const modifyAstForSketch = async (
engineCommandManager: EngineCommandManager, engineCommandManager: EngineCommandManager,
ast: UnboxedNode<Program>, ast: Program,
variableName: string, variableName: string,
currentPlane: string, currentPlane: string,
engineId: string engineId: string
): Promise<UnboxedNode<Program>> => { ): Promise<Program> => {
try { try {
const updatedAst: UnboxedNode<Program> = await modify_ast_for_sketch_wasm( const updatedAst: Program = await modify_ast_for_sketch_wasm(
engineCommandManager, engineCommandManager,
JSON.stringify(ast), JSON.stringify(ast),
variableName, variableName,

View File

@ -3,7 +3,6 @@ import { StateMachineCommandSetConfig, KclCommandValue } from 'lib/commandTypes'
import { KCL_DEFAULT_LENGTH, KCL_DEFAULT_DEGREE } from 'lib/constants' import { KCL_DEFAULT_LENGTH, KCL_DEFAULT_DEGREE } from 'lib/constants'
import { components } from 'lib/machine-api' import { components } from 'lib/machine-api'
import { Selections } from 'lib/selections' import { Selections } from 'lib/selections'
import { machineManager } from 'lib/machineManager'
import { modelingMachine, SketchTool } from 'machines/modelingMachine' import { modelingMachine, SketchTool } from 'machines/modelingMachine'
type OutputFormat = Models['OutputFormat_type'] type OutputFormat = Models['OutputFormat_type']
@ -187,9 +186,10 @@ export const modelingMachineCommandConfig: StateMachineCommandSetConfig<
machine.make_model.model || machine.make_model.model ||
machine.make_model.manufacturer || machine.make_model.manufacturer ||
'Unknown Machine', 'Unknown Machine',
options: () => { options: (commandBarContext) => {
return Object.entries(machineManager.machines).map( return Object.values(
([_, machine]) => ({ commandBarContext.machineManager?.machines || []
).map((machine: components['schemas']['MachineInfoResponse']) => ({
name: name:
`${machine.id} (${ `${machine.id} (${
machine.make_model.model || machine.make_model.manufacturer machine.make_model.model || machine.make_model.manufacturer
@ -215,13 +215,12 @@ export const modelingMachineCommandConfig: StateMachineCommandSetConfig<
: ''), : ''),
isCurrent: false, isCurrent: false,
disabled: machine.state.state !== 'idle', disabled: machine.state.state !== 'idle',
value: machine as components['schemas']['MachineInfoResponse'], value: machine,
}) }))
)
}, },
defaultValue: () => { defaultValue: (commandBarContext) => {
return Object.values( return Object.values(
machineManager.machines commandBarContext.machineManager.machines || []
)[0] as components['schemas']['MachineInfoResponse'] )[0] as components['schemas']['MachineInfoResponse']
}, },
}, },

View File

@ -5,7 +5,7 @@ import { Selection } from './selections'
import { Identifier, Expr, VariableDeclaration } from 'lang/wasm' import { Identifier, Expr, VariableDeclaration } from 'lang/wasm'
import { commandBarMachine } from 'machines/commandBarMachine' import { commandBarMachine } from 'machines/commandBarMachine'
import { ReactNode } from 'react' import { ReactNode } from 'react'
import { UnboxedNode } from 'wasm-lib/kcl/bindings/UnboxedNode' import { MachineManager } from 'components/MachineManagerProvider'
type Icon = CustomIconName type Icon = CustomIconName
const PLATFORMS = ['both', 'web', 'desktop'] as const const PLATFORMS = ['both', 'web', 'desktop'] as const
@ -24,8 +24,8 @@ export interface KclExpression {
} }
export interface KclExpressionWithVariable extends KclExpression { export interface KclExpressionWithVariable extends KclExpression {
variableName: string variableName: string
variableDeclarationAst: UnboxedNode<VariableDeclaration> variableDeclarationAst: VariableDeclaration
variableIdentifierAst: UnboxedNode<Identifier> variableIdentifierAst: Identifier
insertIndex: number insertIndex: number
} }
export type KclCommandValue = KclExpression | KclExpressionWithVariable export type KclCommandValue = KclExpression | KclExpressionWithVariable
@ -128,6 +128,7 @@ export type CommandArgumentConfig<
| (( | ((
commandBarContext: { commandBarContext: {
argumentsToSubmit: Record<string, unknown> argumentsToSubmit: Record<string, unknown>
machineManager?: MachineManager
}, // Should be the commandbarMachine's context, but it creates a circular dependency }, // Should be the commandbarMachine's context, but it creates a circular dependency
machineContext?: C machineContext?: C
) => CommandArgumentOption<OutputType>[]) ) => CommandArgumentOption<OutputType>[])

View File

@ -92,6 +92,7 @@ export const MAKE_TOAST_MESSAGES = {
NO_MACHINE_API_IP: 'No machine api ip available', NO_MACHINE_API_IP: 'No machine api ip available',
NO_CURRENT_MACHINE: 'No current machine available', NO_CURRENT_MACHINE: 'No current machine available',
NO_MACHINE_ID: 'No machine id available', NO_MACHINE_ID: 'No machine id available',
NO_NAME: 'No name provided',
ERROR_STARTING_PRINT: 'Error while starting print', ERROR_STARTING_PRINT: 'Error while starting print',
SUCCESS: 'Started print successfully', SUCCESS: 'Started print successfully',
} }

View File

@ -1,5 +1,5 @@
import { deserialize_files } from 'wasm-lib/pkg/wasm_lib' import { deserialize_files } from 'wasm-lib/pkg/wasm_lib'
import { machineManager } from './machineManager' import { MachineManager } from 'components/MachineManagerProvider'
import toast from 'react-hot-toast' import toast from 'react-hot-toast'
import { components } from './machine-api' import { components } from './machine-api'
import ModelingAppFile from './modelingAppFile' import ModelingAppFile from './modelingAppFile'
@ -8,9 +8,17 @@ import { MAKE_TOAST_MESSAGES } from './constants'
// Make files locally from an export call. // Make files locally from an export call.
export async function exportMake( export async function exportMake(
data: ArrayBuffer, data: ArrayBuffer,
toastId: string name: string,
toastId: string,
machineManager: MachineManager
): Promise<Response | null> { ): Promise<Response | null> {
if (machineManager.machineCount() === 0) { if (name === '') {
console.error(MAKE_TOAST_MESSAGES.NO_NAME)
toast.error(MAKE_TOAST_MESSAGES.NO_NAME, { id: toastId })
return null
}
if (machineManager.machines.length === 0) {
console.error(MAKE_TOAST_MESSAGES.NO_MACHINES) console.error(MAKE_TOAST_MESSAGES.NO_MACHINES)
toast.error(MAKE_TOAST_MESSAGES.NO_MACHINES, { id: toastId }) toast.error(MAKE_TOAST_MESSAGES.NO_MACHINES, { id: toastId })
return null return null
@ -39,7 +47,7 @@ export async function exportMake(
const params: components['schemas']['PrintParameters'] = { const params: components['schemas']['PrintParameters'] = {
machine_id: machineId, machine_id: machineId,
job_name: 'Exported Job', // TODO: make this the project name. job_name: name,
} }
try { try {
console.log('params', params) console.log('params', params)

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