Compare commits

...

40 Commits

Author SHA1 Message Date
602f27737f A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu) 2024-08-01 18:47:39 +00:00
38adaf8c68 Fix sketch.ts to be more lenient 2024-08-01 14:36:41 -04:00
971471f45d Fix isNodeType types to be stricter 2024-08-01 13:55:19 -04:00
92b3f6192d Fix executeAstMock to be more lenient 2024-08-01 13:25:54 -04:00
2ff1d1167f Rename function since it's a type assertion, not cast 2024-08-01 13:18:29 -04:00
b2fe72f677 Fix to be more lenient 2024-08-01 13:18:29 -04:00
8e5d13315d Change getNodeFromPath to have more precise types 2024-08-01 13:18:29 -04:00
43a34b191e Upgrade to clap 4.5.13 to fix build error (#3223) 2024-08-01 17:03:05 +00:00
19a93e8deb Cut release v0.24.6 (#3214) 2024-08-01 09:47:25 -04:00
b8c623e1ec sure up test (#3220) 2024-08-01 12:30:08 +00:00
4006c28479 make test fail fast (#3218) 2024-08-01 11:56:59 +00:00
8c932fdb8d unpause vid in next event loop (#3219)
* unpause vid in next event loop

* fmt
2024-08-01 10:53:44 +00:00
a74c715c01 fix 'Engine disconnect & reconnect in sketch mode' test (#3215)
* fix 'Engine disconnect & reconnect in sketch mode' test

* tweak

* tweak 2
2024-08-01 18:39:24 +10:00
1ac39d95f2 Bug fix: prevent KCL error due to colliding AST execution on project switch (#3205)
* Only run "Execute AST" action if defaultUnit setting changes

* A little more logging and catching anywhere we call video.play()
2024-08-01 05:40:14 +00:00
41b1ec94fa Bump clap from 4.5.11 to 4.5.13 in /src/wasm-lib (#3210)
Bumps [clap](https://github.com/clap-rs/clap) from 4.5.11 to 4.5.13.
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.11...v4.5.13)

---
updated-dependencies:
- dependency-name: clap
  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-07-31 22:18:40 -07:00
525c803888 Bump toml from 0.8.17 to 0.8.19 in /src/wasm-lib (#3212)
Bumps [toml](https://github.com/toml-rs/toml) from 0.8.17 to 0.8.19.
- [Commits](https://github.com/toml-rs/toml/compare/toml-v0.8.17...toml-v0.8.19)

---
updated-dependencies:
- dependency-name: toml
  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-07-31 22:18:29 -07:00
2ee1c78aad Add a system for badges to appear on pane buttons (#3208) 2024-08-01 13:29:24 +10:00
dc21034b86 Move KCL programs into their own files (#3200)
* Move KCL programs into their own files

* Move even more
2024-07-31 15:07:56 -05:00
1684786659 Update machine-api spec (#3202)
YOYO NEW API SPEC!

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-07-31 11:19:36 -07:00
12505b4398 Bump toml from 0.8.16 to 0.8.17 in /src/wasm-lib (#3198)
Bumps [toml](https://github.com/toml-rs/toml) from 0.8.16 to 0.8.17.
- [Commits](https://github.com/toml-rs/toml/compare/toml-v0.8.16...toml-v0.8.17)

---
updated-dependencies:
- dependency-name: toml
  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-07-31 11:08:07 -07:00
115f2fdea2 Simplify the KCL stdlib test codegen (#3196)
This will ensure that the KCL snapshot tests all use the same logic, whether they're in `tests/executor/main.rs` or in the KCL stdlib modules.
2024-07-31 09:54:46 -05:00
0df28abc4b Update machine-api spec (#3197)
YOYO NEW API SPEC!

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-07-30 19:57:57 -07:00
1e07ea4986 Use better names for engine/KCL tests (#3193)
'serial_test' isn't actually accurate. Two of these tests run in parallel
now. So I renamed it 'kcl_test' as that's what it's actually doing.

In the nextest config, I changed the label from 'serial-integration' to
'uses-engine' because the former isn't true, and also doesn't explain
_why_ it's being limited. The new name explains why we're limiting the
number of tests that can run in parallel.
2024-07-30 16:12:01 -05:00
f34c23d203 Cut release v0.24.5 (#3191) 2024-07-30 15:28:07 -04:00
5295f0ae7d Fix rectangle tool flakiness (#3190)
* Refactor line tool and rectangle tool to share same "no points" code path

* Remove console.log

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

* Re-run CI

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-07-30 18:16:53 +00:00
07a90b3171 Use kcl_input! macro (#3189)
* Use kcl_input! macro

These two lines are equivalent:
`kcl_input!("foo")`
`include_str!("inputs/foo.kcl")`

Simplifies the tests.

* Move more KCL test programs into their own files

* Move twenty-twenty asserts into their own function

* Move more asserts into 'assert_out'
2024-07-30 11:14:37 -05:00
54936f6932 actually fix lint styles (#3187)
Signed-off-by: Jess Frazelle <github@jessfraz.com>
2024-07-30 07:27:47 +00:00
6e296af507 initialize codemirror lint styles once (#3185)
* fix diagnostic styles

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

* fixes

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

* Revert "fixes"

This reverts commit e7b2411ebc.

* Revert "fix diagnostic styles"

This reverts commit 625099d9c8.

* actual fix

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

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2024-07-30 04:42:05 +00:00
60c152bf14 fix edge functions when after sketch on face/fn (#3184)
Signed-off-by: Jess Frazelle <github@jessfraz.com>
2024-07-30 04:30:25 +00:00
59de494125 Bump kittycad from 0.3.8 to 0.3.9 in /src/wasm-lib (#3183)
Bumps [kittycad](https://github.com/KittyCAD/kittycad.rs) from 0.3.8 to 0.3.9.
- [Release notes](https://github.com/KittyCAD/kittycad.rs/releases)
- [Commits](https://github.com/KittyCAD/kittycad.rs/compare/v0.3.8...v0.3.9)

---
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-07-29 20:49:39 -07:00
1c44b01d16 Fix lazy fillet (#3176)
* WIP: Fix lazy fillet

* cleanup

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

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
Co-authored-by: Jess Frazelle <github@jessfraz.com>
Co-authored-by: Jess Frazelle <jessfraz@users.noreply.github.com>
2024-07-30 03:22:52 +00:00
789fb83a5d ensure we clear _before_ we execute when there is a race (#3177)
* updates

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

* comment

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

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2024-07-29 19:55:53 -07:00
63fc287742 bugfix: KCL Test Server should clear scene properly (#3174)
There was already a Reset Scene method which properly cleaned up the
3D modeling scene. I didn't know about it, so I wrote my own. But my own
one didn't call the necessary post-clear hooks, so it didn't recreate
the default planes.

This PR calls the right Reset Scene method, so the default planes get
recreated after the scene is cleared.
2024-07-29 20:40:07 -05:00
5e1b91b0e7 wrap with retry - wait on error in gutter (#3137)
* wrap with retry - wait on error in gutter

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

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

This reverts commit 2ca97f90a2.

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Kurt Hutten Irev-Dev <k.hutten@protonmail.ch>
2024-07-30 07:16:52 +10:00
a1c2e817a4 internal linter for making sure everything is camel case (#3172)
* updates

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

* add lint rule for object property key

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

* add linter to example shit

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

* fix samples

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

* fix lints

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

* updates

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

* generate docs

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

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2024-07-29 20:18:55 +00:00
6ed4e72e1d KCL execution server can use a local engine (#3171)
Allow the KCL execution server to choose a local engine, instead of just
the remote engine.

Technically this was already possible, via the $LOCAL_ENGINE_ADDR
environment variable. But it was hard to discover this.
2024-07-29 13:43:27 -05:00
6477011c0f Fix to not crash when there's no var declaration (#3168) 2024-07-29 13:09:12 -04:00
cd9dc3e6a5 Move KCL tests into files (#3169) 2024-07-29 12:05:31 -05:00
4b424de5a6 Add a test for onboarding code reset confirmation and persistence (#3167)
* Add a test for onboarding code reset confirmation and persistence

* Don't use PW's `context` it doesn't have our teardown code
2024-07-29 12:50:01 -04:00
0f1b94f8b9 remove suss linter ext we dont use (#3150)
remove suss linter ext we dont use

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2024-07-29 15:41:02 +00:00
148 changed files with 3746 additions and 3527 deletions

View File

@ -124,7 +124,7 @@ const extrusion = extrude(5, sketch001)
* `sketch_group`: `SketchGroup` - A sketch group is a collection of paths. (REQUIRED)
```js
{
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -166,7 +166,7 @@ const extrusion = extrude(5, sketch001)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -180,7 +180,7 @@ const extrusion = extrude(5, sketch001)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -198,7 +198,7 @@ const extrusion = extrude(5, sketch001)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: SketchSurface,

View File

@ -128,7 +128,7 @@ const extrusion = extrude(5, sketch001)
* `sketch_group`: `SketchGroup` - A sketch group is a collection of paths. (REQUIRED)
```js
{
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -170,7 +170,7 @@ const extrusion = extrude(5, sketch001)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -184,7 +184,7 @@ const extrusion = extrude(5, sketch001)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -202,7 +202,7 @@ const extrusion = extrude(5, sketch001)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: SketchSurface,

View File

@ -43,7 +43,7 @@ const example = extrude(10, exampleSketch)
* `sketch_group`: `SketchGroup` - A sketch group is a collection of paths. (REQUIRED)
```js
{
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -85,7 +85,7 @@ const example = extrude(10, exampleSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -99,7 +99,7 @@ const example = extrude(10, exampleSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -117,7 +117,7 @@ const example = extrude(10, exampleSketch)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: SketchSurface,
@ -455,7 +455,7 @@ const example = extrude(10, exampleSketch)
`SketchGroup` - A sketch group is a collection of paths.
```js
{
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -497,7 +497,7 @@ const example = extrude(10, exampleSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -511,7 +511,7 @@ const example = extrude(10, exampleSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -529,7 +529,7 @@ const example = extrude(10, exampleSketch)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: SketchSurface,

View File

@ -42,7 +42,7 @@ const extrusion = extrude(10, sketch001)
* `sketch_group`: `SketchGroup` - A sketch group is a collection of paths. (REQUIRED)
```js
{
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -84,7 +84,7 @@ const extrusion = extrude(10, sketch001)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -98,7 +98,7 @@ const extrusion = extrude(10, sketch001)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -116,7 +116,7 @@ const extrusion = extrude(10, sketch001)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: SketchSurface,
@ -454,7 +454,7 @@ const extrusion = extrude(10, sketch001)
`SketchGroup` - A sketch group is a collection of paths.
```js
{
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -496,7 +496,7 @@ const extrusion = extrude(10, sketch001)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -510,7 +510,7 @@ const extrusion = extrude(10, sketch001)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -528,7 +528,7 @@ const extrusion = extrude(10, sketch001)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: SketchSurface,

View File

@ -44,7 +44,7 @@ const example = extrude(10, exampleSketch)
* `sketch_group`: `SketchGroup` - A sketch group is a collection of paths. (REQUIRED)
```js
{
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -86,7 +86,7 @@ const example = extrude(10, exampleSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -100,7 +100,7 @@ const example = extrude(10, exampleSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -118,7 +118,7 @@ const example = extrude(10, exampleSketch)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: SketchSurface,
@ -456,7 +456,7 @@ const example = extrude(10, exampleSketch)
`SketchGroup` - A sketch group is a collection of paths.
```js
{
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -498,7 +498,7 @@ const example = extrude(10, exampleSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -512,7 +512,7 @@ const example = extrude(10, exampleSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -530,7 +530,7 @@ const example = extrude(10, exampleSketch)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: SketchSurface,

View File

@ -136,7 +136,7 @@ const example = extrude(10, exampleSketch)
* `sketch_group`: `SketchGroup` - A sketch group is a collection of paths. (REQUIRED)
```js
{
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -178,7 +178,7 @@ const example = extrude(10, exampleSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -192,7 +192,7 @@ const example = extrude(10, exampleSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -210,7 +210,7 @@ const example = extrude(10, exampleSketch)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: SketchSurface,
@ -548,7 +548,7 @@ const example = extrude(10, exampleSketch)
`SketchGroup` - A sketch group is a collection of paths.
```js
{
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -590,7 +590,7 @@ const example = extrude(10, exampleSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -604,7 +604,7 @@ const example = extrude(10, exampleSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -622,7 +622,7 @@ const example = extrude(10, exampleSketch)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: SketchSurface,

View File

@ -41,7 +41,7 @@ const example = extrude(10, exampleSketch)
* `sketch_group`: `SketchGroup` - A sketch group is a collection of paths. (REQUIRED)
```js
{
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -83,7 +83,7 @@ const example = extrude(10, exampleSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -97,7 +97,7 @@ const example = extrude(10, exampleSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -115,7 +115,7 @@ const example = extrude(10, exampleSketch)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: SketchSurface,
@ -453,7 +453,7 @@ const example = extrude(10, exampleSketch)
`SketchGroup` - A sketch group is a collection of paths.
```js
{
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -495,7 +495,7 @@ const example = extrude(10, exampleSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -509,7 +509,7 @@ const example = extrude(10, exampleSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -527,7 +527,7 @@ const example = extrude(10, exampleSketch)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: SketchSurface,

View File

@ -41,7 +41,7 @@ const example = extrude(10, exampleSketch)
* `sketch_group`: `SketchGroup` - A sketch group is a collection of paths. (REQUIRED)
```js
{
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -83,7 +83,7 @@ const example = extrude(10, exampleSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -97,7 +97,7 @@ const example = extrude(10, exampleSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -115,7 +115,7 @@ const example = extrude(10, exampleSketch)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: SketchSurface,
@ -453,7 +453,7 @@ const example = extrude(10, exampleSketch)
`SketchGroup` - A sketch group is a collection of paths.
```js
{
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -495,7 +495,7 @@ const example = extrude(10, exampleSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -509,7 +509,7 @@ const example = extrude(10, exampleSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -527,7 +527,7 @@ const example = extrude(10, exampleSketch)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: SketchSurface,

View File

@ -19,8 +19,8 @@ const exampleSketch = startSketchOn('XZ')
|> startProfileAt([0, 0], %)
|> line([10, 0], %)
|> arc({
angle_start: 0,
angle_end: 280,
angleStart: 0,
angleEnd: 280,
radius: 16
}, %)
|> close(%)
@ -34,9 +34,9 @@ const exampleSketch = startSketchOn('XZ')
```js
{
// The end angle.
angle_end: number,
angleEnd: number,
// The start angle.
angle_start: number,
angleStart: number,
// The radius.
radius: number,
} |
@ -52,7 +52,7 @@ const exampleSketch = startSketchOn('XZ')
* `sketch_group`: `SketchGroup` - A sketch group is a collection of paths. (REQUIRED)
```js
{
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -94,7 +94,7 @@ const exampleSketch = startSketchOn('XZ')
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -108,7 +108,7 @@ const exampleSketch = startSketchOn('XZ')
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -126,7 +126,7 @@ const exampleSketch = startSketchOn('XZ')
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: SketchSurface,
@ -464,7 +464,7 @@ const exampleSketch = startSketchOn('XZ')
`SketchGroup` - A sketch group is a collection of paths.
```js
{
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -506,7 +506,7 @@ const exampleSketch = startSketchOn('XZ')
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -520,7 +520,7 @@ const exampleSketch = startSketchOn('XZ')
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -538,7 +538,7 @@ const exampleSketch = startSketchOn('XZ')
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: SketchSurface,

View File

@ -47,7 +47,7 @@ const example = extrude(10, exampleSketch)
* `sketch_group`: `SketchGroup` - A sketch group is a collection of paths. (REQUIRED)
```js
{
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -89,7 +89,7 @@ const example = extrude(10, exampleSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -103,7 +103,7 @@ const example = extrude(10, exampleSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -121,7 +121,7 @@ const example = extrude(10, exampleSketch)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: SketchSurface,
@ -459,7 +459,7 @@ const example = extrude(10, exampleSketch)
`SketchGroup` - A sketch group is a collection of paths.
```js
{
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -501,7 +501,7 @@ const example = extrude(10, exampleSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -515,7 +515,7 @@ const example = extrude(10, exampleSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -533,7 +533,7 @@ const example = extrude(10, exampleSketch)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: SketchSurface,

View File

@ -149,7 +149,7 @@ const mountingPlate = extrude(thickness, mountingPlateSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -163,7 +163,7 @@ const mountingPlate = extrude(thickness, mountingPlateSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -181,7 +181,7 @@ const mountingPlate = extrude(thickness, mountingPlateSketch)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -223,7 +223,7 @@ const mountingPlate = extrude(thickness, mountingPlateSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -237,7 +237,7 @@ const mountingPlate = extrude(thickness, mountingPlateSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -549,7 +549,7 @@ const mountingPlate = extrude(thickness, mountingPlateSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -563,7 +563,7 @@ const mountingPlate = extrude(thickness, mountingPlateSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -581,7 +581,7 @@ const mountingPlate = extrude(thickness, mountingPlateSketch)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -623,7 +623,7 @@ const mountingPlate = extrude(thickness, mountingPlateSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -637,7 +637,7 @@ const mountingPlate = extrude(thickness, mountingPlateSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,

View File

@ -82,7 +82,7 @@ const example = extrude(5, exampleSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -96,7 +96,7 @@ const example = extrude(5, exampleSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -114,7 +114,7 @@ const example = extrude(5, exampleSketch)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: SketchSurface,
@ -324,7 +324,7 @@ const example = extrude(5, exampleSketch)
},
} |
{
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -366,7 +366,7 @@ const example = extrude(5, exampleSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -380,7 +380,7 @@ const example = extrude(5, exampleSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -619,7 +619,7 @@ const example = extrude(5, exampleSketch)
`SketchGroup` - A sketch group is a collection of paths.
```js
{
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -661,7 +661,7 @@ const example = extrude(5, exampleSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -675,7 +675,7 @@ const example = extrude(5, exampleSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -693,7 +693,7 @@ const example = extrude(5, exampleSketch)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: SketchSurface,

View File

@ -42,7 +42,7 @@ const example = extrude(10, exampleSketch)
* `sketch_group`: `SketchGroup` - A sketch group is a collection of paths. (REQUIRED)
```js
{
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -84,7 +84,7 @@ const example = extrude(10, exampleSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -98,7 +98,7 @@ const example = extrude(10, exampleSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -116,7 +116,7 @@ const example = extrude(10, exampleSketch)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: SketchSurface,
@ -454,7 +454,7 @@ const example = extrude(10, exampleSketch)
`SketchGroup` - A sketch group is a collection of paths.
```js
{
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -496,7 +496,7 @@ const example = extrude(10, exampleSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -510,7 +510,7 @@ const example = extrude(10, exampleSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -528,7 +528,7 @@ const example = extrude(10, exampleSketch)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: SketchSurface,

View File

@ -19,8 +19,8 @@ const example = startSketchOn('XZ')
|> startProfileAt([0, 0], %)
|> line([10, 0], %)
|> arc({
angle_end: 0,
angle_start: 120,
angleStart: 120,
angleEnd: 0,
radius: 5
}, %)
|> line([5, 0], %)
@ -41,8 +41,8 @@ const example = startSketchOn('XZ')
const exampleSketch = startSketchOn('XZ')
|> startProfileAt([-10, 0], %)
|> arc({
angle_end: -60,
angle_start: 120,
angleStart: 120,
angleEnd: -60,
radius: 5
}, %)
|> line([10, 0], %)
@ -67,7 +67,7 @@ const example = extrude(10, exampleSketch)
* `sketch_group_set`: `SketchGroupSet` - A sketch group or a group of sketch groups. (REQUIRED)
```js
{
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -109,7 +109,7 @@ const example = extrude(10, exampleSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -123,7 +123,7 @@ const example = extrude(10, exampleSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -141,7 +141,7 @@ const example = extrude(10, exampleSketch)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: SketchSurface,
@ -479,7 +479,7 @@ const example = extrude(10, exampleSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -493,7 +493,7 @@ const example = extrude(10, exampleSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -511,7 +511,7 @@ const example = extrude(10, exampleSketch)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -553,7 +553,7 @@ const example = extrude(10, exampleSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -567,7 +567,7 @@ const example = extrude(10, exampleSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,

View File

@ -149,7 +149,7 @@ const mountingPlate = extrude(thickness, mountingPlateSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -163,7 +163,7 @@ const mountingPlate = extrude(thickness, mountingPlateSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -181,7 +181,7 @@ const mountingPlate = extrude(thickness, mountingPlateSketch)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -223,7 +223,7 @@ const mountingPlate = extrude(thickness, mountingPlateSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -237,7 +237,7 @@ const mountingPlate = extrude(thickness, mountingPlateSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -549,7 +549,7 @@ const mountingPlate = extrude(thickness, mountingPlateSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -563,7 +563,7 @@ const mountingPlate = extrude(thickness, mountingPlateSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -581,7 +581,7 @@ const mountingPlate = extrude(thickness, mountingPlateSketch)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -623,7 +623,7 @@ const mountingPlate = extrude(thickness, mountingPlateSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -637,7 +637,7 @@ const mountingPlate = extrude(thickness, mountingPlateSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,

View File

@ -19,10 +19,9 @@ const part001 = startSketchOn('XY')
|> circle([5, 5], 10, %)
|> extrude(10, %)
|> helix({
angle_start: 0,
angleStart: 0,
ccw: true,
revolutions: 16,
angle_start: 0
revolutions: 16
}, %)
```
@ -34,7 +33,7 @@ const part001 = startSketchOn('XY')
```js
{
// Start angle (in degrees).
angle_start: number,
angleStart: number,
// Is the helix rotation counter clockwise? The default is `false`.
ccw: string,
// Length of the helix. If this argument is not provided, the height of the extrude group is used.
@ -51,7 +50,7 @@ const part001 = startSketchOn('XY')
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -65,7 +64,7 @@ const part001 = startSketchOn('XY')
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -83,7 +82,7 @@ const part001 = startSketchOn('XY')
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -125,7 +124,7 @@ const part001 = startSketchOn('XY')
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -139,7 +138,7 @@ const part001 = startSketchOn('XY')
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -442,7 +441,7 @@ const part001 = startSketchOn('XY')
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -456,7 +455,7 @@ const part001 = startSketchOn('XY')
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -474,7 +473,7 @@ const part001 = startSketchOn('XY')
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -516,7 +515,7 @@ const part001 = startSketchOn('XY')
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -530,7 +529,7 @@ const part001 = startSketchOn('XY')
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,

View File

@ -53,7 +53,7 @@ const example = extrude(1, exampleSketch)
* `hole_sketch_group`: `SketchGroupSet` - A sketch group or a group of sketch groups. (REQUIRED)
```js
{
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -95,7 +95,7 @@ const example = extrude(1, exampleSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -109,7 +109,7 @@ const example = extrude(1, exampleSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -127,7 +127,7 @@ const example = extrude(1, exampleSketch)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: SketchSurface,
@ -457,7 +457,7 @@ const example = extrude(1, exampleSketch)
* `sketch_group`: `SketchGroup` - A sketch group is a collection of paths. (REQUIRED)
```js
{
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -499,7 +499,7 @@ const example = extrude(1, exampleSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -513,7 +513,7 @@ const example = extrude(1, exampleSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -531,7 +531,7 @@ const example = extrude(1, exampleSketch)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: SketchSurface,
@ -860,7 +860,7 @@ const example = extrude(1, exampleSketch)
`SketchGroup` - A sketch group is a collection of paths.
```js
{
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -902,7 +902,7 @@ const example = extrude(1, exampleSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -916,7 +916,7 @@ const example = extrude(1, exampleSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -934,7 +934,7 @@ const example = extrude(1, exampleSketch)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: SketchSurface,

View File

@ -33,7 +33,7 @@ const example = extrude(5, exampleSketch)
* `sketch_group`: `SketchGroup` - A sketch group is a collection of paths. (REQUIRED)
```js
{
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -75,7 +75,7 @@ const example = extrude(5, exampleSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -89,7 +89,7 @@ const example = extrude(5, exampleSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -107,7 +107,7 @@ const example = extrude(5, exampleSketch)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: SketchSurface,

View File

@ -33,7 +33,7 @@ const example = extrude(5, exampleSketch)
* `sketch_group`: `SketchGroup` - A sketch group is a collection of paths. (REQUIRED)
```js
{
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -75,7 +75,7 @@ const example = extrude(5, exampleSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -89,7 +89,7 @@ const example = extrude(5, exampleSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -107,7 +107,7 @@ const example = extrude(5, exampleSketch)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: SketchSurface,

View File

@ -46,7 +46,7 @@ const example = extrude(5, exampleSketch)
* `sketch_group`: `SketchGroup` - A sketch group is a collection of paths. (REQUIRED)
```js
{
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -88,7 +88,7 @@ const example = extrude(5, exampleSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -102,7 +102,7 @@ const example = extrude(5, exampleSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -120,7 +120,7 @@ const example = extrude(5, exampleSketch)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: SketchSurface,
@ -458,7 +458,7 @@ const example = extrude(5, exampleSketch)
`SketchGroup` - A sketch group is a collection of paths.
```js
{
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -500,7 +500,7 @@ const example = extrude(5, exampleSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -514,7 +514,7 @@ const example = extrude(5, exampleSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -532,7 +532,7 @@ const example = extrude(5, exampleSketch)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: SketchSurface,

View File

@ -33,7 +33,7 @@ const example = extrude(5, exampleSketch)
* `sketch_group`: `SketchGroup` - A sketch group is a collection of paths. (REQUIRED)
```js
{
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -75,7 +75,7 @@ const example = extrude(5, exampleSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -89,7 +89,7 @@ const example = extrude(5, exampleSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -107,7 +107,7 @@ const example = extrude(5, exampleSketch)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: SketchSurface,
@ -445,7 +445,7 @@ const example = extrude(5, exampleSketch)
`SketchGroup` - A sketch group is a collection of paths.
```js
{
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -487,7 +487,7 @@ const example = extrude(5, exampleSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -501,7 +501,7 @@ const example = extrude(5, exampleSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -519,7 +519,7 @@ const example = extrude(5, exampleSketch)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: SketchSurface,

View File

@ -51,7 +51,7 @@ const example = extrude(1, exampleSketch)
* `sketch_group_set`: `SketchGroupSet` - A sketch group or a group of sketch groups. (REQUIRED)
```js
{
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -93,7 +93,7 @@ const example = extrude(1, exampleSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -107,7 +107,7 @@ const example = extrude(1, exampleSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -125,7 +125,7 @@ const example = extrude(1, exampleSketch)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: SketchSurface,

View File

@ -55,7 +55,7 @@ const example = extrude(-5, exampleSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -69,7 +69,7 @@ const example = extrude(-5, exampleSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -87,7 +87,7 @@ const example = extrude(-5, exampleSketch)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -129,7 +129,7 @@ const example = extrude(-5, exampleSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -143,7 +143,7 @@ const example = extrude(-5, exampleSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,

View File

@ -44,7 +44,7 @@ const example = extrude(1, exampleSketch)
* `sketch_group_set`: `SketchGroupSet` - A sketch group or a group of sketch groups. (REQUIRED)
```js
{
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -86,7 +86,7 @@ const example = extrude(1, exampleSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -100,7 +100,7 @@ const example = extrude(1, exampleSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -118,7 +118,7 @@ const example = extrude(1, exampleSketch)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: SketchSurface,

View File

@ -53,7 +53,7 @@ const example = extrude(1, exampleSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -67,7 +67,7 @@ const example = extrude(1, exampleSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -85,7 +85,7 @@ const example = extrude(1, exampleSketch)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -127,7 +127,7 @@ const example = extrude(1, exampleSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -141,7 +141,7 @@ const example = extrude(1, exampleSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,

View File

@ -55,7 +55,7 @@ let vase = layer()
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -69,7 +69,7 @@ let vase = layer()
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -87,7 +87,7 @@ let vase = layer()
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -129,7 +129,7 @@ let vase = layer()
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -143,7 +143,7 @@ let vase = layer()
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,

View File

@ -34,7 +34,7 @@ const sketch001 = startSketchOn('XY')
* `sketch_group`: `SketchGroup` - A sketch group is a collection of paths. (REQUIRED)
```js
{
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -76,7 +76,7 @@ const sketch001 = startSketchOn('XY')
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -90,7 +90,7 @@ const sketch001 = startSketchOn('XY')
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -108,7 +108,7 @@ const sketch001 = startSketchOn('XY')
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: SketchSurface,

View File

@ -29,7 +29,7 @@ const sketch001 = startSketchOn('XY')
* `sketch_group`: `SketchGroup` - A sketch group is a collection of paths. (REQUIRED)
```js
{
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -71,7 +71,7 @@ const sketch001 = startSketchOn('XY')
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -85,7 +85,7 @@ const sketch001 = startSketchOn('XY')
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -103,7 +103,7 @@ const sketch001 = startSketchOn('XY')
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: SketchSurface,

View File

@ -28,7 +28,7 @@ const sketch001 = startSketchOn('XY')
* `sketch_group`: `SketchGroup` - A sketch group is a collection of paths. (REQUIRED)
```js
{
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -70,7 +70,7 @@ const sketch001 = startSketchOn('XY')
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -84,7 +84,7 @@ const sketch001 = startSketchOn('XY')
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -102,7 +102,7 @@ const sketch001 = startSketchOn('XY')
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: SketchSurface,

View File

@ -250,7 +250,7 @@ uuid |
* `sketch_group`: `SketchGroup` - A sketch group is a collection of paths. (REQUIRED)
```js
{
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -292,7 +292,7 @@ uuid |
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -306,7 +306,7 @@ uuid |
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -324,7 +324,7 @@ uuid |
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: SketchSurface,
@ -658,7 +658,7 @@ uuid |
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -672,7 +672,7 @@ uuid |
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -690,7 +690,7 @@ uuid |
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -732,7 +732,7 @@ uuid |
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -746,7 +746,7 @@ uuid |
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,

View File

@ -137,7 +137,7 @@ shell({ faces: ['end'], thickness: 0.25 }, firstSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -151,7 +151,7 @@ shell({ faces: ['end'], thickness: 0.25 }, firstSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -169,7 +169,7 @@ shell({ faces: ['end'], thickness: 0.25 }, firstSketch)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -211,7 +211,7 @@ shell({ faces: ['end'], thickness: 0.25 }, firstSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -225,7 +225,7 @@ shell({ faces: ['end'], thickness: 0.25 }, firstSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -528,7 +528,7 @@ shell({ faces: ['end'], thickness: 0.25 }, firstSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -542,7 +542,7 @@ shell({ faces: ['end'], thickness: 0.25 }, firstSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -560,7 +560,7 @@ shell({ faces: ['end'], thickness: 0.25 }, firstSketch)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -602,7 +602,7 @@ shell({ faces: ['end'], thickness: 0.25 }, firstSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -616,7 +616,7 @@ shell({ faces: ['end'], thickness: 0.25 }, firstSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,

View File

@ -97,7 +97,7 @@ const example = extrude(5, exampleSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -111,7 +111,7 @@ const example = extrude(5, exampleSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -129,7 +129,7 @@ const example = extrude(5, exampleSketch)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -411,7 +411,7 @@ const example = extrude(5, exampleSketch)
`SketchGroup` - A sketch group is a collection of paths.
```js
{
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -453,7 +453,7 @@ const example = extrude(5, exampleSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -467,7 +467,7 @@ const example = extrude(5, exampleSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -485,7 +485,7 @@ const example = extrude(5, exampleSketch)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: SketchSurface,

View File

@ -59,7 +59,7 @@ const example = extrude(5, exampleSketch)
`SketchGroup` - A sketch group is a collection of paths.
```js
{
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -101,7 +101,7 @@ const example = extrude(5, exampleSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -115,7 +115,7 @@ const example = extrude(5, exampleSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -133,7 +133,7 @@ const example = extrude(5, exampleSketch)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: SketchSurface,

View File

@ -106,9 +106,9 @@ const example002 = extrude(5, exampleSketch002)
const a1 = startSketchOn({
plane: {
origin: { x: 0, y: 0, z: 0 },
x_axis: { x: 1, y: 0, z: 0 },
y_axis: { x: 0, y: 1, z: 0 },
z_axis: { x: 0, y: 0, z: 1 }
xAxis: { x: 1, y: 0, z: 0 },
yAxis: { x: 0, y: 1, z: 0 },
zAxis: { x: 0, y: 0, z: 1 }
}
})
|> startProfileAt([0, 0], %)
@ -141,19 +141,19 @@ const a1 = startSketchOn({
z: number,
},
// What should the planes X axis be?
x_axis: {
xAxis: {
x: number,
y: number,
z: number,
},
// What should the planes Y axis be?
y_axis: {
yAxis: {
x: number,
y: number,
z: number,
},
// The z-axis (normal).
z_axis: {
zAxis: {
x: number,
y: number,
z: number,
@ -166,7 +166,7 @@ const a1 = startSketchOn({
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -180,7 +180,7 @@ const a1 = startSketchOn({
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -198,7 +198,7 @@ const a1 = startSketchOn({
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -578,7 +578,7 @@ const a1 = startSketchOn({
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -592,7 +592,7 @@ const a1 = startSketchOn({
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -610,7 +610,7 @@ const a1 = startSketchOn({
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {

File diff suppressed because it is too large Load Diff

View File

@ -42,7 +42,7 @@ const example = extrude(10, exampleSketch)
* `sketch_group`: `SketchGroup` - A sketch group is a collection of paths. (REQUIRED)
```js
{
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -84,7 +84,7 @@ const example = extrude(10, exampleSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -98,7 +98,7 @@ const example = extrude(10, exampleSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -116,7 +116,7 @@ const example = extrude(10, exampleSketch)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: SketchSurface,
@ -454,7 +454,7 @@ const example = extrude(10, exampleSketch)
`SketchGroup` - A sketch group is a collection of paths.
```js
{
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -496,7 +496,7 @@ const example = extrude(10, exampleSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -510,7 +510,7 @@ const example = extrude(10, exampleSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -528,7 +528,7 @@ const example = extrude(10, exampleSketch)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: SketchSurface,

View File

@ -33,7 +33,7 @@ const example = extrude(10, exampleSketch)
* `sketch_group`: `SketchGroup` - A sketch group is a collection of paths. (REQUIRED)
```js
{
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -75,7 +75,7 @@ const example = extrude(10, exampleSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -89,7 +89,7 @@ const example = extrude(10, exampleSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -107,7 +107,7 @@ const example = extrude(10, exampleSketch)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: SketchSurface,
@ -445,7 +445,7 @@ const example = extrude(10, exampleSketch)
`SketchGroup` - A sketch group is a collection of paths.
```js
{
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -487,7 +487,7 @@ const example = extrude(10, exampleSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -501,7 +501,7 @@ const example = extrude(10, exampleSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -519,7 +519,7 @@ const example = extrude(10, exampleSketch)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: SketchSurface,

View File

@ -36,7 +36,7 @@ const example = extrude(10, exampleSketch)
* `sketch_group`: `SketchGroup` - A sketch group is a collection of paths. (REQUIRED)
```js
{
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -78,7 +78,7 @@ const example = extrude(10, exampleSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -92,7 +92,7 @@ const example = extrude(10, exampleSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -110,7 +110,7 @@ const example = extrude(10, exampleSketch)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: SketchSurface,
@ -448,7 +448,7 @@ const example = extrude(10, exampleSketch)
`SketchGroup` - A sketch group is a collection of paths.
```js
{
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -490,7 +490,7 @@ const example = extrude(10, exampleSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -504,7 +504,7 @@ const example = extrude(10, exampleSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -522,7 +522,7 @@ const example = extrude(10, exampleSketch)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: SketchSurface,

View File

@ -36,7 +36,7 @@ const example = extrude(10, exampleSketch)
* `sketch_group`: `SketchGroup` - A sketch group is a collection of paths. (REQUIRED)
```js
{
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -78,7 +78,7 @@ const example = extrude(10, exampleSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -92,7 +92,7 @@ const example = extrude(10, exampleSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -110,7 +110,7 @@ const example = extrude(10, exampleSketch)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: SketchSurface,
@ -448,7 +448,7 @@ const example = extrude(10, exampleSketch)
`SketchGroup` - A sketch group is a collection of paths.
```js
{
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -490,7 +490,7 @@ const example = extrude(10, exampleSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -504,7 +504,7 @@ const example = extrude(10, exampleSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -522,7 +522,7 @@ const example = extrude(10, exampleSketch)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: SketchSurface,

View File

@ -34,7 +34,7 @@ const example = extrude(10, exampleSketch)
* `sketch_group`: `SketchGroup` - A sketch group is a collection of paths. (REQUIRED)
```js
{
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -76,7 +76,7 @@ const example = extrude(10, exampleSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -90,7 +90,7 @@ const example = extrude(10, exampleSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -108,7 +108,7 @@ const example = extrude(10, exampleSketch)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: SketchSurface,
@ -446,7 +446,7 @@ const example = extrude(10, exampleSketch)
`SketchGroup` - A sketch group is a collection of paths.
```js
{
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -488,7 +488,7 @@ const example = extrude(10, exampleSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -502,7 +502,7 @@ const example = extrude(10, exampleSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -520,7 +520,7 @@ const example = extrude(10, exampleSketch)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: SketchSurface,

View File

@ -32,7 +32,7 @@ const example = extrude(5, exampleSketch)
* `sketch_group`: `SketchGroup` - A sketch group is a collection of paths. (REQUIRED)
```js
{
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -74,7 +74,7 @@ const example = extrude(5, exampleSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -88,7 +88,7 @@ const example = extrude(5, exampleSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -106,7 +106,7 @@ const example = extrude(5, exampleSketch)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: SketchSurface,
@ -444,7 +444,7 @@ const example = extrude(5, exampleSketch)
`SketchGroup` - A sketch group is a collection of paths.
```js
{
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: {
@ -486,7 +486,7 @@ const example = extrude(5, exampleSketch)
// Chamfers or fillets on this extrude group.
filletOrChamfers: [{
// The engine id of the edge to fillet.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this fillet.
id: uuid,
radius: number,
@ -500,7 +500,7 @@ const example = extrude(5, exampleSketch)
} |
{
// The engine id of the edge to chamfer.
edge_id: uuid,
edgeId: uuid,
// The id of the engine command that called this chamfer.
id: uuid,
length: number,
@ -518,7 +518,7 @@ const example = extrude(5, exampleSketch)
id: uuid,
// The sketch group.
sketchGroup: {
// The id of the sketch group.
// The id of the sketch group (this will change when the engine's reference to it changes.
id: uuid,
// What the sketch is on (can be a plane or a face).
on: SketchSurface,

View File

@ -925,10 +925,10 @@ test.describe('Editor tests', () => {
await expect(page.locator('.cm-lint-marker-error')).toBeVisible()
await expect(
page.locator('.cm-lintRange.cm-lintRange-error').first()
page.locator('.cm-lint-marker.cm-lint-marker-error')
).toBeVisible()
await page.locator('.cm-lintRange.cm-lintRange-error').hover()
await page.locator('.cm-lint-marker.cm-lint-marker-error').hover()
await expect(page.locator('.cm-diagnosticText').first()).toBeVisible()
await expect(
page.getByText('Cannot redefine `topAng`').first()
@ -1045,7 +1045,7 @@ test.describe('Editor tests', () => {
await page.hover('.cm-lint-marker-error')
const searchText =
'sketch profile must lie entirely on one side of the revolution axis'
await expect(page.getByText(searchText).first()).toBeVisible()
await expect(page.getByText(searchText)).toBeVisible()
})
test.describe('Autocomplete works', () => {
test('with enter/click to accept the completion', async ({ page }) => {
@ -2265,6 +2265,50 @@ test.describe('Onboarding tests', () => {
await expect(page.locator('.cm-content')).toContainText('// Shelf Bracket')
})
test('Code resets after confirmation', async ({ page }) => {
const initialCode = `const sketch001 = startSketchOn('XZ')`
// Load the page up with some code so we see the confirmation warning
// when we go to replay onboarding
await page.addInitScript((code) => {
localStorage.setItem('persistCode', code)
}, initialCode)
const u = await getUtils(page)
await page.setViewportSize({ width: 1200, height: 500 })
await u.waitForAuthSkipAppStart()
// Replay the onboarding
await page.getByRole('link', { name: 'Settings' }).last().click()
const replayButton = page.getByRole('button', { name: 'Replay onboarding' })
await expect(replayButton).toBeVisible()
await replayButton.click()
// Ensure we see the warning, and that the code has not yet updated
await expect(
page.getByText('Replaying onboarding resets your code')
).toBeVisible()
await expect(page.locator('.cm-content')).toHaveText(initialCode)
const nextButton = page.getByTestId('onboarding-next')
await expect(nextButton).toBeVisible()
await nextButton.click()
// Ensure we see the introduction and that the code has been reset
await expect(page.getByText('Welcome to Modeling App!')).toBeVisible()
await expect(page.locator('.cm-content')).toContainText('// Shelf Bracket')
// Ensure we persisted the code to local storage.
// Playwright's addInitScript method unfortunately will reset
// this code if we try reloading the page as a test,
// so this is our best way to test persistence afaik.
expect(
await page.evaluate(() => {
return localStorage.getItem('persistCode')
})
).toContain('// Shelf Bracket')
})
test('Click through each onboarding step', async ({ page }) => {
const u = await getUtils(page)
@ -3975,16 +4019,19 @@ test.describe('Regression tests', () => {
)
})
await page.goto('/')
await u.waitForPageLoad()
// error in guter
await expect(page.locator('.cm-lint-marker-error')).toBeVisible()
await page.waitForTimeout(200)
// expect it still to be there (sometimes it just clears for a bit?)
await expect(page.locator('.cm-lint-marker-error')).toBeVisible({
timeout: 10_000,
})
await expect(async () => {
await page.goto('/')
await u.waitForPageLoad()
// error in guter
await expect(page.locator('.cm-lint-marker-error')).toBeVisible({
timeout: 1_000,
})
await page.waitForTimeout(200)
// expect it still to be there (sometimes it just clears for a bit?)
await expect(page.locator('.cm-lint-marker-error')).toBeVisible({
timeout: 1_000,
})
}).toPass({ timeout: 40_000, intervals: [1_000] })
// error text on hover
await page.hover('.cm-lint-marker-error')
@ -4132,12 +4179,15 @@ test.describe('Sketch tests', () => {
await page.setViewportSize({ width: 1200, height: 500 })
await u.waitForAuthSkipAppStart()
await page.getByText('tangentialArcTo([24.95, -5.38], %)').click()
await expect(
page.getByRole('button', { name: 'Edit Sketch' })
).toBeEnabled()
await page.getByRole('button', { name: 'Edit Sketch' }).click()
await expect(async () => {
await page.mouse.click(700, 200)
await page.getByText('tangentialArcTo([24.95, -5.38], %)').click()
await expect(
page.getByRole('button', { name: 'Edit Sketch' })
).toBeEnabled({ timeout: 1000 })
await page.getByRole('button', { name: 'Edit Sketch' }).click()
}).toPass({ timeout: 40_000, intervals: [1_000] })
await page.waitForTimeout(600) // wait for animation
@ -7243,15 +7293,15 @@ test.describe('Test network and connection issues', () => {
.toHaveText(`const sketch001 = startSketchOn('XZ')
|> startProfileAt(${commonPoints.startAt}, %)
|> line([${commonPoints.num1}, 0], %)
|> line([-9.16, 8.81], %)`)
|> line([-8.84, 8.75], %)`)
await page.waitForTimeout(100)
await page.mouse.click(startXPx, 500 - PUR * 20)
await expect(page.locator('.cm-content'))
.toHaveText(`const sketch001 = startSketchOn('XZ')
|> startProfileAt(${commonPoints.startAt}, %)
|> line([${commonPoints.num1}, 0], %)
|> line([-9.16, 8.81], %)
|> line([-5.28, 0], %)`)
|> line([-8.84, 8.75], %)
|> line([-5.6, 0], %)`)
// Unequip line tool
await page.keyboard.press('Escape')
@ -8047,3 +8097,34 @@ test('Sketch on face', async ({ page }) => {
const sketch002 = extrude(${[5, 5]} + 7, sketch002)`
await expect(page.locator('.cm-content')).toHaveText(result2.regExp)
})
test('Typing KCL errors induces a badge on the error logs pane button', async ({
page,
}) => {
const u = await getUtils(page)
// Load the app with the working starter code
await page.addInitScript((code) => {
localStorage.setItem('persistCode', code)
}, bracket)
await page.setViewportSize({ width: 1200, height: 500 })
await u.waitForAuthSkipAppStart()
// wait for execution done
await u.openDebugPanel()
await u.expectCmdLog('[data-message-type="execution-done"]')
await u.closeDebugPanel()
// Ensure no badge is present
const errorLogsButton = page.getByRole('button', { name: 'KCL Errors pane' })
await expect(errorLogsButton).not.toContainText('notification')
// Delete a character to break the KCL
await u.openKclCodePanel()
await page.getByText('extrude(').click()
await page.keyboard.press('Backspace')
// Ensure that a badge appears on the button
await expect(errorLogsButton).toContainText('notification')
})

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 39 KiB

View File

@ -266,7 +266,7 @@ export async function getUtils(page: Page) {
getSegmentBodyCoords: async (locator: string, px = 30) => {
const overlay = page.locator(locator)
const bbox = await overlay
.boundingBox()
.boundingBox({ timeout: 5000 })
.then((box) => ({ ...box, x: box?.x || 0, y: box?.y || 0 }))
const angle = Number(await overlay.getAttribute('data-overlay-angle'))
const angleXOffset = Math.cos(((angle - 180) * Math.PI) / 180) * px

340
openapi/machine-api.json Normal file
View File

@ -0,0 +1,340 @@
{
"components": {
"responses": {
"Error": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
},
"description": "Error"
}
},
"schemas": {
"Error": {
"description": "Error information from a response.",
"properties": {
"error_code": {
"type": "string"
},
"message": {
"type": "string"
},
"request_id": {
"type": "string"
}
},
"required": [
"message",
"request_id"
],
"type": "object"
},
"Machine": {
"description": "Details for a 3d printer connected over USB.",
"oneOf": [
{
"description": "Details for a 3d printer connected over USB.",
"properties": {
"id": {
"type": "string"
},
"manufacturer": {
"type": "string"
},
"model": {
"type": "string"
},
"port": {
"type": "string"
},
"type": {
"enum": [
"UsbPrinter"
],
"type": "string"
}
},
"required": [
"id",
"manufacturer",
"model",
"port",
"type"
],
"type": "object"
},
{
"description": "Details for a 3d printer connected over USB.",
"properties": {
"hostname": {
"description": "The hostname of the printer.",
"nullable": true,
"type": "string"
},
"ip": {
"description": "The IP address of the printer.",
"format": "ip",
"type": "string"
},
"manufacturer": {
"allOf": [
{
"$ref": "#/components/schemas/NetworkPrinterManufacturer"
}
],
"description": "The manufacturer of the printer."
},
"model": {
"description": "The model of the printer.",
"nullable": true,
"type": "string"
},
"port": {
"description": "The port of the printer.",
"format": "uint16",
"minimum": 0,
"nullable": true,
"type": "integer"
},
"serial": {
"description": "The serial number of the printer.",
"nullable": true,
"type": "string"
},
"type": {
"enum": [
"NetworkPrinter"
],
"type": "string"
}
},
"required": [
"ip",
"manufacturer",
"type"
],
"type": "object"
}
]
},
"NetworkPrinterManufacturer": {
"description": "Network printer manufacturer.",
"oneOf": [
{
"description": "Bambu.",
"enum": [
"Bambu"
],
"type": "string"
},
{
"description": "Formlabs.",
"enum": [
"Formlabs"
],
"type": "string"
}
]
},
"Pong": {
"description": "The response from the `/ping` endpoint.",
"properties": {
"message": {
"description": "The pong response.",
"type": "string"
}
},
"required": [
"message"
],
"type": "object"
},
"PrintJobResponse": {
"description": "The response from the `/print` endpoint.",
"properties": {
"job_id": {
"description": "The job id used for this print.",
"type": "string"
},
"parameters": {
"allOf": [
{
"$ref": "#/components/schemas/PrintParameters"
}
],
"description": "The parameters used for this print."
}
},
"required": [
"job_id",
"parameters"
],
"type": "object"
},
"PrintParameters": {
"description": "Parameters for printing.",
"properties": {
"machine_id": {
"type": "string"
}
},
"required": [
"machine_id"
],
"type": "object"
}
}
},
"info": {
"contact": {
"email": "machine-api@zoo.dev",
"url": "https://zoo.dev"
},
"description": "",
"title": "machine-api",
"version": "0.1.0"
},
"openapi": "3.0.3",
"paths": {
"/": {
"get": {
"operationId": "api_get_schema",
"responses": {
"200": {
"content": {
"application/json": {
"schema": {}
}
},
"description": "successful operation"
},
"4XX": {
"$ref": "#/components/responses/Error"
},
"5XX": {
"$ref": "#/components/responses/Error"
}
},
"summary": "Return the OpenAPI schema in JSON format.",
"tags": [
"meta"
]
}
},
"/machines": {
"get": {
"operationId": "get_machines",
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"additionalProperties": {
"$ref": "#/components/schemas/Machine"
},
"title": "Map_of_Machine",
"type": "object"
}
}
},
"description": "successful operation"
},
"4XX": {
"$ref": "#/components/responses/Error"
},
"5XX": {
"$ref": "#/components/responses/Error"
}
},
"summary": "List available machines and their statuses",
"tags": [
"print"
]
}
},
"/ping": {
"get": {
"operationId": "ping",
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Pong"
}
}
},
"description": "successful operation"
},
"4XX": {
"$ref": "#/components/responses/Error"
},
"5XX": {
"$ref": "#/components/responses/Error"
}
},
"summary": "Return pong.",
"tags": [
"meta"
]
}
},
"/print": {
"post": {
"operationId": "print_file",
"requestBody": {
"content": {
"multipart/form-data": {
"schema": {
"format": "binary",
"type": "string"
}
}
},
"required": true
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/PrintJobResponse"
}
}
},
"description": "successful operation"
},
"4XX": {
"$ref": "#/components/responses/Error"
},
"5XX": {
"$ref": "#/components/responses/Error"
}
},
"summary": "Print a given file. File must be a sliceable 3D model.",
"tags": [
"print"
]
}
}
},
"tags": [
{
"description": "Meta information about the API.",
"externalDocs": {
"url": "https://docs.zoo.dev/api/meta"
},
"name": "meta"
},
{
"description": "Utilities for printing and discovering printers.",
"externalDocs": {
"url": "https://docs.zoo.dev/api/print"
},
"name": "print"
}
]
}

View File

@ -1,6 +1,6 @@
{
"name": "untitled-app",
"version": "0.24.4",
"version": "0.24.6",
"private": true,
"dependencies": {
"@codemirror/autocomplete": "^6.17.0",

View File

@ -1,12 +0,0 @@
import { Extension } from '@codemirror/state'
import { linter, forEachDiagnostic, Diagnostic } from '@codemirror/lint'
export default function lspLintExt(): Extension {
return linter((view) => {
let diagnostics: Diagnostic[] = []
forEachDiagnostic(view.state, (d: Diagnostic, from: number, to: number) => {
diagnostics.push(d)
})
return diagnostics
})
}

View File

@ -17,8 +17,8 @@ import type {
PluginSpec,
ViewPlugin,
} from '@codemirror/view'
import { setDiagnosticsEffect } from '@codemirror/lint'
import { EditorView, Tooltip } from '@codemirror/view'
import { linter } from '@codemirror/lint'
import type { PublishDiagnosticsParams } from 'vscode-languageserver-protocol'
import type * as LSP from 'vscode-languageserver-protocol'
@ -36,7 +36,6 @@ import lspAutocompleteExt from './autocomplete'
import lspHoverExt from './hover'
import lspFormatExt from './format'
import lspIndentExt from './indent'
import lspLintExt from './lint'
import lspSemanticTokensExt from './semantic-tokens'
const useLast = (values: readonly any[]) => values.reduce((_, v) => v, '')
@ -216,20 +215,6 @@ export class LanguageServerPlugin implements PluginValue {
if (!this.client.ready) return
// TODO(paultag): This is the *wrong* place for this to live.
//
// We need to clear diagnostics before updating the code, because
// if the code shrinks, the errors/diagnostics can go out of range
// of the source code, which cause an exception, breaking all the
// things.
//
// We need some sort of clear diagnostics boolean on the editor
// and we can drop this.
this.view.dispatch({
effects: [setDiagnosticsEffect.of([])],
annotations: [],
})
try {
// Update the state (not the editor) with the new code.
this.client.textDocumentDidChange({
@ -587,8 +572,8 @@ export class LanguageServerPluginSpec
lspFormatExt(plugin),
lspHoverExt(plugin),
lspIndentExt(),
lspLintExt(),
lspSemanticTokensExt(),
linter(null),
]
}
}

197
src-tauri/Cargo.lock generated
View File

@ -188,7 +188,7 @@ dependencies = [
"tauri-plugin-shell",
"tauri-plugin-updater",
"tokio",
"toml 0.8.14",
"toml 0.8.19",
"url",
]
@ -332,7 +332,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.71",
"syn 2.0.72",
]
[[package]]
@ -367,7 +367,7 @@ checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.71",
"syn 2.0.72",
]
[[package]]
@ -407,7 +407,7 @@ checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.71",
"syn 2.0.72",
]
[[package]]
@ -550,7 +550,7 @@ dependencies = [
"proc-macro-crate 3.1.0",
"proc-macro2",
"quote",
"syn 2.0.71",
"syn 2.0.72",
"syn_derive",
]
@ -648,6 +648,12 @@ version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "byteorder-lite"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495"
[[package]]
name = "bytes"
version = "1.6.0"
@ -721,7 +727,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a969e13a7589e9e3e4207e153bae624ade2b5622fb4684a4923b23ec3d57719"
dependencies = [
"serde",
"toml 0.8.14",
"toml 0.8.19",
]
[[package]]
@ -792,9 +798,9 @@ dependencies = [
[[package]]
name = "clap"
version = "4.5.9"
version = "4.5.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64acc1846d54c1fe936a78dc189c34e28d3f5afc348403f28ecf53660b9b8462"
checksum = "0fbb260a053428790f3de475e304ff84cdbc4face759ea7a3e64c1edd938a7fc"
dependencies = [
"clap_builder",
"clap_derive",
@ -802,9 +808,9 @@ dependencies = [
[[package]]
name = "clap_builder"
version = "4.5.9"
version = "4.5.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6fb8393d67ba2e7bfaf28a23458e4e2b543cc73a99595511eb207fdb8aede942"
checksum = "64b17d7ea74e9f833c7dbf2cbe4fb12ff26783eda4782a8975b72f895c9b4d99"
dependencies = [
"anstream",
"anstyle",
@ -816,14 +822,14 @@ dependencies = [
[[package]]
name = "clap_derive"
version = "4.5.8"
version = "4.5.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bac35c6dafb060fd4d275d9a4ffae97917c13a6327903a8be2153cd964f7085"
checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0"
dependencies = [
"heck 0.5.0",
"proc-macro2",
"quote",
"syn 2.0.71",
"syn 2.0.72",
]
[[package]]
@ -1073,7 +1079,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331"
dependencies = [
"quote",
"syn 2.0.71",
"syn 2.0.72",
]
[[package]]
@ -1083,7 +1089,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "edb49164822f3ee45b17acd4a208cfc1251410cf0cad9a833234c9890774dd9f"
dependencies = [
"quote",
"syn 2.0.71",
"syn 2.0.72",
]
[[package]]
@ -1107,7 +1113,7 @@ dependencies = [
"proc-macro2",
"quote",
"strsim 0.10.0",
"syn 2.0.71",
"syn 2.0.72",
]
[[package]]
@ -1118,7 +1124,7 @@ checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f"
dependencies = [
"darling_core",
"quote",
"syn 2.0.71",
"syn 2.0.72",
]
[[package]]
@ -1179,7 +1185,7 @@ checksum = "4078275de501a61ceb9e759d37bdd3d7210e654dbc167ac1a3678ef4435ed57b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.71",
"syn 2.0.72",
"synstructure",
]
@ -1206,7 +1212,7 @@ dependencies = [
[[package]]
name = "derive-docs"
version = "0.1.20"
version = "0.1.21"
dependencies = [
"Inflector",
"convert_case 0.6.0",
@ -1216,7 +1222,7 @@ dependencies = [
"regex",
"serde",
"serde_tokenstream",
"syn 2.0.71",
"syn 2.0.72",
]
[[package]]
@ -1227,7 +1233,7 @@ checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.71",
"syn 2.0.72",
]
[[package]]
@ -1288,7 +1294,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.71",
"syn 2.0.72",
]
[[package]]
@ -1320,7 +1326,7 @@ checksum = "f2b99bf03862d7f545ebc28ddd33a665b50865f4dfd84031a393823879bd4c54"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.71",
"syn 2.0.72",
]
[[package]]
@ -1383,7 +1389,7 @@ dependencies = [
"cc",
"memchr",
"rustc_version",
"toml 0.8.14",
"toml 0.8.19",
"vswhom",
"winreg 0.52.0",
]
@ -1427,7 +1433,7 @@ checksum = "5c785274071b1b420972453b306eeca06acf4633829db4223b58a2a8c5953bc4"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.71",
"syn 2.0.72",
]
[[package]]
@ -1588,7 +1594,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.71",
"syn 2.0.72",
]
[[package]]
@ -1704,7 +1710,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.71",
"syn 2.0.72",
]
[[package]]
@ -1980,7 +1986,7 @@ dependencies = [
"proc-macro-error",
"proc-macro2",
"quote",
"syn 2.0.71",
"syn 2.0.72",
]
[[package]]
@ -2008,7 +2014,7 @@ dependencies = [
"inflections",
"proc-macro2",
"quote",
"syn 2.0.71",
"syn 2.0.72",
]
[[package]]
@ -2083,7 +2089,7 @@ dependencies = [
"proc-macro-error",
"proc-macro2",
"quote",
"syn 2.0.71",
"syn 2.0.72",
]
[[package]]
@ -2399,6 +2405,18 @@ dependencies = [
"unicode-normalization",
]
[[package]]
name = "image"
version = "0.25.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99314c8a2152b8ddb211f924cdae532d8c5e4c8bb54728e12fff1b0cd5963a10"
dependencies = [
"bytemuck",
"byteorder-lite",
"num-traits",
"png",
]
[[package]]
name = "indexmap"
version = "1.9.3"
@ -2571,7 +2589,7 @@ dependencies = [
[[package]]
name = "kcl-lib"
version = "0.2.0"
version = "0.2.3"
dependencies = [
"anyhow",
"approx",
@ -2581,6 +2599,7 @@ dependencies = [
"bson",
"chrono",
"clap",
"convert_case 0.6.0",
"dashmap 6.0.1",
"databake",
"derive-docs",
@ -2588,6 +2607,7 @@ dependencies = [
"futures",
"git_rev",
"gltf-json",
"image",
"js-sys",
"kittycad",
"lazy_static",
@ -2602,7 +2622,7 @@ dependencies = [
"thiserror",
"tokio",
"tokio-tungstenite",
"toml 0.8.14",
"toml 0.8.19",
"tower-lsp",
"ts-rs",
"url",
@ -2628,9 +2648,9 @@ dependencies = [
[[package]]
name = "kittycad"
version = "0.3.7"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1777b503442fa4666564cc3ab237d456df853a09648a4b2bb09622d25d021a5"
checksum = "36b87a9cca545825ba18005c1944b8525fac28867d99984178bf22c79fb5ec25"
dependencies = [
"anyhow",
"async-trait",
@ -3368,7 +3388,7 @@ dependencies = [
"regex",
"regex-syntax 0.8.3",
"structmeta",
"syn 2.0.71",
"syn 2.0.72",
]
[[package]]
@ -3487,7 +3507,7 @@ dependencies = [
"phf_shared 0.11.2",
"proc-macro2",
"quote",
"syn 2.0.71",
"syn 2.0.72",
]
[[package]]
@ -3519,9 +3539,9 @@ dependencies = [
[[package]]
name = "phonenumber"
version = "0.3.5+8.13.36"
version = "0.3.6+8.13.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f174c8db59b620032bd52b655fc97000458850fec0db35fcd4e802b668517ec0"
checksum = "11756237b57b8cc5e97dc8b1e70ea436324d30e7075de63b14fd15073a8f692a"
dependencies = [
"bincode",
"either",
@ -3555,7 +3575,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.71",
"syn 2.0.72",
]
[[package]]
@ -4429,7 +4449,7 @@ dependencies = [
"proc-macro2",
"quote",
"serde_derive_internals",
"syn 2.0.71",
"syn 2.0.72",
]
[[package]]
@ -4549,7 +4569,7 @@ checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.71",
"syn 2.0.72",
]
[[package]]
@ -4560,17 +4580,18 @@ checksum = "330f01ce65a3a5fe59a60c82f3c9a024b573b8a6e875bd233fe5f934e71d54e3"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.71",
"syn 2.0.72",
]
[[package]]
name = "serde_json"
version = "1.0.120"
version = "1.0.121"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5"
checksum = "4ab380d7d9f22ef3f21ad3e6c1ebe8e4fc7a2000ccba2e4d71fc96f15b2cb609"
dependencies = [
"indexmap 2.2.6",
"itoa 1.0.11",
"memchr",
"ryu",
"serde",
]
@ -4593,14 +4614,14 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.71",
"syn 2.0.72",
]
[[package]]
name = "serde_spanned"
version = "0.6.6"
version = "0.6.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0"
checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d"
dependencies = [
"serde",
]
@ -4614,7 +4635,7 @@ dependencies = [
"proc-macro2",
"quote",
"serde",
"syn 2.0.71",
"syn 2.0.72",
]
[[package]]
@ -4656,7 +4677,7 @@ dependencies = [
"darling",
"proc-macro2",
"quote",
"syn 2.0.71",
"syn 2.0.72",
]
[[package]]
@ -4924,7 +4945,7 @@ dependencies = [
"proc-macro2",
"quote",
"structmeta-derive",
"syn 2.0.71",
"syn 2.0.72",
]
[[package]]
@ -4935,7 +4956,7 @@ checksum = "152a0b65a590ff6c3da95cabe2353ee04e6167c896b28e3b14478c2636c922fc"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.71",
"syn 2.0.72",
]
[[package]]
@ -4957,7 +4978,7 @@ dependencies = [
"proc-macro2",
"quote",
"rustversion",
"syn 2.0.71",
"syn 2.0.72",
]
[[package]]
@ -4990,9 +5011,9 @@ dependencies = [
[[package]]
name = "syn"
version = "2.0.71"
version = "2.0.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b146dcf730474b4bcd16c311627b31ede9ab149045db4d6088b3becaea046462"
checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af"
dependencies = [
"proc-macro2",
"quote",
@ -5008,7 +5029,7 @@ dependencies = [
"proc-macro-error",
"proc-macro2",
"quote",
"syn 2.0.71",
"syn 2.0.72",
]
[[package]]
@ -5025,7 +5046,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.71",
"syn 2.0.72",
]
[[package]]
@ -5067,7 +5088,7 @@ dependencies = [
"cfg-expr",
"heck 0.5.0",
"pkg-config",
"toml 0.8.14",
"toml 0.8.19",
"version-compare",
]
@ -5220,7 +5241,7 @@ dependencies = [
"serde_json",
"tauri-utils",
"tauri-winres",
"toml 0.8.14",
"toml 0.8.19",
"walkdir",
]
@ -5242,7 +5263,7 @@ dependencies = [
"serde",
"serde_json",
"sha2",
"syn 2.0.71",
"syn 2.0.72",
"tauri-utils",
"thiserror",
"time",
@ -5260,7 +5281,7 @@ dependencies = [
"heck 0.5.0",
"proc-macro2",
"quote",
"syn 2.0.71",
"syn 2.0.72",
"tauri-codegen",
"tauri-utils",
]
@ -5278,7 +5299,7 @@ dependencies = [
"serde",
"serde_json",
"tauri-utils",
"toml 0.8.14",
"toml 0.8.19",
"walkdir",
]
@ -5562,7 +5583,7 @@ dependencies = [
"serde_with",
"swift-rs",
"thiserror",
"toml 0.8.14",
"toml 0.8.19",
"url",
"urlpattern",
"walkdir",
@ -5618,22 +5639,22 @@ checksum = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c"
[[package]]
name = "thiserror"
version = "1.0.62"
version = "1.0.63"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2675633b1499176c2dff06b0856a27976a8f9d436737b4cf4f312d4d91d8bbb"
checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.62"
version = "1.0.63"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d20468752b09f49e909e55a5d338caa8bedf615594e9d80bc4c565d30faf798c"
checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.71",
"syn 2.0.72",
]
[[package]]
@ -5730,7 +5751,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.71",
"syn 2.0.72",
]
[[package]]
@ -5809,21 +5830,21 @@ dependencies = [
[[package]]
name = "toml"
version = "0.8.14"
version = "0.8.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f49eb2ab21d2f26bd6db7bf383edc527a7ebaee412d17af4d40fdccd442f335"
checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e"
dependencies = [
"serde",
"serde_spanned",
"toml_datetime",
"toml_edit 0.22.14",
"toml_edit 0.22.20",
]
[[package]]
name = "toml_datetime"
version = "0.6.6"
version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf"
checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41"
dependencies = [
"serde",
]
@ -5865,15 +5886,15 @@ dependencies = [
[[package]]
name = "toml_edit"
version = "0.22.14"
version = "0.22.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f21c7aaf97f1bd9ca9d4f9e73b0a6c74bd5afef56f2bc931943a6e1c37e04e38"
checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d"
dependencies = [
"indexmap 2.2.6",
"serde",
"serde_spanned",
"toml_datetime",
"winnow 0.6.6",
"winnow 0.6.18",
]
[[package]]
@ -5930,7 +5951,7 @@ checksum = "84fd902d4e0b9a4b27f2f440108dc034e1758628a9b702f8ec61ad66355422fa"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.71",
"syn 2.0.72",
]
[[package]]
@ -5959,7 +5980,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.71",
"syn 2.0.72",
]
[[package]]
@ -6089,7 +6110,7 @@ checksum = "c88cc88fd23b5a04528f3a8436024f20010a16ec18eb23c164b1242f65860130"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.71",
"syn 2.0.72",
"termcolor",
]
@ -6306,7 +6327,7 @@ dependencies = [
"proc-macro-error",
"proc-macro2",
"quote",
"syn 2.0.71",
"syn 2.0.72",
]
[[package]]
@ -6405,7 +6426,7 @@ dependencies = [
"once_cell",
"proc-macro2",
"quote",
"syn 2.0.71",
"syn 2.0.72",
"wasm-bindgen-shared",
]
@ -6439,7 +6460,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.71",
"syn 2.0.72",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
@ -6580,7 +6601,7 @@ checksum = "ac1345798ecd8122468840bcdf1b95e5dc6d2206c5e4b0eafa078d061f59c9bc"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.71",
"syn 2.0.72",
]
[[package]]
@ -6686,7 +6707,7 @@ checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.71",
"syn 2.0.72",
]
[[package]]
@ -6697,7 +6718,7 @@ checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.71",
"syn 2.0.72",
]
[[package]]
@ -6944,9 +6965,9 @@ dependencies = [
[[package]]
name = "winnow"
version = "0.6.6"
version = "0.6.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0c976aaaa0e1f90dbb21e9587cdaf1d9679a1cde8875c0d6bd83ab96a208352"
checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f"
dependencies = [
"memchr",
]
@ -7149,7 +7170,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.71",
"syn 2.0.72",
]
[[package]]

View File

@ -80,5 +80,5 @@
}
},
"productName": "Zoo Modeling App",
"version": "0.24.4"
"version": "0.24.6"
}

View File

@ -5,7 +5,7 @@ import { cameraMouseDragGuards } from 'lib/cameraControls'
import { useSettingsAuthContext } from 'hooks/useSettingsAuthContext'
import { ARROWHEAD, DEBUG_SHOW_BOTH_SCENES } from './sceneInfra'
import { ReactCameraProperties } from './CameraControls'
import { throttle } from 'lib/utils'
import { isArray, throttle } from 'lib/utils'
import {
sceneInfra,
kclManager,
@ -20,13 +20,17 @@ import {
getParentGroup,
} from './sceneEntities'
import { SegmentOverlay, SketchDetails } from 'machines/modelingMachine'
import { findUsesOfTagInPipe, getNodeFromPath } from 'lang/queryAst'
import {
expectNodeOnPath,
findUsesOfTagInPipe,
getLastNodeFromPath,
getNodeFromPath,
} from 'lang/queryAst'
import {
CallExpression,
PathToNode,
Program,
SourceRange,
Value,
parse,
recast,
} from 'lang/wasm'
@ -186,13 +190,12 @@ const Overlay = ({
let xAlignment = overlay.angle < 0 ? '0%' : '-100%'
let yAlignment = overlay.angle < -90 || overlay.angle >= 90 ? '0%' : '-100%'
const _node1 = getNodeFromPath<CallExpression>(
const callExpression = expectNodeOnPath<CallExpression>(
kclManager.ast,
overlay.pathToNode,
'CallExpression'
)
if (err(_node1)) return
const callExpression = _node1.node
if (err(callExpression)) return
const constraints = getConstraintInfo(
callExpression,
@ -549,13 +552,13 @@ const ConstraintSymbol = ({
varNameMap[_type as LineInputsType]?.implicitConstraintDesc
const _node = useMemo(
() => getNodeFromPath<Value>(kclManager.ast, pathToNode),
() => getLastNodeFromPath(kclManager.ast, pathToNode),
[kclManager.ast, pathToNode]
)
if (err(_node)) return
const node = _node.node
const range: SourceRange = node ? [node.start, node.end] : [0, 0]
const range: SourceRange = !isArray(node) ? [node.start, node.end] : [0, 0]
if (_type === 'intersectionTag') return null

View File

@ -27,6 +27,7 @@ import {
defaultPlaneColor,
getSceneScale,
INTERSECTION_PLANE_LAYER,
OnClickCallbackArgs,
OnMouseEnterLeaveArgs,
RAYCASTABLE_PLANE,
SEGMENT_LENGTH_LABEL,
@ -60,7 +61,12 @@ import {
codeManager,
editorManager,
} from 'lib/singletons'
import { getNodeFromPath, getNodePathFromSourceRange } from 'lang/queryAst'
import {
isNodeType,
expectNodeOnPath,
getNodeFromPath,
getNodePathFromSourceRange,
} from 'lang/queryAst'
import { executeAst } from 'lang/langHelpers'
import {
createArcGeometry,
@ -76,8 +82,15 @@ import {
changeSketchArguments,
updateStartProfileAtArgs,
} from 'lang/std/sketch'
import { isOverlap, normaliseAngle, roundOff, throttle } from 'lib/utils'
import {
isArray,
isOverlap,
normaliseAngle,
roundOff,
throttle,
} from 'lib/utils'
import {
addStartProfileAt,
createArrayExpression,
createCallExpressionStdLib,
createLiteral,
@ -296,6 +309,51 @@ export class SceneEntities {
if (intersectionPlane) this.scene.remove(intersectionPlane)
}
setupNoPointsListener({
sketchDetails,
afterClick,
}: {
sketchDetails: SketchDetails
afterClick: (args: OnClickCallbackArgs) => void
}) {
// Create a THREEjs plane to raycast clicks onto
this.createIntersectionPlane()
const quaternion = quaternionFromUpNForward(
new Vector3(...sketchDetails.yAxis),
new Vector3(...sketchDetails.zAxis)
)
// Position the click raycast plane
if (this.intersectionPlane) {
this.intersectionPlane.setRotationFromQuaternion(quaternion)
this.intersectionPlane.position.copy(
new Vector3(...(sketchDetails?.origin || [0, 0, 0]))
)
}
sceneInfra.setCallbacks({
onClick: async (args) => {
if (!args) return
if (args.mouseEvent.which !== 1) return
const { intersectionPoint } = args
if (!intersectionPoint?.twoD || !sketchDetails?.sketchPathToNode) return
const addStartProfileAtRes = addStartProfileAt(
kclManager.ast,
sketchDetails.sketchPathToNode,
[intersectionPoint.twoD.x, intersectionPoint.twoD.y]
)
if (trap(addStartProfileAtRes)) return
const { modifiedAst } = addStartProfileAtRes
await kclManager.updateAst(modifiedAst, false)
this.removeIntersectionPlane()
// Now perform the caller-specified action
afterClick(args)
},
})
}
async setupSketch({
sketchPathToNode,
forward,
@ -416,13 +474,18 @@ export class SceneEntities {
)
let seg: Group
const _node1 = getNodeFromPath<CallExpression>(
const callExp = getNodeFromPath<CallExpression>(
maybeModdedAst,
segPathToNode,
'CallExpression'
)
if (err(_node1)) return
const callExpName = _node1.node?.callee?.name
if (err(callExp)) return
const callExpName = isNodeType<CallExpression>(
callExp.node,
'CallExpression'
)
? callExp.node.callee.name
: ''
if (segment.type === 'TangentialArcTo') {
seg = tangentialArcToSegment({
@ -543,8 +606,12 @@ export class SceneEntities {
'VariableDeclaration'
)
if (trap(_node1)) return Promise.reject(_node1)
const variableDeclarationName =
_node1.node?.declarations?.[0]?.id?.name || ''
const variableDeclarationName = isNodeType<VariableDeclaration>(
_node1.node,
'VariableDeclaration'
)
? _node1.node.declarations[0]?.id?.name || ''
: ''
const sg = kclManager.programMemory.get(
variableDeclarationName
@ -672,21 +739,6 @@ export class SceneEntities {
...this.mouseEnterLeaveCallbacks(),
})
}
setupRectangleOriginListener = () => {
sceneInfra.setCallbacks({
onClick: (args) => {
const twoD = args.intersectionPoint?.twoD
if (!twoD) {
console.warn(`This click didn't have a 2D intersection`, args)
return
}
sceneInfra.modelingSend({
type: 'Add rectangle origin',
data: [twoD.x, twoD.y],
})
},
})
}
setupDraftRectangle = async (
sketchPathToNode: PathToNode,
forward: [number, number, number],
@ -696,14 +748,15 @@ export class SceneEntities {
) => {
let _ast = structuredClone(kclManager.ast)
const _node1 = getNodeFromPath<VariableDeclaration>(
const varDec = expectNodeOnPath<VariableDeclaration>(
_ast,
sketchPathToNode || [],
'VariableDeclaration'
)
if (trap(_node1)) return Promise.reject(_node1)
const variableDeclarationName =
_node1.node?.declarations?.[0]?.id?.name || ''
if (trap(varDec)) return Promise.reject(varDec)
const variableDeclarationName = varDec.declarations?.[0]?.id?.name || ''
const startSketchOn = varDec.declarations
const startSketchOnInit = startSketchOn?.[0]?.init
const tags: [string, string, string] = [
findUniqueName(_ast, 'rectangleSegmentA'),
@ -711,15 +764,6 @@ export class SceneEntities {
findUniqueName(_ast, 'rectangleSegmentC'),
]
const _node2 = getNodeFromPath<VariableDeclaration>(
_ast,
sketchPathToNode || [],
'VariableDeclaration'
)
if (trap(_node2)) return Promise.reject(_node2)
const startSketchOn = _node2.node?.declarations
const startSketchOnInit = startSketchOn?.[0]?.init
startSketchOn[0].init = createPipeExpression([
startSketchOnInit,
...getRectangleCallExpressions(rectangleOrigin, tags),
@ -750,12 +794,17 @@ export class SceneEntities {
'VariableDeclaration'
)
if (trap(_node)) return Promise.reject(_node)
const sketchInit = _node.node?.declarations?.[0]?.init
const sketchInit = isNodeType<VariableDeclaration>(
_node.node,
'VariableDeclaration'
)
? _node.node.declarations[0]?.init
: null
const x = (args.intersectionPoint.twoD.x || 0) - rectangleOrigin[0]
const y = (args.intersectionPoint.twoD.y || 0) - rectangleOrigin[1]
if (sketchInit.type === 'PipeExpression') {
if (sketchInit?.type === 'PipeExpression') {
updateRectangleSketch(sketchInit, x, y, tags[0])
}
@ -798,9 +847,14 @@ export class SceneEntities {
'VariableDeclaration'
)
if (trap(_node)) return Promise.reject(_node)
const sketchInit = _node.node?.declarations?.[0]?.init
const sketchInit = isNodeType<VariableDeclaration>(
_node.node,
'VariableDeclaration'
)
? _node.node.declarations[0]?.init
: null
if (sketchInit.type === 'PipeExpression') {
if (sketchInit?.type === 'PipeExpression') {
updateRectangleSketch(sketchInit, x, y, tags[0])
let _recastAst = parse(recast(_ast))
@ -1036,7 +1090,7 @@ export class SceneEntities {
if (trap(_node)) return
const node = _node.node
if (node.type !== 'CallExpression') return
if (isArray(node) || node.type !== 'CallExpression') return
let modded:
| {
@ -1641,7 +1695,9 @@ export class SceneEntities {
)
if (trap(_node, { suppress: true })) return
const node = _node.node
editorManager.setHighlightRange([node.start, node.end])
editorManager.setHighlightRange(
!isArray(node) ? [node.start, node.end] : [0, 0]
)
const yellow = 0xffff00
colorSegment(selected, yellow)
const extraSegmentGroup = parent.getObjectByName(EXTRA_SEGMENT_HANDLE)
@ -1771,7 +1827,14 @@ function prepareTruncatedMemoryAndAst(
'VariableDeclaration'
)
if (err(_node)) return _node
const variableDeclarationName = _node.node?.declarations?.[0]?.id?.name || ''
if (isArray(_node.node))
return new Error('Expected node to be an object, but found Array')
const variableDeclarationName = isNodeType<VariableDeclaration>(
_node.node,
'VariableDeclaration'
)
? _node.node.declarations[0]?.id?.name || ''
: ''
const lastSeg = (
programMemory.get(variableDeclarationName) as SketchGroup
).value.slice(-1)[0]
@ -1894,7 +1957,12 @@ export function sketchGroupFromPathToNode({
)
if (err(_varDec)) return _varDec
const varDec = _varDec.node
const result = programMemory.get(varDec?.id?.name || '')
if (isArray(varDec))
return new Error('Expected node to be an object, but found Array')
const varName = isNodeType<VariableDeclarator>(varDec, 'VariableDeclarator')
? varDec.id.name
: ''
const result = programMemory.get(varName)
if (result?.type === 'ExtrudeGroup') {
return result.sketchGroup
}

View File

@ -72,7 +72,7 @@ interface OnDragCallbackArgs extends OnMouseEnterLeaveArgs {
}
intersects: Intersection<Object3D<Object3DEventMap>>[]
}
interface OnClickCallbackArgs {
export interface OnClickCallbackArgs {
mouseEvent: MouseEvent
intersectionPoint?: {
twoD: Vector2

View File

@ -72,7 +72,6 @@ import { err, trap } from 'lib/trap'
import { useCommandsContext } from 'hooks/useCommandsContext'
import { modelingMachineEvent } from 'editor/manager'
import { hasValidFilletSelection } from 'lang/modifyAst/addFillet'
import { uuidv4 } from 'lib/utils'
type MachineContext<T extends AnyStateMachine> = {
state: StateFrom<T>
@ -143,7 +142,9 @@ export const ModelingMachineProvider = ({
kclManager.executeCode().then(() => {
if (engineCommandManager.engineConnection?.idleMode) return
store.videoElement?.play()
store.videoElement?.play().catch((e) => {
console.warn('Video playing was prevented', e)
})
})
})()
},

View File

@ -14,6 +14,7 @@ import { MemoryPane, MemoryPaneMenu } from './MemoryPane'
import { KclErrorsPane, LogsPane } from './LoggingPanes'
import { DebugPane } from './DebugPane'
import { FileTreeInner, FileTreeMenu } from 'components/FileTree'
import { useKclContext } from 'lang/KclProvider'
export type SidebarType =
| 'code'
@ -25,6 +26,14 @@ export type SidebarType =
| 'lspMessages'
| 'variables'
/**
* This interface can be extended as more context is needed for the panes
* to determine if they should show their badges or not.
*/
interface PaneCallbackProps {
kclContext: ReturnType<typeof useKclContext>
}
export type SidebarPane = {
id: SidebarType
title: string
@ -33,6 +42,7 @@ export type SidebarPane = {
Content: ReactNode | React.FC
Menu?: ReactNode | React.FC
hideOnPlatform?: 'desktop' | 'web'
showBadge?: (props: PaneCallbackProps) => boolean | number
}
export const sidebarPanes: SidebarPane[] = [
@ -74,6 +84,7 @@ export const sidebarPanes: SidebarPane[] = [
icon: faExclamationCircle,
Content: KclErrorsPane,
keybinding: 'Shift + E',
showBadge: ({ kclContext }) => kclContext.errors.length,
},
{
id: 'debug',

View File

@ -12,6 +12,7 @@ import { useModelingContext } from 'hooks/useModelingContext'
import { CustomIconName } from 'components/CustomIcon'
import { useCommandsContext } from 'hooks/useCommandsContext'
import { IconDefinition } from '@fortawesome/free-solid-svg-icons'
import { useKclContext } from 'lang/KclProvider'
interface ModelingSidebarProps {
paneOpacity: '' | 'opacity-20' | 'opacity-40'
@ -19,6 +20,7 @@ interface ModelingSidebarProps {
export function ModelingSidebar({ paneOpacity }: ModelingSidebarProps) {
const { commandBarSend } = useCommandsContext()
const kclContext = useKclContext()
const { settings } = useSettingsAuthContext()
const onboardingStatus = settings.context.app.onboardingStatus
const { send, context } = useModelingContext()
@ -62,6 +64,15 @@ export function ModelingSidebar({ paneOpacity }: ModelingSidebarProps) {
[sidebarPanes, showDebugPanel.current]
)
const paneBadgeMap: Record<SidebarType, number | boolean> = useMemo(() => {
return filteredPanes.reduce((acc, pane) => {
if (pane.showBadge) {
acc[pane.id] = pane.showBadge({ kclContext })
}
return acc
}, {} as Record<SidebarType, number | boolean>)
}, [kclContext.errors])
const togglePane = useCallback(
(newPane: SidebarType) => {
send({
@ -120,6 +131,7 @@ export function ModelingSidebar({ paneOpacity }: ModelingSidebarProps) {
paneIsOpen={context.store?.openPanes.includes(pane.id)}
onClick={() => togglePane(pane.id)}
aria-pressed={context.store?.openPanes.includes(pane.id)}
showBadge={paneBadgeMap[pane.id]}
/>
))}
</ul>
@ -186,12 +198,14 @@ interface ModelingPaneButtonProps
}
onClick: () => void
paneIsOpen?: boolean
showBadge?: boolean | number
}
function ModelingPaneButton({
paneConfig,
onClick,
paneIsOpen,
showBadge,
...props
}: ModelingPaneButtonProps) {
useHotkeys(paneConfig.keybinding, onClick, {
@ -223,6 +237,23 @@ function ModelingPaneButton({
{paneConfig.title}
{paneIsOpen !== undefined ? ` pane` : ''}
</span>
{!!showBadge && (
<p
className={
'absolute m-0 p-0 -top-1 -right-1 w-3 h-3 flex items-center justify-center text-[10px] font-semibold text-white bg-primary hue-rotate-90 rounded-full border border-chalkboard-10 dark:border-chalkboard-80'
}
>
<span className="sr-only">&nbsp;has&nbsp;</span>
{typeof showBadge === 'number' ? (
<span>{showBadge}</span>
) : (
<span className="sr-only">a</span>
)}
<span className="sr-only">
&nbsp;notification{Number(showBadge) > 1 ? 's' : ''}
</span>
</p>
)}
<Tooltip
position="right"
contentClassName="max-w-none flex items-center gap-4"

View File

@ -175,11 +175,35 @@ export const SettingsAuthProviderBase = ({
id: `${event.type}.success`,
})
},
'Execute AST': () => {
kclManager.isFirstRender = true
kclManager.executeCode(true).then(() => {
kclManager.isFirstRender = false
})
'Execute AST': (context, event) => {
try {
const allSettingsIncludesUnitChange =
event.type === 'Set all settings' &&
event.settings?.modeling?.defaultUnit?.current !==
context.modeling.defaultUnit.current
const resetSettingsIncludesUnitChange =
event.type === 'Reset settings' &&
context.modeling.defaultUnit.current !==
settings?.modeling?.defaultUnit?.default
if (
event.type === 'set.modeling.defaultUnit' ||
allSettingsIncludesUnitChange ||
resetSettingsIncludesUnitChange
) {
kclManager.isFirstRender = true
kclManager.executeCode(true).then(() => {
kclManager.isFirstRender = false
})
} else {
// For any future logging we'd like to do
// console.log(
// 'Not re-executing AST because the settings change did not affect the code interpretation'
// )
}
} catch (e) {
console.error('Error executing AST after settings change', e)
}
},
},
services: {

View File

@ -156,7 +156,13 @@ export const Stream = () => {
useEffect(() => {
setIsFirstRender(kclManager.isFirstRender)
if (!kclManager.isFirstRender) videoRef.current?.play()
if (!kclManager.isFirstRender)
setTimeout(() =>
// execute in the next event loop
videoRef.current?.play().catch((e) => {
console.warn('Video playing was prevented', e, videoRef.current)
})
)
setIsFreezeFrame(!kclManager.isFirstRender)
}, [kclManager.isFirstRender])
@ -170,8 +176,12 @@ export const Stream = () => {
if (!mediaStream) return
// Do not immediately play the stream!
videoRef.current.srcObject = mediaStream
videoRef.current.pause()
try {
videoRef.current.srcObject = mediaStream
videoRef.current.pause()
} catch (e) {
console.warn('Attempted to pause stream while play was still loading', e)
}
send({
type: 'Set context',

View File

@ -1,9 +1,12 @@
import { toolTips } from 'lang/langHelpers'
import { Selections } from 'lib/selections'
import { Program, Value, VariableDeclarator } from '../../lang/wasm'
import { CallExpression, Program, VariableDeclarator } from '../../lang/wasm'
import {
getNodePathFromSourceRange,
getNodeFromPath,
getLastNodeFromPath,
DynamicNode,
isNodeType,
expectNodeOnPath,
} from '../../lang/queryAst'
import { isSketchVariablesLinked } from '../../lang/std/sketchConstraints'
import {
@ -14,6 +17,7 @@ import {
} from '../../lang/std/sketchcombos'
import { kclManager } from 'lib/singletons'
import { err } from 'lib/trap'
import { isArray } from 'lib/utils'
export function equalAngleInfo({
selectionRanges,
@ -29,26 +33,33 @@ export function equalAngleInfo({
getNodePathFromSourceRange(kclManager.ast, range)
)
const _nodes = paths.map((pathToNode) => {
const tmp = getNodeFromPath<Value>(kclManager.ast, pathToNode)
const tmp = getLastNodeFromPath(kclManager.ast, pathToNode)
if (err(tmp)) return tmp
if (isArray(tmp.node)) {
return new Error('Expected value node, but found array')
}
return tmp.node
})
const _err1 = _nodes.find(err)
if (err(_err1)) return _err1
const nodes = _nodes as Value[]
const nodes: DynamicNode[] = []
for (const node of _nodes) {
if (err(node)) return node
nodes.push(node)
}
const _varDecs = paths.map((pathToNode) => {
const tmp = getNodeFromPath<VariableDeclarator>(
const tmp = expectNodeOnPath<VariableDeclarator>(
kclManager.ast,
pathToNode,
'VariableDeclarator'
)
if (err(tmp)) return tmp
return tmp.node
return tmp
})
const _err2 = _varDecs.find(err)
if (err(_err2)) return _err2
const varDecs = _varDecs as VariableDeclarator[]
const varDecs: VariableDeclarator[] = []
for (const varDec of _varDecs) {
if (err(varDec)) return varDec
varDecs.push(varDec)
}
const primaryLine = varDecs[0]
const secondaryVarDecs = varDecs.slice(1)
@ -57,7 +68,7 @@ export function equalAngleInfo({
)
const isAllTooltips = nodes.every(
(node) =>
node?.type === 'CallExpression' &&
isNodeType<CallExpression>(node, 'CallExpression') &&
toolTips.includes(node.callee.name as any)
)

View File

@ -1,9 +1,12 @@
import { toolTips } from 'lang/langHelpers'
import { Selections } from 'lib/selections'
import { Program, Value, VariableDeclarator } from '../../lang/wasm'
import { CallExpression, Program, VariableDeclarator } from '../../lang/wasm'
import {
getNodePathFromSourceRange,
getNodeFromPath,
getLastNodeFromPath,
DynamicNode,
isNodeType,
expectNodeOnPath,
} from '../../lang/queryAst'
import { isSketchVariablesLinked } from '../../lang/std/sketchConstraints'
import {
@ -14,6 +17,7 @@ import {
} from '../../lang/std/sketchcombos'
import { kclManager } from 'lib/singletons'
import { err } from 'lib/trap'
import { isArray } from 'lib/utils'
export function setEqualLengthInfo({
selectionRanges,
@ -29,26 +33,33 @@ export function setEqualLengthInfo({
getNodePathFromSourceRange(kclManager.ast, range)
)
const _nodes = paths.map((pathToNode) => {
const tmp = getNodeFromPath<Value>(kclManager.ast, pathToNode)
const tmp = getLastNodeFromPath(kclManager.ast, pathToNode)
if (err(tmp)) return tmp
if (isArray(tmp.node)) {
return new Error('Expected value node, but found array')
}
return tmp.node
})
const _err1 = _nodes.find(err)
if (err(_err1)) return _err1
const nodes = _nodes as Value[]
const nodes: DynamicNode[] = []
for (const node of _nodes) {
if (err(node)) return node
nodes.push(node)
}
const _varDecs = paths.map((pathToNode) => {
const tmp = getNodeFromPath<VariableDeclarator>(
const varDec = expectNodeOnPath<VariableDeclarator>(
kclManager.ast,
pathToNode,
'VariableDeclarator'
)
if (err(tmp)) return tmp
return tmp.node
if (err(varDec)) return varDec
return varDec
})
const _err2 = _varDecs.find(err)
if (err(_err2)) return _err2
const varDecs = _varDecs as VariableDeclarator[]
const varDecs: VariableDeclarator[] = []
for (const varDec of _varDecs) {
if (err(varDec)) return varDec
varDecs.push(varDec)
}
const primaryLine = varDecs[0]
const secondaryVarDecs = varDecs.slice(1)
@ -57,7 +68,7 @@ export function setEqualLengthInfo({
)
const isAllTooltips = nodes.every(
(node) =>
node?.type === 'CallExpression' &&
isNodeType<CallExpression>(node, 'CallExpression') &&
toolTips.includes(node.callee.name as any)
)

View File

@ -1,9 +1,11 @@
import { toolTips } from 'lang/langHelpers'
import { Selections } from 'lib/selections'
import { Program, ProgramMemory, Value } from '../../lang/wasm'
import { CallExpression, Program, ProgramMemory } from '../../lang/wasm'
import {
getNodePathFromSourceRange,
getNodeFromPath,
getLastNodeFromPath,
DynamicNode,
isNodeType,
} from '../../lang/queryAst'
import {
PathToNodeMap,
@ -13,6 +15,7 @@ import {
} from '../../lang/std/sketchcombos'
import { kclManager } from 'lib/singletons'
import { err } from 'lib/trap'
import { isArray } from 'lib/utils'
export function horzVertInfo(
selectionRanges: Selections,
@ -27,17 +30,22 @@ export function horzVertInfo(
getNodePathFromSourceRange(kclManager.ast, range)
)
const _nodes = paths.map((pathToNode) => {
const tmp = getNodeFromPath<Value>(kclManager.ast, pathToNode)
const tmp = getLastNodeFromPath(kclManager.ast, pathToNode)
if (err(tmp)) return tmp
if (isArray(tmp.node)) {
return new Error('Expected value node, but found array')
}
return tmp.node
})
const _err1 = _nodes.find(err)
if (err(_err1)) return _err1
const nodes = _nodes as Value[]
const nodes: DynamicNode[] = []
for (const node of _nodes) {
if (err(node)) return node
nodes.push(node)
}
const isAllTooltips = nodes.every(
(node) =>
node?.type === 'CallExpression' &&
isNodeType<CallExpression>(node, 'CallExpression') &&
toolTips.includes(node.callee.name as any)
)

View File

@ -1,10 +1,18 @@
import { toolTips } from 'lang/langHelpers'
import { Selections } from 'lib/selections'
import { BinaryPart, Program, Value, VariableDeclarator } from '../../lang/wasm'
import {
BinaryPart,
CallExpression,
Program,
VariableDeclarator,
} from '../../lang/wasm'
import {
getNodePathFromSourceRange,
getNodeFromPath,
isLinesParallelAndConstrained,
getLastNodeFromPath,
expectNodeOnPath,
DynamicNode,
isNodeType,
} from '../../lang/queryAst'
import { isSketchVariablesLinked } from '../../lang/std/sketchConstraints'
import {
@ -18,6 +26,7 @@ import { createVariableDeclaration } from '../../lang/modifyAst'
import { removeDoubleNegatives } from '../AvailableVarsHelpers'
import { kclManager } from 'lib/singletons'
import { err } from 'lib/trap'
import { isArray } from 'lib/utils'
const getModalInfo = createInfoModal(GetInfoModal)
@ -72,26 +81,33 @@ export function intersectInfo({
getNodePathFromSourceRange(kclManager.ast, range)
)
const _nodes = paths.map((pathToNode) => {
const tmp = getNodeFromPath<Value>(kclManager.ast, pathToNode)
const tmp = getLastNodeFromPath(kclManager.ast, pathToNode)
if (err(tmp)) return tmp
if (isArray(tmp.node)) {
return new Error('Expected value node, but found array')
}
return tmp.node
})
const _err1 = _nodes.find(err)
if (err(_err1)) return _err1
const nodes = _nodes as Value[]
const nodes: DynamicNode[] = []
for (const node of _nodes) {
if (err(node)) return node
nodes.push(node)
}
const _varDecs = paths.map((pathToNode) => {
const tmp = getNodeFromPath<VariableDeclarator>(
const varDec = expectNodeOnPath<VariableDeclarator>(
kclManager.ast,
pathToNode,
'VariableDeclarator'
)
if (err(tmp)) return tmp
return tmp.node
if (err(varDec)) return varDec
return varDec
})
const _err2 = _varDecs.find(err)
if (err(_err2)) return _err2
const varDecs = _varDecs as VariableDeclarator[]
const varDecs: VariableDeclarator[] = []
for (const varDec of _varDecs) {
if (err(varDec)) return varDec
varDecs.push(varDec)
}
const primaryLine = varDecs[0]
const secondaryVarDecs = varDecs.slice(1)
@ -100,7 +116,7 @@ export function intersectInfo({
)
const isAllTooltips = nodes.every(
(node) =>
node?.type === 'CallExpression' &&
isNodeType<CallExpression>(node, 'CallExpression') &&
[
...toolTips,
'startSketchAt', // TODO probably a better place for this to live

View File

@ -1,9 +1,11 @@
import { toolTips } from 'lang/langHelpers'
import { Selection, Selections } from 'lib/selections'
import { PathToNode, Program, Value } from '../../lang/wasm'
import { CallExpression, PathToNode, Program } from '../../lang/wasm'
import {
getNodePathFromSourceRange,
getNodeFromPath,
getLastNodeFromPath,
DynamicNode,
isNodeType,
} from '../../lang/queryAst'
import {
PathToNodeMap,
@ -13,6 +15,7 @@ import {
} from '../../lang/std/sketchcombos'
import { kclManager } from 'lib/singletons'
import { err } from 'lib/trap'
import { isArray } from 'lib/utils'
export function removeConstrainingValuesInfo({
selectionRanges,
@ -33,13 +36,18 @@ export function removeConstrainingValuesInfo({
getNodePathFromSourceRange(kclManager.ast, range)
)
const _nodes = paths.map((pathToNode) => {
const tmp = getNodeFromPath<Value>(kclManager.ast, pathToNode)
const tmp = getLastNodeFromPath(kclManager.ast, pathToNode)
if (err(tmp)) return tmp
if (isArray(tmp.node)) {
return new Error('Expected value node, but found array')
}
return tmp.node
})
const _err1 = _nodes.find(err)
if (err(_err1)) return _err1
const nodes = _nodes as Value[]
const nodes: DynamicNode[] = []
for (const node of _nodes) {
if (err(node)) return node
nodes.push(node)
}
const updatedSelectionRanges = pathToNodes
? {
@ -54,7 +62,7 @@ export function removeConstrainingValuesInfo({
: selectionRanges
const isAllTooltips = nodes.every(
(node) =>
node?.type === 'CallExpression' &&
isNodeType<CallExpression>(node, 'CallExpression') &&
toolTips.includes(node.callee.name as any)
)

View File

@ -1,6 +1,6 @@
import { toolTips } from 'lang/langHelpers'
import { Selections } from 'lib/selections'
import { BinaryPart, Program, Value } from '../../lang/wasm'
import { BinaryPart, CallExpression, Program, Value } from '../../lang/wasm'
import {
getNodePathFromSourceRange,
getNodeFromPath,
@ -49,22 +49,22 @@ export function absDistanceInfo({
getNodePathFromSourceRange(kclManager.ast, range)
)
const _nodes = paths.map((pathToNode) => {
const tmp = getNodeFromPath<Value>(
const tmp = getNodeFromPath<CallExpression>(
kclManager.ast,
pathToNode,
'CallExpression'
)
if (err(tmp)) return tmp
return tmp.node
return tmp.stopAtNode
})
const _err1 = _nodes.find(err)
if (err(_err1)) return _err1
const nodes = _nodes as Value[]
const nodes: (CallExpression | null)[] = []
for (const node of _nodes) {
if (err(node)) return node
nodes.push(node)
}
const isAllTooltips = nodes.every(
(node) =>
node?.type === 'CallExpression' &&
toolTips.includes(node.callee.name as any)
(node) => node && toolTips.includes(node.callee.name as any)
)
const transforms = getTransformInfos(selectionRanges, kclManager.ast, disType)

View File

@ -1,9 +1,17 @@
import { toolTips } from 'lang/langHelpers'
import { Selections } from 'lib/selections'
import { BinaryPart, Program, Value, VariableDeclarator } from '../../lang/wasm'
import {
BinaryPart,
CallExpression,
Program,
VariableDeclarator,
} from '../../lang/wasm'
import {
getNodePathFromSourceRange,
getNodeFromPath,
getLastNodeFromPath,
DynamicNode,
expectNodeOnPath,
isNodeType,
} from '../../lang/queryAst'
import { isSketchVariablesLinked } from '../../lang/std/sketchConstraints'
import {
@ -17,6 +25,7 @@ import { createVariableDeclaration } from '../../lang/modifyAst'
import { removeDoubleNegatives } from '../AvailableVarsHelpers'
import { kclManager } from 'lib/singletons'
import { err } from 'lib/trap'
import { isArray } from 'lib/utils'
const getModalInfo = createInfoModal(GetInfoModal)
@ -35,26 +44,33 @@ export function angleBetweenInfo({
)
const _nodes = paths.map((pathToNode) => {
const tmp = getNodeFromPath<Value>(kclManager.ast, pathToNode)
const tmp = getLastNodeFromPath(kclManager.ast, pathToNode)
if (err(tmp)) return tmp
if (isArray(tmp.node)) {
return new Error('Expected value node, but found array')
}
return tmp.node
})
const _err1 = _nodes.find(err)
if (err(_err1)) return _err1
const nodes = _nodes as Value[]
const nodes: DynamicNode[] = []
for (const node of _nodes) {
if (err(node)) return node
nodes.push(node)
}
const _varDecs = paths.map((pathToNode) => {
const tmp = getNodeFromPath<VariableDeclarator>(
const varDec = expectNodeOnPath<VariableDeclarator>(
kclManager.ast,
pathToNode,
'VariableDeclarator'
)
if (err(tmp)) return tmp
return tmp.node
if (err(varDec)) return varDec
return varDec
})
const _err2 = _varDecs.find(err)
if (err(_err2)) return _err2
const varDecs = _varDecs as VariableDeclarator[]
const varDecs: VariableDeclarator[] = []
for (const varDec of _varDecs) {
if (err(varDec)) return varDec
varDecs.push(varDec)
}
const primaryLine = varDecs[0]
const secondaryVarDecs = varDecs.slice(1)
@ -63,7 +79,7 @@ export function angleBetweenInfo({
)
const isAllTooltips = nodes.every(
(node) =>
node?.type === 'CallExpression' &&
isNodeType<CallExpression>(node, 'CallExpression') &&
toolTips.includes(node.callee.name as any)
)

View File

@ -1,8 +1,15 @@
import { toolTips } from 'lang/langHelpers'
import { BinaryPart, Program, Value, VariableDeclarator } from '../../lang/wasm'
import {
BinaryPart,
CallExpression,
Program,
VariableDeclarator,
} from '../../lang/wasm'
import {
getNodePathFromSourceRange,
getNodeFromPath,
getLastNodeFromPath,
expectNodeOnPath,
isNodeType,
} from '../../lang/queryAst'
import { isSketchVariablesLinked } from '../../lang/std/sketchConstraints'
import {
@ -17,6 +24,7 @@ import { removeDoubleNegatives } from '../AvailableVarsHelpers'
import { kclManager } from 'lib/singletons'
import { Selections } from 'lib/selections'
import { cleanErrs, err } from 'lib/trap'
import { isArray } from 'lib/utils'
const getModalInfo = createInfoModal(GetInfoModal)
@ -36,27 +44,31 @@ export function horzVertDistanceInfo({
getNodePathFromSourceRange(kclManager.ast, range)
)
const _nodes = paths.map((pathToNode) => {
const tmp = getNodeFromPath<Value>(kclManager.ast, pathToNode)
const tmp = getLastNodeFromPath(kclManager.ast, pathToNode)
if (err(tmp)) return tmp
if (isArray(tmp.node)) {
return new Error('Expected value node, but found array')
}
return tmp.node
})
const [hasErr, , nodesWErrs] = cleanErrs(_nodes)
const [hasErr, nodes, nodesWErrs] = cleanErrs(_nodes)
if (hasErr) return nodesWErrs[0]
const nodes = _nodes as Value[]
const _varDecs = paths.map((pathToNode) => {
const tmp = getNodeFromPath<VariableDeclarator>(
const varDec = expectNodeOnPath<VariableDeclarator>(
kclManager.ast,
pathToNode,
'VariableDeclarator'
)
if (err(tmp)) return tmp
return tmp.node
if (err(varDec)) return varDec
return varDec
})
const _err2 = _varDecs.find(err)
if (err(_err2)) return _err2
const varDecs = _varDecs as VariableDeclarator[]
const varDecs: VariableDeclarator[] = []
for (const varDec of _varDecs) {
if (err(varDec)) return varDec
varDecs.push(varDec)
}
const primaryLine = varDecs[0]
const secondaryVarDecs = varDecs.slice(1)
@ -65,7 +77,7 @@ export function horzVertDistanceInfo({
)
const isAllTooltips = nodes.every(
(node) =>
node?.type === 'CallExpression' &&
isNodeType<CallExpression>(node, 'CallExpression') &&
[
...toolTips,
'startSketchAt', // TODO probably a better place for this to live

View File

@ -1,6 +1,6 @@
import { toolTips } from 'lang/langHelpers'
import { Selections } from 'lib/selections'
import { BinaryPart, Program, Value } from '../../lang/wasm'
import { BinaryPart, CallExpression, Program } from '../../lang/wasm'
import {
getNodePathFromSourceRange,
getNodeFromPath,
@ -43,18 +43,24 @@ export function angleLengthInfo({
getNodePathFromSourceRange(kclManager.ast, range)
)
const nodes = paths.map((pathToNode) =>
getNodeFromPath<Value>(kclManager.ast, pathToNode, 'CallExpression')
)
const _err1 = nodes.find(err)
if (err(_err1)) return _err1
const isAllTooltips = nodes.every((meta) => {
if (err(meta)) return false
return (
meta.node?.type === 'CallExpression' &&
toolTips.includes(meta.node.callee.name as any)
const _nodes = paths.map((pathToNode) => {
const tmp = getNodeFromPath<CallExpression>(
kclManager.ast,
pathToNode,
'CallExpression'
)
if (err(tmp)) return tmp
return tmp.stopAtNode
})
const nodes: (CallExpression | null)[] = []
for (const node of _nodes) {
if (err(node)) return node
nodes.push(node)
}
const isAllTooltips = nodes.every((node) => {
if (err(node)) return false
return node && toolTips.includes(node.callee.name as any)
})
const transforms = getTransformInfos(

View File

@ -6,11 +6,7 @@ import { Selections, processCodeMirrorRanges, Selection } from 'lib/selections'
import { undo, redo } from '@codemirror/commands'
import { CommandBarMachineEvent } from 'machines/commandBarMachine'
import { addLineHighlight, addLineHighlightEvent } from './highlightextension'
import {
forEachDiagnostic,
Diagnostic,
setDiagnosticsEffect,
} from '@codemirror/lint'
import { Diagnostic, setDiagnosticsEffect } from '@codemirror/lint'
const updateOutsideEditorAnnotation = Annotation.define<boolean>()
export const updateOutsideEditorEvent = updateOutsideEditorAnnotation.of(true)
@ -114,12 +110,20 @@ export default class EditorManager {
}
}
clearDiagnostics(): void {
this.setDiagnostics([])
}
setDiagnostics(diagnostics: Diagnostic[]): void {
if (!this._editorView) return
// Clear out any existing diagnostics that are the same.
for (const diagnostic of diagnostics) {
for (const otherDiagnostic of diagnostics) {
if (diagnosticIsEqual(diagnostic, otherDiagnostic)) {
diagnostics = diagnostics.filter(
(d) => !diagnosticIsEqual(d, diagnostic)
)
diagnostics.push(diagnostic)
break
}
}
}
this._editorView.dispatch({
effects: [setDiagnosticsEffect.of(diagnostics)],
@ -131,26 +135,6 @@ export default class EditorManager {
})
}
addDiagnostics(diagnostics: Diagnostic[]): void {
if (!this._editorView) return
forEachDiagnostic(this._editorView.state, function (diag) {
diagnostics.push(diag)
})
const uniqueDiagnostics = new Set<Diagnostic>()
diagnostics.forEach((diagnostic) => {
for (const knownDiagnostic of uniqueDiagnostics.values()) {
if (diagnosticIsEqual(diagnostic, knownDiagnostic)) {
return
}
}
uniqueDiagnostics.add(diagnostic)
})
this.setDiagnostics([...uniqueDiagnostics])
}
undo() {
if (this._editorView) {
undo(this._editorView)

View File

@ -186,6 +186,7 @@ export function useSetupEngineManager(
}
function getDimensions(streamWidth?: number, streamHeight?: number) {
const factorOf = 4
const maxResolution = 2000
const width = streamWidth ? streamWidth : 0
const height = streamHeight ? streamHeight : 0
@ -193,7 +194,7 @@ function getDimensions(streamWidth?: number, streamHeight?: number) {
Math.min(maxResolution / width, maxResolution / height),
1.0
)
const quadWidth = Math.round((width * ratio) / 4) * 4
const quadHeight = Math.round((height * ratio) / 4) * 4
const quadWidth = Math.round((width * ratio) / factorOf) * factorOf
const quadHeight = Math.round((height * ratio) / factorOf) * factorOf
return { width: quadWidth, height: quadHeight }
}

View File

@ -1,7 +1,7 @@
import { executeAst, lintAst } from 'lang/langHelpers'
import { Selections } from 'lib/selections'
import { KCLError, kclErrorsToDiagnostics } from './errors'
import { uuidv4 } from 'lib/utils'
import { isArray, uuidv4 } from 'lib/utils'
import { EngineCommandManager } from './std/engineConnection'
import { err } from 'lib/trap'
@ -15,11 +15,17 @@ import {
recast,
SourceRange,
} from 'lang/wasm'
import { getNodeFromPath } from './queryAst'
import {
expectNodeOnPath,
getLastNodeFromPath,
getNodeFromPath,
} from './queryAst'
import { codeManager, editorManager, sceneInfra } from 'lib/singletons'
import { Diagnostic } from '@codemirror/lint'
export class KclManager {
private _ast: Program = {
type: 'Program',
body: [],
start: 0,
end: 0,
@ -32,6 +38,7 @@ export class KclManager {
}
private _programMemory: ProgramMemory = ProgramMemory.empty()
private _logs: string[] = []
private _lints: Diagnostic[] = []
private _kclErrors: KCLError[] = []
private _isExecuting = false
private _wasmInitFailed = true
@ -72,16 +79,36 @@ export class KclManager {
this._logsCallBack(logs)
}
get lints() {
return this._lints
}
set lints(lints) {
if (lints === this._lints) return
this._lints = lints
// Run the lints through the diagnostics.
this.kclErrors = this._kclErrors
}
get kclErrors() {
return this._kclErrors
}
set kclErrors(kclErrors) {
if (kclErrors === this._kclErrors && this.lints.length === 0) return
this._kclErrors = kclErrors
let diagnostics = kclErrorsToDiagnostics(kclErrors)
editorManager.addDiagnostics(diagnostics)
if (this.lints.length > 0) {
diagnostics = diagnostics.concat(this.lints)
}
editorManager.setDiagnostics(diagnostics)
this._kclErrorsCallBack(kclErrors)
}
addKclErrors(kclErrors: KCLError[]) {
if (kclErrors.length === 0) return
this.kclErrors = this.kclErrors.concat(kclErrors)
}
get isExecuting() {
return this._isExecuting
}
@ -134,6 +161,7 @@ export class KclManager {
clearAst() {
this._ast = {
type: 'Program',
body: [],
start: 0,
end: 0,
@ -148,12 +176,12 @@ export class KclManager {
safeParse(code: string): Program | null {
const ast = parse(code)
this.lints = []
this.kclErrors = []
if (!err(ast)) return ast
const kclerror: KCLError = ast as KCLError
console.error('error parsing code', kclerror)
this.kclErrors = [kclerror]
this.addKclErrors([kclerror])
// TODO: re-eval if session should end?
if (kclerror.msg === 'file is empty')
this.engineCommandManager?.endSession()
@ -190,16 +218,19 @@ export class KclManager {
this._cancelTokens.set(currentExecutionId, false)
this.isExecuting = true
// Make sure we clear before starting again. End session will do this.
this.engineCommandManager?.endSession()
await this.ensureWasmInit()
const { logs, errors, programMemory } = await executeAst({
ast,
engineCommandManager: this.engineCommandManager,
})
editorManager.addDiagnostics(await lintAst({ ast: ast }))
this.lints = await lintAst({ ast: ast })
sceneInfra.modelingSend({ type: 'code edit during sketch' })
defaultSelectionFilter(programMemory, this.engineCommandManager)
await this.engineCommandManager.waitForAllCommands()
if (zoomToFit) {
let zoomObjectId: string | undefined = ''
@ -219,6 +250,15 @@ export class KclManager {
padding: 0.1, // padding around the objects
},
})
await this.engineCommandManager.sendSceneCommand({
type: 'modeling_cmd_req',
cmd_id: uuidv4(),
cmd: {
type: 'zoom_to_fit',
object_ids: zoomObjectId ? [zoomObjectId] : [], // leave empty to zoom to all objects
padding: 0.1, // padding around the objects
},
})
}
this.isExecuting = false
@ -228,7 +268,7 @@ export class KclManager {
return
}
this.logs = logs
this.kclErrors = errors
this.addKclErrors(errors)
this.programMemory = programMemory
this.ast = { ...ast }
this._executeCallback()
@ -272,8 +312,6 @@ export class KclManager {
useFakeExecutor: true,
})
editorManager.addDiagnostics(await lintAst({ ast: ast }))
this._logs = logs
this._kclErrors = errors
this._programMemory = programMemory
@ -281,14 +319,14 @@ export class KclManager {
Object.entries(this.engineCommandManager.artifactMap).forEach(
([commandId, artifact]) => {
if (!artifact.pathToNode) return
const _node1 = getNodeFromPath<CallExpression>(
const _node = getNodeFromPath<CallExpression>(
this.ast,
artifact.pathToNode,
'CallExpression'
)
if (err(_node1)) return
const { node } = _node1
if (node.type !== 'CallExpression') return
if (err(_node)) return
const { node } = _node
if (isArray(node) || node.type !== 'CallExpression') return
const [oldStart, oldEnd] = artifact.range
if (oldStart === 0 && oldEnd === 0) return
if (oldStart === node.start && oldEnd === node.end) return
@ -305,7 +343,6 @@ export class KclManager {
})
}
async executeCode(zoomToFit?: boolean): Promise<void> {
console.log('[kcl/KclSingleton] executeCode')
const ast = this.safeParse(codeManager.code)
if (!ast) {
this.clearAst()
@ -361,12 +398,15 @@ export class KclManager {
let returnVal: Selections | undefined = undefined
if (optionalParams?.focusPath) {
const _node1 = getNodeFromPath<any>(
const _node1 = getLastNodeFromPath(
astWithUpdatedSource,
optionalParams?.focusPath
)
if (err(_node1)) return Promise.reject(_node1)
const { node } = _node1
if (isArray(node)) {
return Promise.reject(new Error('Expected node to not be an array'))
}
const { start, end } = node
if (!start || !end)

View File

@ -1,4 +1,5 @@
import { getNodePathFromSourceRange, getNodeFromPath } from './queryAst'
import { isArray } from 'lib/utils'
import { getNodePathFromSourceRange, getLastNodeFromPath } from './queryAst'
import { Identifier, parse, initPromise, Parameter } from './wasm'
import { err } from 'lib/trap'
@ -25,10 +26,13 @@ const sk3 = startSketchAt([0, 0])
const ast = parse(code)
if (err(ast)) throw ast
const nodePath = getNodePathFromSourceRange(ast, sourceRange)
const _node = getNodeFromPath<any>(ast, nodePath)
const _node = getLastNodeFromPath(ast, nodePath)
if (err(_node)) throw _node
const { node } = _node
if (isArray(node)) {
throw new Error('Expected call expression node, but found array')
}
expect([node.start, node.end]).toEqual(sourceRange)
expect(node.type).toBe('CallExpression')
})
@ -53,7 +57,7 @@ const b1 = cube([0,0], 10)`
const ast = parse(code)
if (err(ast)) throw ast
const nodePath = getNodePathFromSourceRange(ast, sourceRange)
const _node = getNodeFromPath<Parameter>(ast, nodePath)
const _node = getLastNodeFromPath(ast, nodePath)
if (err(_node)) throw _node
const node = _node.node
@ -66,8 +70,12 @@ const b1 = cube([0,0], 10)`
['params', 'FunctionExpression'],
[0, 'index'],
])
if (isArray(node)) {
throw new Error('Expected parameter node, but found array')
}
expect(node.type).toBe('Parameter')
expect(node.identifier.name).toBe('pos')
const param = node as any as Parameter
expect(param.identifier.name).toBe('pos')
})
it('gets path right for deep within function definition body', () => {
const code = `fn cube = (pos, scale) => {
@ -90,7 +98,7 @@ const b1 = cube([0,0], 10)`
const ast = parse(code)
if (err(ast)) throw ast
const nodePath = getNodePathFromSourceRange(ast, sourceRange)
const _node = getNodeFromPath<Identifier>(ast, nodePath)
const _node = getLastNodeFromPath(ast, nodePath)
if (err(_node)) throw _node
const node = _node.node
expect(nodePath).toEqual([
@ -112,7 +120,11 @@ const b1 = cube([0,0], 10)`
['elements', 'ArrayExpression'],
[0, 'index'],
])
if (isArray(node)) {
throw new Error('Expected identifier node, but found array')
}
expect(node.type).toBe('Identifier')
expect(node.name).toBe('scale')
const ident = node as any as Identifier
expect(ident.name).toBe('scale')
})
})

View File

@ -119,6 +119,7 @@ describe('Testing addSketchTo', () => {
it('should add a sketch to a program', () => {
const result = addSketchTo(
{
type: 'Program',
body: [],
start: 0,
end: 0,

View File

@ -27,6 +27,8 @@ import {
getNodePathFromSourceRange,
isNodeSafeToReplace,
traverse,
getLastNodeFromPath,
expectNodeOnPath,
} from './queryAst'
import { addTagForSketchOnFace, getConstraintInfo } from './std/sketch'
import {
@ -36,7 +38,7 @@ import {
transformAstSketchLines,
} from './std/sketchcombos'
import { DefaultPlaneStr } from 'clientSideScene/sceneEntities'
import { isOverlap, roundOff } from 'lib/utils'
import { isArray, isOverlap, roundOff } from 'lib/utils'
import { KCL_DEFAULT_CONSTANT_PREFIXES } from 'lib/constants'
import { ConstrainInfo } from './std/stdTypes'
import { TagDeclarator } from 'wasm-lib/kcl/bindings/TagDeclarator'
@ -79,16 +81,12 @@ export function addStartProfileAt(
pathToNode: PathToNode,
at: [number, number]
): { modifiedAst: Program; pathToNode: PathToNode } | Error {
const _node1 = getNodeFromPath<VariableDeclaration>(
const variableDeclaration = expectNodeOnPath<VariableDeclaration>(
node,
pathToNode,
'VariableDeclaration'
)
if (err(_node1)) return _node1
const variableDeclaration = _node1.node
if (variableDeclaration.type !== 'VariableDeclaration') {
return new Error('variableDeclaration.init.type !== PipeExpression')
}
if (err(variableDeclaration)) return variableDeclaration
const _node = { ...node }
const init = variableDeclaration.declarations[0].init
const startProfileAt = createCallExpressionStdLib('startProfileAt', [
@ -263,7 +261,7 @@ export function extrudeSketch(
}
| Error {
const _node = { ...node }
const _node1 = getNodeFromPath(_node, pathToNode)
const _node1 = getLastNodeFromPath(_node, pathToNode)
if (err(_node1)) return _node1
const { node: sketchExpression } = _node1
@ -274,9 +272,9 @@ export function extrudeSketch(
'PipeExpression'
)
if (err(_node2)) return _node2
const { node: pipeExpression } = _node2
const { stopAtNode: pipeExpression } = _node2
const isInPipeExpression = pipeExpression.type === 'PipeExpression'
const isInPipeExpression = !!pipeExpression
const _node3 = getNodeFromPath<VariableDeclarator>(
_node,
@ -284,7 +282,11 @@ export function extrudeSketch(
'VariableDeclarator'
)
if (err(_node3)) return _node3
const { node: variableDeclarator, shallowPath: pathToDecleration } = _node3
const { stopAtNode: variableDeclarator, shallowPath: pathToDecleration } =
_node3
if (!variableDeclarator) {
return new Error('VariableDeclarator not found')
}
const extrudeCall = createCallExpressionStdLib('extrude', [
distance,
@ -356,34 +358,34 @@ export function sketchOnExtrudedFace(
node,
KCL_DEFAULT_CONSTANT_PREFIXES.SKETCH
)
const _node1 = getNodeFromPath<VariableDeclarator>(
const oldSketchNode = expectNodeOnPath<VariableDeclarator>(
_node,
sketchPathToNode,
'VariableDeclarator',
true
{
firstFound: true,
message: 'Old sketch node not found',
}
)
if (err(_node1)) return _node1
const { node: oldSketchNode } = _node1
if (err(oldSketchNode)) return oldSketchNode
const oldSketchName = oldSketchNode.id.name
const _node2 = getNodeFromPath<CallExpression>(
const expression = expectNodeOnPath<CallExpression>(
_node,
sketchPathToNode,
'CallExpression'
)
if (err(_node2)) return _node2
const { node: expression } = _node2
if (err(expression)) return expression
const _node3 = getNodeFromPath<VariableDeclarator>(
const extrudeVarDec = expectNodeOnPath<VariableDeclarator>(
_node,
extrudePathToNode,
'VariableDeclarator'
)
if (err(_node3)) return _node3
const { node: extrudeVarDec } = _node3
const extrudeName = extrudeVarDec.id?.name
if (err(extrudeVarDec)) return extrudeVarDec
const extrudeName = extrudeVarDec.id.name
let _tag = null
let _tag: Identifier | Literal | null = null
if (cap === 'none') {
const __tag = addTagForSketchOnFace(
{
@ -678,9 +680,12 @@ export function giveSketchFnCallTag(
}
| Error {
const path = getNodePathFromSourceRange(ast, range)
const _node1 = getNodeFromPath<CallExpression>(ast, path, 'CallExpression')
if (err(_node1)) return _node1
const { node: primaryCallExp } = _node1
const primaryCallExp = expectNodeOnPath<CallExpression>(
ast,
path,
'CallExpression'
)
if (err(primaryCallExp)) return primaryCallExp
// Tag is always 3rd expression now, using arg index feels brittle
// but we can come up with a better way to identify tag later.
@ -784,27 +789,35 @@ export function deleteSegmentFromPipeExpression(
): Program | Error {
let _modifiedAst = structuredClone(modifiedAst)
dependentRanges.forEach((range) => {
for (const range of dependentRanges) {
const path = getNodePathFromSourceRange(_modifiedAst, range)
const callExp = getNodeFromPath<CallExpression>(
const _callExp = getNodeFromPath<CallExpression>(
_modifiedAst,
path,
'CallExpression',
true
)
if (err(callExp)) return callExp
if (err(_callExp)) return _callExp
const callExp = _callExp.stopAtNode
if (!callExp) {
return new Error('Call Expression not found')
}
const constraintInfo = getConstraintInfo(callExp.node, code, path).find(
const constraintInfo = getConstraintInfo(callExp, code, path).find(
({ sourceRange }) => isOverlap(sourceRange, range)
)
if (!constraintInfo) return
if (!constraintInfo) {
return new Error('Constraint Info not found')
}
const input = makeRemoveSingleConstraintInput(
constraintInfo.argPosition,
callExp.shallowPath
_callExp.shallowPath
)
if (!input) return
if (!input) {
return new Error('Input not found')
}
const transform = removeSingleConstraintInfo(
{
...input,
@ -812,11 +825,13 @@ export function deleteSegmentFromPipeExpression(
_modifiedAst,
programMemory
)
if (!transform) return
if (!transform) {
return new Error('Transform not found')
}
_modifiedAst = transform.modifiedAst
})
}
const pipeExpression = getNodeFromPath<PipeExpression>(
const pipeExpression = expectNodeOnPath<PipeExpression>(
_modifiedAst,
pathToNode,
'PipeExpression'
@ -827,7 +842,7 @@ export function deleteSegmentFromPipeExpression(
([_, desc]) => desc === 'PipeExpression'
)
const segmentIndexInPipe = pathToNode[pipeInPathIndex + 1]
pipeExpression.node.body.splice(segmentIndexInPipe[0] as number, 1)
pipeExpression.body.splice(segmentIndexInPipe[0] as number, 1)
// Move up to the next segment.
segmentIndexInPipe[0] = Math.max((segmentIndexInPipe[0] as number) - 1, 0)
@ -902,19 +917,23 @@ export async function deleteFromSelection(
const astClone = structuredClone(ast)
const range = selection.range
const path = getNodePathFromSourceRange(ast, range)
const varDec = getNodeFromPath<VariableDeclarator>(
const _varDec = getNodeFromPath<VariableDeclarator>(
ast,
path,
'VariableDeclarator'
)
if (err(varDec)) return varDec
if (err(_varDec)) return _varDec
const { stopAtNode: varDec } = _varDec
if (!varDec) {
return new Error('VariableDeclarator not found')
}
if (
(selection.type === 'extrude-wall' ||
selection.type === 'end-cap' ||
selection.type === 'start-cap') &&
varDec.node.init.type === 'PipeExpression'
varDec.init.type === 'PipeExpression'
) {
const varDecName = varDec.node.id.name
const varDecName = varDec.id.name
let pathToNode: PathToNode | null = null
let extrudeNameToDelete = ''
traverse(astClone, {
@ -976,13 +995,16 @@ export async function deleteFromSelection(
lastKey: number
}[] = []
for (const { path, sketchName } of pathsDependingOnExtrude) {
const parent = getNodeFromPath<PipeExpression['body']>(
astClone,
path.slice(0, -1)
)
if (err(parent)) {
const _parent = getLastNodeFromPath(astClone, path.slice(0, -1))
if (err(_parent)) {
return
}
const { node: parent } = _parent
if (!isArray(parent)) {
console.error(`Parent is not an array: ${parent}`)
return
}
const pipeBodyItems = parent as PipeExpression['body']
const sketchToPreserve = programMemory.get(sketchName) as SketchGroup
console.log('sketchName', sketchName)
// Can't kick off multiple requests at once as getFaceDetails
@ -1000,7 +1022,7 @@ export async function deleteFromSelection(
}
const lastKey = Number(path.slice(-1)[0][0])
modificationDetails.push({
parent: parent.node,
parent: pipeBodyItems,
faceDetails,
lastKey,
})
@ -1048,14 +1070,14 @@ export async function deleteFromSelection(
}
// await prom
return astClone
} else if (varDec.node.init.type === 'PipeExpression') {
const pipeBody = varDec.node.init.body
} else if (varDec.init.type === 'PipeExpression') {
const pipeBody = varDec.init.body
if (
pipeBody[0].type === 'CallExpression' &&
pipeBody[0].callee.name === 'startSketchOn'
) {
// remove varDec
const varDecIndex = varDec.shallowPath[1][0] as number
const varDecIndex = _varDec.shallowPath[1][0] as number
astClone.body.splice(varDecIndex, 1)
return astClone
}

View File

@ -12,7 +12,7 @@ import {
hasValidFilletSelection,
isTagUsedInFillet,
} from './addFillet'
import { getNodeFromPath, getNodePathFromSourceRange } from '../queryAst'
import { expectNodeOnPath, getNodePathFromSourceRange } from '../queryAst'
import { createLiteral } from 'lang/modifyAst'
import { err } from 'lib/trap'
import { Selections } from 'lib/selections'
@ -270,13 +270,13 @@ const extrude001 = extrude(-5, sketch001)
]
const pathToNode = getNodePathFromSourceRange(ast, range)
if (err(pathToNode)) return
const callExp = getNodeFromPath<CallExpression>(
const callExp = expectNodeOnPath<CallExpression>(
ast,
pathToNode,
'CallExpression'
)
if (err(callExp)) return
const edges = isTagUsedInFillet({ ast, callExp: callExp.node })
const edges = isTagUsedInFillet({ ast, callExp })
expect(edges).toEqual(['getOppositeEdge', 'baseEdge'])
})
it('should correctly identify getPreviousAdjacentEdge edges', () => {
@ -289,13 +289,13 @@ const extrude001 = extrude(-5, sketch001)
]
const pathToNode = getNodePathFromSourceRange(ast, range)
if (err(pathToNode)) return
const callExp = getNodeFromPath<CallExpression>(
const callExp = expectNodeOnPath<CallExpression>(
ast,
pathToNode,
'CallExpression'
)
if (err(callExp)) return
const edges = isTagUsedInFillet({ ast, callExp: callExp.node })
const edges = isTagUsedInFillet({ ast, callExp })
expect(edges).toEqual(['getPreviousAdjacentEdge'])
})
it('should correctly identify no edges', () => {
@ -308,13 +308,13 @@ const extrude001 = extrude(-5, sketch001)
]
const pathToNode = getNodePathFromSourceRange(ast, range)
if (err(pathToNode)) return
const callExp = getNodeFromPath<CallExpression>(
const callExp = expectNodeOnPath<CallExpression>(
ast,
pathToNode,
'CallExpression'
)
if (err(callExp)) return
const edges = isTagUsedInFillet({ ast, callExp: callExp.node })
const edges = isTagUsedInFillet({ ast, callExp })
expect(edges).toEqual([])
})
})

View File

@ -18,6 +18,7 @@ import {
createPipeExpression,
} from '../modifyAst'
import {
expectNodeOnPath,
getNodeFromPath,
getNodePathFromSourceRange,
hasSketchPipeBeenExtruded,
@ -46,15 +47,12 @@ export function addFillet(
*/
// Find the specific sketch segment to tag with the new tag
const sketchSegmentChunk = getNodeFromPath(
const sketchSegmentNode = expectNodeOnPath<CallExpression>(
_node,
pathToSegmentNode,
'CallExpression'
)
if (err(sketchSegmentChunk)) return sketchSegmentChunk
const { node: sketchSegmentNode } = sketchSegmentChunk as {
node: CallExpression
}
if (err(sketchSegmentNode)) return sketchSegmentNode
// Check whether selection is a valid segment from sketchLineHelpersMap
if (!(sketchSegmentNode.callee.name in sketchLineHelperMap)) {
@ -93,13 +91,12 @@ export function addFillet(
])
// Locate the extrude call
const extrudeChunk = getNodeFromPath<VariableDeclaration>(
const extrudeVarDecl = expectNodeOnPath<VariableDeclaration>(
_node,
pathToExtrudeNode,
'VariableDeclaration'
)
if (err(extrudeChunk)) return extrudeChunk
const { node: extrudeVarDecl } = extrudeChunk
if (err(extrudeVarDecl)) return extrudeVarDecl
const extrudeDeclarator = extrudeVarDecl.declarations[0]
const extrudeInit = extrudeDeclarator.init
@ -281,12 +278,12 @@ export const hasValidFilletSelection = ({
'CallExpression'
)
if (err(segmentNode)) return false
if (segmentNode.node.type === 'CallExpression') {
const segmentName = segmentNode.node.callee.name
if (segmentNode.stopAtNode) {
const segmentName = segmentNode.stopAtNode.callee.name
if (segmentName in sketchLineHelperMap) {
const edges = isTagUsedInFillet({
ast,
callExp: segmentNode.node,
callExp: segmentNode.stopAtNode,
})
// edge has already been filleted
if (

View File

@ -19,13 +19,47 @@ import {
} from './wasm'
import { createIdentifier, splitPathAtLastIndex } from './modifyAst'
import { getSketchSegmentFromSourceRange } from './std/sketchConstraints'
import { getAngle } from '../lib/utils'
import { getAngle, isArray } from '../lib/utils'
import { getFirstArg } from './std/sketch'
import {
getConstraintLevelFromSourceRange,
getConstraintType,
} from './std/sketchcombos'
import { err } from 'lib/trap'
import { BodyItem } from 'wasm-lib/kcl/bindings/BodyItem'
export interface DynamicNode {
type: SyntaxType
// Source range of the node.
start: number
end: number
[index: string]: unknown
}
function isAstNode(
node: any
): node is { type: SyntaxType; start: number; end: number } {
// TODO: Should we check for start and end also?
return node && typeof node === 'object' && 'type' in node
}
/**
* Given T and its corresponding SyntaxType, narrow the node to type T if
* node.type matches.
*/
export function isNodeType<T extends DynamicNode>(
node: unknown,
syntaxType: SyntaxType | SyntaxType[]
): node is T {
return (
!!node &&
typeof node === 'object' &&
'type' in node &&
(isArray(syntaxType)
? syntaxType.includes(node.type as SyntaxType)
: node.type === syntaxType)
)
}
/**
* Retrieves a node from a given path within a Program node structure, optionally stopping at a specified node type.
@ -33,51 +67,64 @@ import { err } from 'lib/trap'
* and return the node at the end of this path.
* By default it will return the node of the deepest "stopAt" type encountered, or the node at the end of the path if no "stopAt" type is provided.
* If the "returnEarly" flag is set to true, the function will return as soon as a node of the specified type is found.
*
* If stopAt is provided, it must match T's type property.
*/
export function getNodeFromPath<T>(
export function getNodeFromPath<T extends DynamicNode>(
node: Program,
path: PathToNode,
stopAt?: SyntaxType | SyntaxType[],
returnEarly = false
):
| {
node: T
node: DynamicNode | unknown[]
stopAtNode: T | null
shallowPath: PathToNode
deepPath: PathToNode
}
| Error {
let currentNode = node as any
let stopAtNode = null
let currentNode: DynamicNode | unknown[] = node
let stopAtNode: T | null = null
let successfulPaths: PathToNode = []
let pathsExplored: PathToNode = []
for (const pathItem of path) {
if (typeof currentNode[pathItem[0]] !== 'object') {
if (stopAtNode) {
const pathIndex = pathItem[0]
let nextNode: unknown
if (currentNode && typeof pathIndex === 'number' && isArray(currentNode)) {
nextNode = currentNode[pathIndex]
}
if (
currentNode &&
typeof pathIndex === 'string' &&
typeof currentNode === 'object' &&
!isArray(currentNode)
) {
nextNode = currentNode[pathIndex]
}
if (!isArray(nextNode) && !isAstNode(nextNode)) {
if (isAstNode(stopAtNode)) {
return {
node: stopAtNode,
stopAtNode,
shallowPath: pathsExplored,
deepPath: successfulPaths,
}
}
return new Error('not an object')
}
currentNode = currentNode?.[pathItem[0]]
currentNode = nextNode
successfulPaths.push(pathItem)
if (!stopAtNode) {
pathsExplored.push(pathItem)
}
if (
typeof stopAt !== 'undefined' &&
(Array.isArray(stopAt)
? stopAt.includes(currentNode.type)
: currentNode.type === stopAt)
) {
if (stopAt && isNodeType<T>(currentNode, stopAt)) {
// it will match the deepest node of the type
// instead of returning at the first match
stopAtNode = currentNode
if (returnEarly) {
return {
node: stopAtNode,
stopAtNode,
shallowPath: pathsExplored,
deepPath: successfulPaths,
}
@ -86,32 +133,104 @@ export function getNodeFromPath<T>(
}
return {
node: stopAtNode || currentNode,
stopAtNode,
shallowPath: pathsExplored,
deepPath: successfulPaths,
}
}
/**
* Returns the terminal node in the given path. Like getNodeFromPath, but no
* stopAt parameter.
*/
export function getLastNodeFromPath(
node: Program,
path: PathToNode
):
| {
node: DynamicNode | unknown[]
}
| Error {
const _result = getNodeFromPath<DynamicNode>(node, path)
if (err(_result)) return _result
return {
node: _result.node,
}
}
/**
* Returns the terminal node in the given path, and asserts that it's the given
* type.
*/
export function expectLastNodeFromPath<T extends DynamicNode>(
node: Program,
path: PathToNode,
syntaxType: SyntaxType | SyntaxType[]
): T | Error {
const result = getLastNodeFromPath(node, path)
if (err(result)) return result
if (!isNodeType<T>(result.node, syntaxType)) {
return new Error(
`Expected node of type ${syntaxType}: found ${JSON.stringify(result)}`
)
}
return result.node
}
/**
* Returns the node in the path with the given type. Like getNodeFromPath, but
* if no stopAt node is found, an error is returned instead of null.
*
* @param {boolean} [options.firstFound=false] if true, return the first node of
* the type found. The default returns the last node found.
* @param {boolean} [options.message] the error message to return if the node is
* not found.
*/
export function expectNodeOnPath<T extends DynamicNode>(
node: Program,
path: PathToNode,
syntaxType: SyntaxType,
options: { firstFound?: boolean; message?: string } = {
firstFound: false,
}
): T | Error {
const result = getNodeFromPath<T>(node, path, syntaxType, options.firstFound)
if (err(result)) return result
if (!result.stopAtNode) {
return new Error(
options.message ?? `Node of type ${syntaxType} not found in path`
)
}
return result.stopAtNode
}
/**
* Functions the same as getNodeFromPath, but returns a curried function that can be called with the stopAt and returnEarly arguments.
*/
export function getNodeFromPathCurry(
node: Program,
path: PathToNode
): <T>(
stopAt?: SyntaxType | SyntaxType[],
): <T extends DynamicNode>(
stopAt: SyntaxType | SyntaxType[],
returnEarly?: boolean
) =>
| {
node: T
node: DynamicNode | unknown[]
stopAtNode: T | null
path: PathToNode
}
| Error {
return <T>(stopAt?: SyntaxType | SyntaxType[], returnEarly = false) => {
return <T extends DynamicNode>(
stopAt: SyntaxType | SyntaxType[],
returnEarly = false
) => {
const _node1 = getNodeFromPath<T>(node, path, stopAt, returnEarly)
if (err(_node1)) return _node1
const { node: _node, shallowPath } = _node1
const { node: _node, stopAtNode, shallowPath } = _node1
return {
node: _node,
stopAtNode,
path: shallowPath,
}
}
@ -459,7 +578,7 @@ export function findAllPreviousVariablesPath(
const { index: insertIndex, path: bodyPath } = splitPathAtLastIndex(pathToDec)
const _node2 = getNodeFromPath<Program['body']>(ast, bodyPath)
const _node2 = getLastNodeFromPath(ast, bodyPath)
if (err(_node2)) {
console.error(_node2)
return {
@ -468,19 +587,30 @@ export function findAllPreviousVariablesPath(
insertIndex: 0,
}
}
if (!isArray(_node2.node)) {
console.error(
`Expected node of type array, but found: ${JSON.stringify(_node2)}`
)
return {
variables: [],
bodyPath: [],
insertIndex: 0,
}
}
const { node: bodyItems } = _node2
const variables: PrevVariable<any>[] = []
bodyItems?.forEach?.((item) => {
if (item.type !== 'VariableDeclaration' || item.end > startRange) return
for (const unknownItem of bodyItems) {
const item = unknownItem as BodyItem
if (item.type !== 'VariableDeclaration' || item.end > startRange) continue
const varName = item.declarations[0].id.name
const varValue = programMemory?.get(varName)
if (!varValue || typeof varValue?.value !== type) return
if (!varValue || typeof varValue?.value !== type) continue
variables.push({
key: varName,
value: varValue.value,
})
})
}
return {
insertIndex,
@ -554,7 +684,7 @@ export function isNodeSafeToReplacePath(
}
pathToReplaced[1][0] = index + 1
const startPath = finPath.slice(0, -1)
const _nodeToReplace = getNodeFromPath(_ast, startPath)
const _nodeToReplace = getLastNodeFromPath(_ast, startPath)
if (err(_nodeToReplace)) return _nodeToReplace
const nodeToReplace = _nodeToReplace.node as any
nodeToReplace[last[0]] = identifier
@ -656,7 +786,8 @@ export function isLinesParallelAndConstrained(
'CallExpression'
)
if (err(_secondaryNode)) return _secondaryNode
const secondaryNode = _secondaryNode.node
const secondaryNode = _secondaryNode.stopAtNode
if (!secondaryNode) return new Error('no secondary node found')
const _varDec = getNodeFromPath(ast, primaryPath, 'VariableDeclaration')
if (err(_varDec)) return _varDec
const varDec = _varDec.node
@ -682,7 +813,7 @@ export function isLinesParallelAndConstrained(
Math.abs(primaryAngle - secondaryAngle) < EPSILON ||
Math.abs(primaryAngle - secondaryAngleAlt) < EPSILON
// is secordary line fully constrain, or has constrain type of 'angle'
// is secondary line fully constrain, or has constrain type of 'angle'
const secondaryFirstArg = getFirstArg(secondaryNode)
if (err(secondaryFirstArg)) return secondaryFirstArg
@ -747,8 +878,8 @@ export function doesPipeHaveCallExp({
console.error(pipeExpressionMeta)
return false
}
const pipeExpression = pipeExpressionMeta.node
if (pipeExpression.type !== 'PipeExpression') return false
const pipeExpression = pipeExpressionMeta.stopAtNode
if (!pipeExpression) return false
return pipeExpression.body.some(
(expression) =>
expression.type === 'CallExpression' &&
@ -775,8 +906,8 @@ export function hasExtrudeSketchGroup({
console.error(varDecMeta)
return false
}
const varDec = varDecMeta.node
if (varDec.type !== 'VariableDeclaration') return false
const varDec = varDecMeta.stopAtNode
if (!varDec) return false
const varName = varDec.declarations[0].id.name
const varValue = programMemory?.get(varName)
return varValue?.type === 'ExtrudeGroup' || varValue?.type === 'SketchGroup'
@ -814,8 +945,8 @@ export function findUsesOfTagInPipe(
console.error(nodeMeta)
return []
}
const node = nodeMeta.node
if (node.type !== 'CallExpression') return []
const node = nodeMeta.stopAtNode
if (!node) return []
const tagIndex = node.callee.name === 'close' ? 1 : 2
const thirdParam = node.arguments[tagIndex]
if (
@ -836,9 +967,14 @@ export function findUsesOfTagInPipe(
console.error(varDec)
return []
}
const varDecNode = varDec.stopAtNode
if (!varDecNode) {
console.error('varDecNode not found')
return []
}
const dependentRanges: SourceRange[] = []
traverse(varDec.node, {
traverse(varDecNode, {
enter: (node) => {
if (
node.type !== 'CallExpression' ||
@ -860,15 +996,16 @@ export function hasSketchPipeBeenExtruded(selection: Selection, ast: Program) {
const path = getNodePathFromSourceRange(ast, selection.range)
const _node = getNodeFromPath<PipeExpression>(ast, path, 'PipeExpression')
if (err(_node)) return false
const { node: pipeExpression } = _node
if (pipeExpression.type !== 'PipeExpression') return false
const { stopAtNode: pipeExpression } = _node
if (!pipeExpression) return false
const _varDec = getNodeFromPath<VariableDeclarator>(
ast,
path,
'VariableDeclarator'
)
if (err(_varDec)) return false
const varDec = _varDec.node
const varDec = _varDec.stopAtNode
if (!varDec) return false
let extruded = false
traverse(ast as any, {
enter(node) {

View File

@ -14,7 +14,11 @@ import {
SourceRange,
CallExpression,
} from '../wasm'
import { getNodeFromPath, getNodePathFromSourceRange } from '../queryAst'
import {
expectNodeOnPath,
getNodeFromPath,
getNodePathFromSourceRange,
} from '../queryAst'
import { enginelessExecutor } from '../../lib/testHelpers'
import { err } from 'lib/trap'
@ -211,7 +215,7 @@ describe('testing addTagForSketchOnFace', () => {
`
const code = genCode(originalLine)
const ast = parse(code)
const programMemory = await enginelessExecutor(ast)
await enginelessExecutor(ast)
const sourceStart = code.indexOf(originalLine)
const sourceRange: [number, number] = [
sourceStart,
@ -600,13 +604,13 @@ describe('testing getConstraintInfo', () => {
]
if (err(ast)) return ast
const pathToNode = getNodePathFromSourceRange(ast, sourceRange)
const callExp = getNodeFromPath<CallExpression>(
const callExp = expectNodeOnPath<CallExpression>(
ast,
pathToNode,
'CallExpression'
)
if (err(callExp)) return callExp
const result = getConstraintInfo(callExp.node, code, pathToNode)
const result = getConstraintInfo(callExp, code, pathToNode)
expect(result).toEqual(expected)
})
})
@ -754,13 +758,13 @@ describe('testing getConstraintInfo', () => {
]
if (err(ast)) return ast
const pathToNode = getNodePathFromSourceRange(ast, sourceRange)
const callExp = getNodeFromPath<CallExpression>(
const callExp = expectNodeOnPath<CallExpression>(
ast,
pathToNode,
'CallExpression'
)
if (err(callExp)) return callExp
const result = getConstraintInfo(callExp.node, code, pathToNode)
const result = getConstraintInfo(callExp, code, pathToNode)
expect(result).toEqual(expected)
})
})
@ -1110,14 +1114,14 @@ describe('testing getConstraintInfo', () => {
]
if (err(ast)) return ast
const pathToNode = getNodePathFromSourceRange(ast, sourceRange)
const callExp = getNodeFromPath<CallExpression>(
const callExp = expectNodeOnPath<CallExpression>(
ast,
pathToNode,
'CallExpression'
)
if (err(callExp)) return callExp
const result = getConstraintInfo(callExp.node, code, pathToNode)
const result = getConstraintInfo(callExp, code, pathToNode)
expect(result).toEqual(expected)
})
})

View File

@ -14,8 +14,10 @@ import {
Identifier,
} from 'lang/wasm'
import {
isNodeType,
expectLastNodeFromPath,
expectNodeOnPath,
getNodeFromPath,
getNodeFromPathCurry,
getNodePathFromSourceRange,
} from 'lang/queryAst'
import {
@ -50,7 +52,7 @@ import {
mutateObjExpProp,
findUniqueName,
} from 'lang/modifyAst'
import { roundOff, getLength, getAngle } from 'lib/utils'
import { roundOff, getLength, getAngle, isArray } from 'lib/utils'
import { err } from 'lib/trap'
import { perpendicularDistance } from 'sketch-helpers'
import { TagDeclarator } from 'wasm-lib/kcl/bindings/TagDeclarator'
@ -330,13 +332,12 @@ export const lineTo: SketchLineHelper = {
referencedSegment,
}) => {
const _node = { ...node }
const nodeMeta = getNodeFromPath<PipeExpression>(
const pipe = expectNodeOnPath<PipeExpression>(
_node,
pathToNode,
'PipeExpression'
)
if (err(nodeMeta)) return nodeMeta
const { node: pipe } = nodeMeta
if (err(pipe)) return pipe
const newVals: [Value, Value] = [
createLiteral(roundOff(to[0], 2)),
@ -373,7 +374,7 @@ export const lineTo: SketchLineHelper = {
},
updateArgs: ({ node, pathToNode, to }) => {
const _node = { ...node }
const nodeMeta = getNodeFromPath<CallExpression>(_node, pathToNode)
const nodeMeta = getNodeFromPath(_node, pathToNode)
if (err(nodeMeta)) return nodeMeta
const { node: callExpression } = nodeMeta
@ -382,8 +383,13 @@ export const lineTo: SketchLineHelper = {
createLiteral(to[1]),
])
mutateArrExp(callExpression.arguments?.[0], toArrExp) ||
mutateObjExpProp(callExpression.arguments?.[0], toArrExp, 'to')
if (isNodeType<CallExpression>(callExpression, 'CallExpression')) {
const firstArg = callExpression.arguments[0]
if (firstArg) {
mutateArrExp(firstArg, toArrExp) ||
mutateObjExpProp(firstArg, toArrExp, 'to')
}
}
return {
modifiedAst: _node,
pathToNode,
@ -414,7 +420,7 @@ export const line: SketchLineHelper = {
spliceBetween,
}) => {
const _node = { ...node }
const nodeMeta = getNodeFromPath<PipeExpression | CallExpression>(
const nodeMeta = getNodeFromPath<PipeExpression>(
_node,
pathToNode,
'PipeExpression'
@ -427,12 +433,16 @@ export const line: SketchLineHelper = {
'VariableDeclarator'
)
if (err(nodeMeta2)) return nodeMeta2
const { node: varDec } = nodeMeta2
const { stopAtNode: varDec } = nodeMeta2
const newXVal = createLiteral(roundOff(to[0] - from[0], 2))
const newYVal = createLiteral(roundOff(to[1] - from[1], 2))
if (spliceBetween && !createCallback && pipe.type === 'PipeExpression') {
if (
spliceBetween &&
!createCallback &&
isNodeType<PipeExpression>(pipe, 'PipeExpression')
) {
const callExp = createCallExpression('line', [
createArrayExpression([newXVal, newYVal]),
createPipeSubstitution(),
@ -455,7 +465,11 @@ export const line: SketchLineHelper = {
}
}
if (replaceExisting && createCallback && pipe.type !== 'CallExpression') {
if (
replaceExisting &&
createCallback &&
isNodeType<PipeExpression>(pipe, 'PipeExpression')
) {
const { index: callIndex } = splitPathAtPipeExpression(pathToNode)
const { callExp, valueUsedInTransform } = createCallback(
[newXVal, newYVal],
@ -477,7 +491,7 @@ export const line: SketchLineHelper = {
createArrayExpression([newXVal, newYVal]),
createPipeSubstitution(),
])
if (pipe.type === 'PipeExpression') {
if (isNodeType<PipeExpression>(pipe, 'PipeExpression')) {
pipe.body = [...pipe.body, callExp]
return {
modifiedAst: _node,
@ -488,6 +502,7 @@ export const line: SketchLineHelper = {
],
}
} else {
if (!varDec) return new Error('Variable declaration not found')
varDec.init = createPipeExpression([varDec.init, callExp])
}
return {
@ -497,7 +512,11 @@ export const line: SketchLineHelper = {
},
updateArgs: ({ node, pathToNode, to, from }) => {
const _node = { ...node }
const nodeMeta = getNodeFromPath<CallExpression>(_node, pathToNode)
const nodeMeta = getNodeFromPath<CallExpression>(
_node,
pathToNode,
'CallExpression'
)
if (err(nodeMeta)) return nodeMeta
const { node: callExpression } = nodeMeta
@ -506,10 +525,15 @@ export const line: SketchLineHelper = {
createLiteral(roundOff(to[1] - from[1], 2)),
])
if (callExpression.arguments?.[0].type === 'ObjectExpression') {
mutateObjExpProp(callExpression.arguments?.[0], toArrExp, 'to')
} else {
mutateArrExp(callExpression.arguments?.[0], toArrExp)
if (isNodeType<CallExpression>(callExpression, 'CallExpression')) {
const firstArg = callExpression.arguments[0]
if (firstArg) {
if (firstArg.type === 'ObjectExpression') {
mutateObjExpProp(firstArg, toArrExp, 'to')
} else {
mutateArrExp(firstArg, toArrExp)
}
}
}
return {
modifiedAst: _node,
@ -531,10 +555,12 @@ export const line: SketchLineHelper = {
export const xLineTo: SketchLineHelper = {
add: ({ node, pathToNode, to, replaceExisting, createCallback }) => {
const _node = { ...node }
const getNode = getNodeFromPathCurry(_node, pathToNode)
const _node1 = getNode<PipeExpression>('PipeExpression')
if (err(_node1)) return _node1
const { node: pipe } = _node1
const pipe = expectLastNodeFromPath<PipeExpression>(
_node,
pathToNode,
'PipeExpression'
)
if (err(pipe)) return pipe
const newVal = createLiteral(roundOff(to[0], 2))
@ -563,14 +589,24 @@ export const xLineTo: SketchLineHelper = {
},
updateArgs: ({ node, pathToNode, to }) => {
const _node = { ...node }
const nodeMeta = getNodeFromPath<CallExpression>(_node, pathToNode)
const nodeMeta = getNodeFromPath<CallExpression>(
_node,
pathToNode,
'CallExpression'
)
if (err(nodeMeta)) return nodeMeta
const { node: callExpression } = nodeMeta
const newX = createLiteral(roundOff(to[0], 2))
if (isLiteralArrayOrStatic(callExpression.arguments?.[0])) {
callExpression.arguments[0] = newX
} else {
mutateObjExpProp(callExpression.arguments?.[0], newX, 'to')
if (isNodeType<CallExpression>(callExpression, 'CallExpression')) {
const firstArg = callExpression.arguments[0]
if (firstArg) {
const newX = createLiteral(roundOff(to[0], 2))
if (isLiteralArrayOrStatic(firstArg)) {
callExpression.arguments[0] = newX
} else {
mutateObjExpProp(firstArg, newX, 'to')
}
}
}
return {
modifiedAst: _node,
@ -592,10 +628,12 @@ export const xLineTo: SketchLineHelper = {
export const yLineTo: SketchLineHelper = {
add: ({ node, pathToNode, to, replaceExisting, createCallback }) => {
const _node = { ...node }
const getNode = getNodeFromPathCurry(_node, pathToNode)
const _node1 = getNode<PipeExpression>('PipeExpression')
if (err(_node1)) return _node1
const { node: pipe } = _node1
const pipe = expectLastNodeFromPath<PipeExpression>(
_node,
pathToNode,
'PipeExpression'
)
if (err(pipe)) return pipe
const newVal = createLiteral(roundOff(to[1], 2))
@ -624,14 +662,24 @@ export const yLineTo: SketchLineHelper = {
},
updateArgs: ({ node, pathToNode, to, from }) => {
const _node = { ...node }
const nodeMeta = getNodeFromPath<CallExpression>(_node, pathToNode)
const nodeMeta = getNodeFromPath<CallExpression>(
_node,
pathToNode,
'CallExpression'
)
if (err(nodeMeta)) return nodeMeta
const { node: callExpression } = nodeMeta
const newY = createLiteral(roundOff(to[1], 2))
if (isLiteralArrayOrStatic(callExpression.arguments?.[0])) {
callExpression.arguments[0] = newY
} else {
mutateObjExpProp(callExpression.arguments?.[0], newY, 'to')
if (isNodeType<CallExpression>(callExpression, 'CallExpression')) {
const firstArg = callExpression.arguments[0]
if (firstArg) {
const newY = createLiteral(roundOff(to[1], 2))
if (isLiteralArrayOrStatic(firstArg)) {
callExpression.arguments[0] = newY
} else {
mutateObjExpProp(firstArg, newY, 'to')
}
}
}
return {
modifiedAst: _node,
@ -653,10 +701,12 @@ export const yLineTo: SketchLineHelper = {
export const xLine: SketchLineHelper = {
add: ({ node, pathToNode, to, from, replaceExisting, createCallback }) => {
const _node = { ...node }
const getNode = getNodeFromPathCurry(_node, pathToNode)
const _node1 = getNode<PipeExpression>('PipeExpression')
if (err(_node1)) return _node1
const { node: pipe } = _node1
const pipe = expectNodeOnPath<PipeExpression>(
_node,
pathToNode,
'PipeExpression'
)
if (err(pipe)) return pipe
const newVal = createLiteral(roundOff(to[0] - from[0], 2))
const firstArg = newVal
@ -684,14 +734,24 @@ export const xLine: SketchLineHelper = {
},
updateArgs: ({ node, pathToNode, to, from }) => {
const _node = { ...node }
const nodeMeta = getNodeFromPath<CallExpression>(_node, pathToNode)
const nodeMeta = getNodeFromPath<CallExpression>(
_node,
pathToNode,
'CallExpression'
)
if (err(nodeMeta)) return nodeMeta
const { node: callExpression } = nodeMeta
const newX = createLiteral(roundOff(to[0] - from[0], 2))
if (isLiteralArrayOrStatic(callExpression.arguments?.[0])) {
callExpression.arguments[0] = newX
} else {
mutateObjExpProp(callExpression.arguments?.[0], newX, 'length')
if (isNodeType<CallExpression>(callExpression, 'CallExpression')) {
const firstArg = callExpression.arguments[0]
if (firstArg) {
const newX = createLiteral(roundOff(to[0] - from[0], 2))
if (isLiteralArrayOrStatic(firstArg)) {
callExpression.arguments[0] = newX
} else {
mutateObjExpProp(firstArg, newX, 'length')
}
}
}
return {
modifiedAst: _node,
@ -713,10 +773,12 @@ export const xLine: SketchLineHelper = {
export const yLine: SketchLineHelper = {
add: ({ node, pathToNode, to, from, replaceExisting, createCallback }) => {
const _node = { ...node }
const getNode = getNodeFromPathCurry(_node, pathToNode)
const _node1 = getNode<PipeExpression>('PipeExpression')
if (err(_node1)) return _node1
const { node: pipe } = _node1
const pipe = expectNodeOnPath<PipeExpression>(
_node,
pathToNode,
'PipeExpression'
)
if (err(pipe)) return pipe
const newVal = createLiteral(roundOff(to[1] - from[1], 2))
if (replaceExisting && createCallback) {
const { index: callIndex } = splitPathAtPipeExpression(pathToNode)
@ -741,14 +803,24 @@ export const yLine: SketchLineHelper = {
},
updateArgs: ({ node, pathToNode, to, from }) => {
const _node = { ...node }
const nodeMeta = getNodeFromPath<CallExpression>(_node, pathToNode)
const nodeMeta = getNodeFromPath<CallExpression>(
_node,
pathToNode,
'CallExpression'
)
if (err(nodeMeta)) return nodeMeta
const { node: callExpression } = nodeMeta
const newY = createLiteral(roundOff(to[1] - from[1], 2))
if (isLiteralArrayOrStatic(callExpression.arguments?.[0])) {
callExpression.arguments[0] = newY
} else {
mutateObjExpProp(callExpression.arguments?.[0], newY, 'length')
if (isNodeType<CallExpression>(callExpression, 'CallExpression')) {
const firstArg = callExpression.arguments[0]
if (firstArg) {
const newY = createLiteral(roundOff(to[1] - from[1], 2))
if (isLiteralArrayOrStatic(firstArg)) {
callExpression.arguments[0] = newY
} else {
mutateObjExpProp(firstArg, newY, 'length')
}
}
}
return {
modifiedAst: _node,
@ -777,8 +849,11 @@ export const tangentialArcTo: SketchLineHelper = {
referencedSegment,
}) => {
const _node = { ...node }
const getNode = getNodeFromPathCurry(_node, pathToNode)
const _node1 = getNode<PipeExpression | CallExpression>('PipeExpression')
const _node1 = getNodeFromPath<PipeExpression>(
_node,
pathToNode,
'PipeExpression'
)
if (err(_node1)) return _node1
const { node: pipe } = _node1
const _node2 = getNodeFromPath<VariableDeclarator>(
@ -787,12 +862,16 @@ export const tangentialArcTo: SketchLineHelper = {
'VariableDeclarator'
)
if (err(_node2)) return _node2
const { node: varDec } = _node2
const { stopAtNode: varDec } = _node2
const toX = createLiteral(roundOff(to[0], 2))
const toY = createLiteral(roundOff(to[1], 2))
if (replaceExisting && createCallback && pipe.type !== 'CallExpression') {
if (
replaceExisting &&
createCallback &&
isNodeType<PipeExpression>(pipe, 'PipeExpression')
) {
const { index: callIndex } = splitPathAtPipeExpression(pathToNode)
const { callExp, valueUsedInTransform } = createCallback(
[toX, toY],
@ -813,7 +892,7 @@ export const tangentialArcTo: SketchLineHelper = {
createArrayExpression([toX, toY]),
createPipeSubstitution(),
])
if (pipe.type === 'PipeExpression') {
if (isNodeType<PipeExpression>(pipe, 'PipeExpression')) {
pipe.body = [...pipe.body, newLine]
return {
modifiedAst: _node,
@ -824,6 +903,7 @@ export const tangentialArcTo: SketchLineHelper = {
],
}
} else {
if (!varDec) return new Error('Variable declaration not found')
varDec.init = createPipeExpression([varDec.init, newLine])
}
return {
@ -833,15 +913,23 @@ export const tangentialArcTo: SketchLineHelper = {
},
updateArgs: ({ node, pathToNode, to, from }) => {
const _node = { ...node }
const nodeMeta = getNodeFromPath<CallExpression>(_node, pathToNode)
const nodeMeta = getNodeFromPath<CallExpression>(
_node,
pathToNode,
'CallExpression'
)
if (err(nodeMeta)) return nodeMeta
const { node: callExpression } = nodeMeta
const x = createLiteral(roundOff(to[0], 2))
const y = createLiteral(roundOff(to[1], 2))
const firstArg = callExpression.arguments?.[0]
if (!mutateArrExp(firstArg, createArrayExpression([x, y]))) {
mutateObjExpProp(firstArg, createArrayExpression([x, y]), 'to')
if (isNodeType<CallExpression>(callExpression, 'CallExpression')) {
const firstArg = callExpression.arguments[0]
if (firstArg) {
if (!mutateArrExp(firstArg, createArrayExpression([x, y]))) {
mutateObjExpProp(firstArg, createArrayExpression([x, y]), 'to')
}
}
}
return {
modifiedAst: _node,
@ -909,10 +997,12 @@ export const angledLine: SketchLineHelper = {
referencedSegment,
}) => {
const _node = { ...node }
const getNode = getNodeFromPathCurry(_node, pathToNode)
const _node1 = getNode<PipeExpression>('PipeExpression')
if (err(_node1)) return _node1
const { node: pipe } = _node1
const pipe = expectNodeOnPath<PipeExpression>(
_node,
pathToNode,
'PipeExpression'
)
if (err(pipe)) return pipe
const newAngleVal = createLiteral(roundOff(getAngle(from, to), 0))
const newLengthVal = createLiteral(roundOff(getLength(from, to), 2))
@ -947,7 +1037,11 @@ export const angledLine: SketchLineHelper = {
},
updateArgs: ({ node, pathToNode, to, from }) => {
const _node = { ...node }
const nodeMeta = getNodeFromPath<CallExpression>(_node, pathToNode)
const nodeMeta = getNodeFromPath<CallExpression>(
_node,
pathToNode,
'CallExpression'
)
if (err(nodeMeta)) return nodeMeta
const { node: callExpression } = nodeMeta
const angle = roundOff(getAngle(from, to), 0)
@ -956,10 +1050,16 @@ export const angledLine: SketchLineHelper = {
const angleLit = createLiteral(angle)
const lengthLit = createLiteral(lineLength)
const firstArg = callExpression.arguments?.[0]
if (!mutateArrExp(firstArg, createArrayExpression([angleLit, lengthLit]))) {
mutateObjExpProp(firstArg, angleLit, 'angle')
mutateObjExpProp(firstArg, lengthLit, 'length')
if (isNodeType<CallExpression>(callExpression, 'CallExpression')) {
const firstArg = callExpression.arguments[0]
if (firstArg) {
if (
!mutateArrExp(firstArg, createArrayExpression([angleLit, lengthLit]))
) {
mutateObjExpProp(firstArg, angleLit, 'angle')
mutateObjExpProp(firstArg, lengthLit, 'length')
}
}
}
return {
@ -993,20 +1093,18 @@ export const angledLineOfXLength: SketchLineHelper = {
replaceExisting,
}) => {
const _node = { ...node }
const nodeMeta = getNodeFromPath<PipeExpression>(
const pipe = expectNodeOnPath<PipeExpression>(
_node,
pathToNode,
'PipeExpression'
)
if (err(nodeMeta)) return nodeMeta
const { node: pipe } = nodeMeta
const nodeMeta2 = getNodeFromPath<VariableDeclarator>(
if (err(pipe)) return pipe
const varDec = expectNodeOnPath<VariableDeclarator>(
_node,
pathToNode,
'VariableDeclarator'
)
if (err(nodeMeta2)) return nodeMeta2
const { node: varDec } = nodeMeta2
if (err(varDec)) return varDec
const variableName = varDec.id.name
const sketch = previousProgramMemory?.get(variableName)
@ -1040,23 +1138,33 @@ export const angledLineOfXLength: SketchLineHelper = {
},
updateArgs: ({ node, pathToNode, to, from }) => {
const _node = { ...node }
const nodeMeta = getNodeFromPath<CallExpression>(_node, pathToNode)
const nodeMeta = getNodeFromPath<CallExpression>(
_node,
pathToNode,
'CallExpression'
)
if (err(nodeMeta)) return nodeMeta
const { node: callExpression } = nodeMeta
const angle = roundOff(getAngle(from, to), 0)
const xLength = roundOff(Math.abs(to[0] - from[0]), 2)
const firstArg = callExpression.arguments?.[0]
const adjustedXLength = isAngleLiteral(firstArg)
? Math.abs(xLength)
: xLength // todo make work for variable angle > 180
if (isNodeType<CallExpression>(callExpression, 'CallExpression')) {
const firstArg = callExpression.arguments[0]
if (firstArg) {
const adjustedXLength = isAngleLiteral(firstArg)
? Math.abs(xLength)
: xLength // todo make work for variable angle > 180
const angleLit = createLiteral(angle)
const lengthLit = createLiteral(adjustedXLength)
const angleLit = createLiteral(angle)
const lengthLit = createLiteral(adjustedXLength)
if (!mutateArrExp(firstArg, createArrayExpression([angleLit, lengthLit]))) {
mutateObjExpProp(firstArg, angleLit, 'angle')
mutateObjExpProp(firstArg, lengthLit, 'length')
if (
!mutateArrExp(firstArg, createArrayExpression([angleLit, lengthLit]))
) {
mutateObjExpProp(firstArg, angleLit, 'angle')
mutateObjExpProp(firstArg, lengthLit, 'length')
}
}
}
return {
@ -1090,20 +1198,18 @@ export const angledLineOfYLength: SketchLineHelper = {
replaceExisting,
}) => {
const _node = { ...node }
const nodeMeta = getNodeFromPath<PipeExpression>(
const pipe = expectNodeOnPath<PipeExpression>(
_node,
pathToNode,
'PipeExpression'
)
if (err(nodeMeta)) return nodeMeta
const { node: pipe } = nodeMeta
const nodeMeta2 = getNodeFromPath<VariableDeclarator>(
if (err(pipe)) return pipe
const varDec = expectNodeOnPath<VariableDeclarator>(
_node,
pathToNode,
'VariableDeclarator'
)
if (err(nodeMeta2)) return nodeMeta2
const { node: varDec } = nodeMeta2
if (err(varDec)) return varDec
const variableName = varDec.id.name
const sketch = previousProgramMemory?.get(variableName)
if (!sketch || sketch.type !== 'SketchGroup') {
@ -1137,23 +1243,33 @@ export const angledLineOfYLength: SketchLineHelper = {
},
updateArgs: ({ node, pathToNode, to, from }) => {
const _node = { ...node }
const nodeMeta = getNodeFromPath<CallExpression>(_node, pathToNode)
const nodeMeta = getNodeFromPath<CallExpression>(
_node,
pathToNode,
'CallExpression'
)
if (err(nodeMeta)) return nodeMeta
const { node: callExpression } = nodeMeta
const angle = roundOff(getAngle(from, to), 0)
const yLength = roundOff(to[1] - from[1], 2)
const firstArg = callExpression.arguments?.[0]
const adjustedYLength = isAngleLiteral(firstArg)
? Math.abs(yLength)
: yLength // todo make work for variable angle > 180
if (isNodeType<CallExpression>(callExpression, 'CallExpression')) {
const firstArg = callExpression.arguments[0]
if (firstArg) {
const adjustedYLength = isAngleLiteral(firstArg)
? Math.abs(yLength)
: yLength // todo make work for variable angle > 180
const angleLit = createLiteral(angle)
const lengthLit = createLiteral(adjustedYLength)
const angleLit = createLiteral(angle)
const lengthLit = createLiteral(adjustedYLength)
if (!mutateArrExp(firstArg, createArrayExpression([angleLit, lengthLit]))) {
mutateObjExpProp(firstArg, angleLit, 'angle')
mutateObjExpProp(firstArg, lengthLit, 'length')
if (
!mutateArrExp(firstArg, createArrayExpression([angleLit, lengthLit]))
) {
mutateObjExpProp(firstArg, angleLit, 'angle')
mutateObjExpProp(firstArg, lengthLit, 'length')
}
}
}
return {
@ -1187,14 +1303,13 @@ export const angledLineToX: SketchLineHelper = {
referencedSegment,
}) => {
const _node = { ...node }
const nodeMeta = getNodeFromPath<PipeExpression>(
const pipe = expectNodeOnPath<PipeExpression>(
_node,
pathToNode,
'PipeExpression'
)
if (err(nodeMeta)) return nodeMeta
if (err(pipe)) return pipe
const { node: pipe } = nodeMeta
const angle = createLiteral(roundOff(getAngle(from, to), 0))
const xArg = createLiteral(roundOff(to[0], 2))
if (replaceExisting && createCallback) {
@ -1227,22 +1342,32 @@ export const angledLineToX: SketchLineHelper = {
},
updateArgs: ({ node, pathToNode, to, from }) => {
const _node = { ...node }
const nodeMeta = getNodeFromPath<CallExpression>(_node, pathToNode)
const nodeMeta = getNodeFromPath<CallExpression>(
_node,
pathToNode,
'CallExpression'
)
if (err(nodeMeta)) return nodeMeta
const { node: callExpression } = nodeMeta
const angle = roundOff(getAngle(from, to), 0)
const xLength = roundOff(to[0], 2)
const firstArg = callExpression.arguments?.[0]
const adjustedXLength = xLength
if (isNodeType<CallExpression>(callExpression, 'CallExpression')) {
const firstArg = callExpression.arguments[0]
if (firstArg) {
const adjustedXLength = xLength
const angleLit = createLiteral(angle)
const lengthLit = createLiteral(adjustedXLength)
const angleLit = createLiteral(angle)
const lengthLit = createLiteral(adjustedXLength)
if (!mutateArrExp(firstArg, createArrayExpression([angleLit, lengthLit]))) {
mutateObjExpProp(firstArg, angleLit, 'angle')
mutateObjExpProp(firstArg, lengthLit, 'to')
if (
!mutateArrExp(firstArg, createArrayExpression([angleLit, lengthLit]))
) {
mutateObjExpProp(firstArg, angleLit, 'angle')
mutateObjExpProp(firstArg, lengthLit, 'to')
}
}
}
return {
modifiedAst: _node,
@ -1275,14 +1400,12 @@ export const angledLineToY: SketchLineHelper = {
referencedSegment,
}) => {
const _node = { ...node }
const nodeMeta = getNodeFromPath<PipeExpression>(
const pipe = expectNodeOnPath<PipeExpression>(
_node,
pathToNode,
'PipeExpression'
)
if (err(nodeMeta)) return nodeMeta
const { node: pipe } = nodeMeta
if (err(pipe)) return pipe
const angle = createLiteral(roundOff(getAngle(from, to), 0))
const yArg = createLiteral(roundOff(to[1], 2))
@ -1317,22 +1440,32 @@ export const angledLineToY: SketchLineHelper = {
},
updateArgs: ({ node, pathToNode, to, from }) => {
const _node = { ...node }
const nodeMeta = getNodeFromPath<CallExpression>(_node, pathToNode)
const nodeMeta = getNodeFromPath<CallExpression>(
_node,
pathToNode,
'CallExpression'
)
if (err(nodeMeta)) return nodeMeta
const { node: callExpression } = nodeMeta
const angle = roundOff(getAngle(from, to), 0)
const xLength = roundOff(to[1], 2)
const firstArg = callExpression.arguments?.[0]
const adjustedXLength = xLength
if (isNodeType<CallExpression>(callExpression, 'CallExpression')) {
const firstArg = callExpression.arguments[0]
if (firstArg) {
const adjustedXLength = xLength
const angleLit = createLiteral(angle)
const lengthLit = createLiteral(adjustedXLength)
const angleLit = createLiteral(angle)
const lengthLit = createLiteral(adjustedXLength)
if (!mutateArrExp(firstArg, createArrayExpression([angleLit, lengthLit]))) {
mutateObjExpProp(firstArg, angleLit, 'angle')
mutateObjExpProp(firstArg, lengthLit, 'to')
if (
!mutateArrExp(firstArg, createArrayExpression([angleLit, lengthLit]))
) {
mutateObjExpProp(firstArg, angleLit, 'angle')
mutateObjExpProp(firstArg, lengthLit, 'to')
}
}
}
return {
modifiedAst: _node,
@ -1372,7 +1505,7 @@ export const angledLineThatIntersects: SketchLineHelper = {
)
if (err(nodeMeta)) return nodeMeta
const { node: pipe } = nodeMeta
const { stopAtNode: pipe } = nodeMeta
const angle = createLiteral(roundOff(getAngle(from, to), 0))
if (!referencedSegment) {
@ -1409,6 +1542,7 @@ export const angledLineThatIntersects: SketchLineHelper = {
]
)
const { index: callIndex } = splitPathAtPipeExpression(pathToNode)
if (!pipe) return new Error('Pipe expression not found')
pipe.body[callIndex] = callExp
return {
modifiedAst: _node,
@ -1420,10 +1554,13 @@ export const angledLineThatIntersects: SketchLineHelper = {
},
updateArgs: ({ node, pathToNode, to, from, previousProgramMemory }) => {
const _node = { ...node }
const nodeMeta = getNodeFromPath<CallExpression>(_node, pathToNode)
if (err(nodeMeta)) return nodeMeta
const callExpression = expectLastNodeFromPath<CallExpression>(
_node,
pathToNode,
'CallExpression'
)
if (err(callExpression)) return callExpression
const { node: callExpression } = nodeMeta
const angle = roundOff(getAngle(from, to), 0)
const firstArg = callExpression.arguments?.[0]
@ -1434,14 +1571,13 @@ export const angledLineThatIntersects: SketchLineHelper = {
: createLiteral('')
const intersectTagName =
intersectTag.type === 'Identifier' ? intersectTag.name : ''
const nodeMeta2 = getNodeFromPath<VariableDeclaration>(
const varDec = expectNodeOnPath<VariableDeclaration>(
_node,
pathToNode,
'VariableDeclaration'
)
if (err(nodeMeta2)) return nodeMeta2
if (err(varDec)) return varDec
const { node: varDec } = nodeMeta2
const varName = varDec.declarations[0].id.name
const sketchGroup = previousProgramMemory.get(varName) as SketchGroup
const intersectPath = sketchGroup.value.find(
@ -1553,11 +1689,16 @@ export const updateStartProfileAtArgs: SketchLineHelper['updateArgs'] = ({
to,
}) => {
const _node = { ...node }
const nodeMeta = getNodeFromPath<CallExpression>(_node, pathToNode)
if (err(nodeMeta)) {
console.error(nodeMeta)
const callExpression = expectLastNodeFromPath<CallExpression>(
_node,
pathToNode,
'CallExpression'
)
if (err(callExpression)) {
console.error(callExpression)
return {
modifiedAst: {
type: 'Program',
start: 0,
end: 0,
body: [],
@ -1572,7 +1713,6 @@ export const updateStartProfileAtArgs: SketchLineHelper['updateArgs'] = ({
}
}
const { node: callExpression } = nodeMeta
const toArrExp = createArrayExpression([
createLiteral(roundOff(to[0])),
createLiteral(roundOff(to[1])),
@ -1615,8 +1755,14 @@ export function changeSketchArguments(
if (err(nodeMeta)) return nodeMeta
const { node: callExpression, shallowPath } = nodeMeta
if (isArray(callExpression)) {
return new Error('Expected call expression but found array')
}
if (!isNodeType<CallExpression>(callExpression, 'CallExpression')) {
return new Error('Call expression not found')
}
if (callExpression?.callee?.name in sketchLineHelperMap) {
if (callExpression.callee.name in sketchLineHelperMap) {
const { updateArgs } = sketchLineHelperMap[callExpression.callee.name]
if (!updateArgs) {
return new Error('not a sketch line helper')
@ -1631,7 +1777,7 @@ export function changeSketchArguments(
})
}
return new Error(`not a sketch line helper: ${callExpression?.callee?.name}`)
return new Error(`not a sketch line helper: ${callExpression.callee.name}`)
}
export function getConstraintInfo(
@ -1737,10 +1883,13 @@ export function addCallExpressionsToPipe({
)
if (err(pipeExpression)) return pipeExpression
if (pipeExpression.node.type !== 'PipeExpression') {
if (!pipeExpression.stopAtNode) {
return new Error('not a pipe expression')
}
pipeExpression.node.body = [...pipeExpression.node.body, ...expressions]
pipeExpression.stopAtNode.body = [
...pipeExpression.stopAtNode.body,
...expressions,
]
return _node
}
@ -1763,10 +1912,13 @@ export function addCloseToPipe({
)
if (err(pipeExpression)) return pipeExpression
if (pipeExpression.node.type !== 'PipeExpression') {
if (!pipeExpression.stopAtNode) {
return new Error('not a pipe expression')
}
pipeExpression.node.body = [...pipeExpression.node.body, closeExpression]
pipeExpression.stopAtNode.body = [
...pipeExpression.stopAtNode.body,
closeExpression,
]
return _node
}
@ -1854,18 +2006,16 @@ type addTagFn = (a: AddTagInfo) => { modifiedAst: Program; tag: string } | Error
function addTag(tagIndex = 2): addTagFn {
return ({ node, pathToNode }) => {
const _node = { ...node }
const callExpr = getNodeFromPath<CallExpression>(
const primaryCallExp = expectNodeOnPath<CallExpression>(
_node,
pathToNode,
'CallExpression'
)
if (err(callExpr)) return callExpr
const { node: primaryCallExp } = callExpr
if (err(primaryCallExp)) return primaryCallExp
// Tag is always 3rd expression now, using arg index feels brittle
// but we can come up with a better way to identify tag later.
const thirdArg = primaryCallExp.arguments?.[tagIndex]
const thirdArg = primaryCallExp.arguments[tagIndex]
const tagDeclarator =
thirdArg ||
(createTagDeclarator(findUniqueName(_node, 'seg', 2)) as TagDeclarator)

View File

@ -1,4 +1,4 @@
import { getNodeFromPath } from 'lang/queryAst'
import { getLastNodeFromPath } from 'lang/queryAst'
import { ToolTip, toolTips } from 'lang/langHelpers'
import {
Program,
@ -8,9 +8,9 @@ import {
SourceRange,
Path,
PathToNode,
Value,
} from '../wasm'
import { err } from 'lib/trap'
import { isArray } from 'lib/utils'
export function getSketchSegmentFromPathToNode(
sketchGroup: SketchGroup,
@ -25,11 +25,14 @@ export function getSketchSegmentFromPathToNode(
// TODO: once pathTodNode is stored on program memory as part of execution,
// we can check if the pathToNode matches the pathToNode of the sketchGroup.
// For now we fall back to the sourceRange
const nodeMeta = getNodeFromPath<Value>(ast, pathToNode)
const nodeMeta = getLastNodeFromPath(ast, pathToNode)
if (err(nodeMeta)) return nodeMeta
const { node } = nodeMeta
if (isArray(node)) {
return new Error('Value node expected, but found array')
}
const node = nodeMeta.node
if (!node || typeof node.start !== 'number' || !node.end)
if (typeof node.start !== 'number' || !node.end)
return new Error('no node found')
const sourceRange: SourceRange = [node.start, node.end]
return getSketchSegmentFromSourceRange(sketchGroup, sourceRange)

View File

@ -12,6 +12,9 @@ import {
ProgramMemory,
} from '../wasm'
import {
isNodeType,
expectNodeOnPath,
getLastNodeFromPath,
getNodeFromPath,
getNodeFromPathCurry,
getNodePathFromSourceRange,
@ -39,7 +42,7 @@ import {
getSketchSegmentFromPathToNode,
getSketchSegmentFromSourceRange,
} from './sketchConstraints'
import { getAngle, roundOff, normaliseAngle } from '../../lib/utils'
import { getAngle, roundOff, normaliseAngle, isArray } from '../../lib/utils'
export type LineInputsType =
| 'xAbsolute'
@ -1225,22 +1228,19 @@ export function removeSingleConstraint({
objectProperty?: string
ast: Program
}): TransformInfo | false {
const callExp = getNodeFromPath<CallExpression>(
const callExp = expectNodeOnPath<CallExpression>(
ast,
pathToCallExp,
'CallExpression'
'CallExpression',
{ message: 'Invalid node type' }
)
if (err(callExp)) {
console.error(callExp)
return false
}
if (callExp.node.type !== 'CallExpression') {
console.error(new Error('Invalid node type'))
return false
}
const transform: TransformInfo = {
tooltip: callExp.node.callee.name as any,
tooltip: callExp.callee.name as any,
createNode:
({ tag, referenceSegName, varValues }) =>
(_, rawValues) => {
@ -1264,7 +1264,7 @@ export function removeSingleConstraint({
})
const objExp = createObjectExpression(expression)
return createStdlibCallExpression(
callExp.node.callee.name as any,
callExp.callee.name as any,
objExp,
tag
)
@ -1289,7 +1289,7 @@ export function removeSingleConstraint({
return varValue.value
})
return createStdlibCallExpression(
callExp.node.callee.name as any,
callExp.callee.name as any,
createArrayExpression(values),
tag
)
@ -1298,7 +1298,7 @@ export function removeSingleConstraint({
// if (typeof arrayIndex !== 'number' || !objectProperty) must be single value input xLine, yLineTo etc
return createCallWrapper(
callExp.node.callee.name as any,
callExp.callee.name as any,
rawValues[0].value,
tag
)
@ -1416,7 +1416,7 @@ export function getTransformInfos(
getNodePathFromSourceRange(ast, range)
)
const nodes = paths.map((pathToNode) =>
getNodeFromPath<Value>(ast, pathToNode, 'CallExpression')
getNodeFromPath<CallExpression>(ast, pathToNode, 'CallExpression')
)
try {
@ -1426,9 +1426,8 @@ export function getTransformInfos(
return false
}
const node = nodeMeta.node
if (node?.type === 'CallExpression')
return getTransformInfo(node, constraintType)
const node = nodeMeta.stopAtNode
if (node) return getTransformInfo(node, constraintType)
return false
}) as TransformInfo[]
@ -1448,9 +1447,7 @@ export function getRemoveConstraintsTransforms(
const paths = selectionRanges.codeBasedSelections.map((selectionRange) =>
getNodePathFromSourceRange(ast, selectionRange.range)
)
const nodes = paths.map((pathToNode) =>
getNodeFromPath<Value>(ast, pathToNode)
)
const nodes = paths.map((pathToNode) => getLastNodeFromPath(ast, pathToNode))
const theTransforms = nodes.map((nodeMeta) => {
// Typescript is not smart enough to know node will never be Error
@ -1461,7 +1458,11 @@ export function getRemoveConstraintsTransforms(
}
const node = nodeMeta.node
if (node?.type === 'CallExpression')
if (isArray(node)) {
console.error('Expected node, but found Array')
return false
}
if (isNodeType<CallExpression>(node, 'CallExpression'))
return getRemoveConstraintsTransform(node, constraintType)
return false
@ -1579,15 +1580,17 @@ export function transformAstSketchLines({
const callExp = getNode<CallExpression>('CallExpression')
if (err(callExp)) return callExp
if (!callExp.stopAtNode) return new Error('Call expression not found')
const varDec = getNode<VariableDeclarator>('VariableDeclarator')
if (err(varDec)) return varDec
if (!varDec.stopAtNode) return new Error('Variable declaration not found')
const firstArg = getFirstArg(callExp.node)
const firstArg = getFirstArg(callExp.stopAtNode)
if (err(firstArg)) return firstArg
const callBackTag = callExp.node.arguments[2]
const callBackTag = callExp.stopAtNode.arguments[2]
const _referencedSegmentNameVal =
callExp.node.arguments[0]?.type === 'ObjectExpression' &&
callExp.node.arguments[0].properties?.find(
callExp.stopAtNode.arguments[0]?.type === 'ObjectExpression' &&
callExp.stopAtNode.arguments[0].properties?.find(
(prop) => prop.key.name === 'intersectTag'
)?.value
const _referencedSegmentName =
@ -1601,7 +1604,7 @@ export function transformAstSketchLines({
const varValues: VarValues = []
getConstraintInfo(callExp.node, '', _pathToNode).forEach((a) => {
getConstraintInfo(callExp.stopAtNode, '', _pathToNode).forEach((a) => {
if (
a.type === 'tangentialWithPrevious' ||
a.type === 'horizontal' ||
@ -1609,33 +1612,46 @@ export function transformAstSketchLines({
)
return
const nodeMeta = getNodeFromPath<Value>(ast, a.pathToNode)
const nodeMeta = getLastNodeFromPath(ast, a.pathToNode)
if (err(nodeMeta)) return
// TODO: Assert that the node is a valid value.
if (a?.argPosition?.type === 'arrayItem') {
if (isArray(nodeMeta.node)) {
console.log('Expected Value, but found Array')
return
}
varValues.push({
type: 'arrayItem',
index: a.argPosition.index,
value: nodeMeta.node,
value: nodeMeta.node as Value,
argType: a.type,
})
} else if (a?.argPosition?.type === 'objectProperty') {
if (isArray(nodeMeta.node)) {
console.log('Expected Value, but found Array')
return
}
varValues.push({
type: 'objectProperty',
key: a.argPosition.key,
value: nodeMeta.node,
value: nodeMeta.node as Value,
argType: a.type,
})
} else if (a?.argPosition?.type === 'singleValue') {
if (isArray(nodeMeta.node)) {
console.log('Expected Value, but found Array')
return
}
varValues.push({
type: 'singleValue',
argType: a.type,
value: nodeMeta.node,
value: nodeMeta.node as Value,
})
}
})
const varName = varDec.node.id.name
const varName = varDec.stopAtNode.id.name
let sketchGroup = programMemory.get(varName)
if (sketchGroup?.type === 'ExtrudeGroup') {
sketchGroup = sketchGroup.sketchGroup
@ -1669,7 +1685,7 @@ export function transformAstSketchLines({
programMemory,
pathToNode: _pathToNode,
referencedSegment,
fnName: transformTo || (callExp.node.callee.name as ToolTip),
fnName: transformTo || (callExp.stopAtNode.callee.name as ToolTip),
to,
from,
createCallback: callBack({
@ -1743,15 +1759,14 @@ export function getConstraintLevelFromSourceRange(
ast: Program | Error
): Error | { range: [number, number]; level: ConstraintLevel } {
if (err(ast)) return ast
const nodeMeta = getNodeFromPath<CallExpression>(
const sketchFnExp = expectNodeOnPath<CallExpression>(
ast,
getNodePathFromSourceRange(ast, cursorRange),
'CallExpression'
)
if (err(nodeMeta)) return nodeMeta
if (err(sketchFnExp)) return sketchFnExp
const { node: sketchFnExp } = nodeMeta
const name = sketchFnExp?.callee?.name as ToolTip
const name = sketchFnExp.callee.name as ToolTip
const range: [number, number] = [sketchFnExp.start, sketchFnExp.end]
if (!toolTips.includes(name)) return { level: 'free', range: range }

View File

@ -24,13 +24,6 @@ export const getRectangleCallExpressions = (
rectangleOrigin: [number, number],
tags: [string, string, string]
) => [
createCallExpressionStdLib('startProfileAt', [
createArrayExpression([
createLiteral(roundOff(rectangleOrigin[0])),
createLiteral(roundOff(rectangleOrigin[1])),
]),
createPipeSubstitution(),
]),
createCallExpressionStdLib('angledLine', [
createArrayExpression([
createLiteral(0), // 0 deg

View File

@ -5,15 +5,16 @@ import {
kclManager,
sceneEntitiesManager,
} from 'lib/singletons'
import { CallExpression, SourceRange, Value, parse, recast } from 'lang/wasm'
import { CallExpression, SourceRange, parse, recast } from 'lang/wasm'
import { ModelingMachineEvent } from 'machines/modelingMachine'
import { uuidv4 } from 'lib/utils'
import { isArray, uuidv4 } from 'lib/utils'
import { EditorSelection, SelectionRange } from '@codemirror/state'
import { getNormalisedCoordinates, isOverlap } from 'lib/utils'
import { isCursorInSketchCommandRange } from 'lang/util'
import { Program } from 'lang/wasm'
import {
doesPipeHaveCallExp,
getLastNodeFromPath,
getNodeFromPath,
hasSketchPipeBeenExtruded,
isSingleCursorInPipe,
@ -177,7 +178,11 @@ export function getEventForSegmentSelection(
)
if (err(nodeMeta)) return null
const node = nodeMeta.node
const node = nodeMeta.stopAtNode
if (!node) {
console.error('Call expression not found')
return null
}
const range: SourceRange = [node.start, node.end]
return {
type: 'Set selection',
@ -300,7 +305,11 @@ function updateSceneObjectColors(codeBasedSelections: Selection[]) {
'CallExpression'
)
if (err(nodeMeta)) return
const node = nodeMeta.node
const node = nodeMeta.stopAtNode
if (!node) {
console.error('Call expression not found')
return
}
const groupHasCursor = codeBasedSelections.some((selection) => {
return isOverlap(selection.range, [node.start, node.end])
})
@ -597,9 +606,10 @@ export function updateSelections(
const newSelections = Object.entries(pathToNodeMap)
.map(([index, pathToNode]): Selection | undefined => {
const nodeMeta = getNodeFromPath<Value>(ast, pathToNode)
const nodeMeta = getLastNodeFromPath(ast, pathToNode)
if (err(nodeMeta)) return undefined
const node = nodeMeta.node
if (isArray(node)) return undefined
return {
range: [node.start, node.end],
type: prevSelectionRanges.codeBasedSelections[Number(index)]?.type,

View File

@ -4,6 +4,13 @@ import { v4 } from 'uuid'
export const uuidv4 = v4
/**
* A safer type guard for arrays since the built-in Array.isArray() asserts `any[]`.
*/
export function isArray(val: any): val is unknown[] {
return Array.isArray(val)
}
export function isOverlap(a: SourceRange, b: SourceRange) {
const [startingRange, secondRange] = a[0] < b[0] ? [a, b] : [b, a]
const [lastOfFirst, firstOfSecond] = [startingRange[1], secondRange[0]]

View File

@ -11,6 +11,7 @@ import { SidebarType } from 'components/ModelingSidebar/ModelingPanes'
import {
isNodeSafeToReplacePath,
getNodePathFromSourceRange,
expectNodeOnPath,
} from 'lang/queryAst'
import {
kclManager,
@ -879,8 +880,8 @@ export const modelingMachine = createMachine(
'VariableDeclarator'
)
if (err(variableDeclaration)) return false
if (variableDeclaration.node.type !== 'VariableDeclarator') return false
const pipeExpression = variableDeclaration.node.init
if (!variableDeclaration.stopAtNode) return false
const pipeExpression = variableDeclaration.stopAtNode.init
if (pipeExpression.type !== 'PipeExpression') return false
const hasStartSketchOn = pipeExpression.body.some(
(item) =>
@ -1082,7 +1083,9 @@ export const modelingMachine = createMachine(
},
})
if (!engineCommandManager.engineConnection?.idleMode) {
store.videoElement?.play()
store.videoElement?.play().catch((e) => {
console.warn('Video playing was prevented', e)
})
}
if (updatedAst?.selections) {
editorManager.selectRange(updatedAst?.selections)
@ -1132,13 +1135,13 @@ export const modelingMachine = createMachine(
selection.codeBasedSelections[0].range
)
const varDecNode = getNodeFromPath<VariableDeclaration>(
const varDecNode = expectNodeOnPath<VariableDeclaration>(
ast,
pathToSegmentNode,
'VariableDeclaration'
)
if (err(varDecNode)) return
const sketchVar = varDecNode.node.declarations[0].id.name
const sketchVar = varDecNode.declarations[0].id.name
const sketchGroup = kclManager.programMemory.get(sketchVar)
if (sketchGroup?.type !== 'SketchGroup') return
const idArtifact = engineCommandManager.artifactMap[sketchGroup.id]
@ -1238,7 +1241,20 @@ export const modelingMachine = createMachine(
},
'listen for rectangle origin': ({ sketchDetails }) => {
if (!sketchDetails) return
sceneEntitiesManager.setupRectangleOriginListener()
sceneEntitiesManager.setupNoPointsListener({
sketchDetails,
afterClick: (args) => {
const twoD = args.intersectionPoint?.twoD
if (twoD) {
sceneInfra.modelingSend({
type: 'Add rectangle origin',
data: [twoD.x, twoD.y],
})
} else {
console.error('No intersection point found')
}
},
})
},
'set up draft rectangle': ({ sketchDetails }, { data }) => {
if (!sketchDetails || !data) return
@ -1268,39 +1284,10 @@ export const modelingMachine = createMachine(
},
'setup noPoints onClick listener': ({ sketchDetails }) => {
if (!sketchDetails) return
sceneEntitiesManager.createIntersectionPlane()
const quaternion = quaternionFromUpNForward(
new Vector3(...sketchDetails.yAxis),
new Vector3(...sketchDetails.zAxis)
)
sceneEntitiesManager.intersectionPlane &&
sceneEntitiesManager.intersectionPlane.setRotationFromQuaternion(
quaternion
)
sceneEntitiesManager.intersectionPlane &&
sceneEntitiesManager.intersectionPlane.position.copy(
new Vector3(...(sketchDetails?.origin || [0, 0, 0]))
)
sceneInfra.setCallbacks({
onClick: async (args) => {
if (!args) return
if (args.mouseEvent.which !== 1) return
const { intersectionPoint } = args
if (!intersectionPoint?.twoD || !sketchDetails?.sketchPathToNode)
return
const addStartProfileAtRes = addStartProfileAt(
kclManager.ast,
sketchDetails.sketchPathToNode,
[intersectionPoint.twoD.x, intersectionPoint.twoD.y]
)
if (trap(addStartProfileAtRes)) return
const { modifiedAst } = addStartProfileAtRes
await kclManager.updateAst(modifiedAst, false)
sceneEntitiesManager.removeIntersectionPlane()
sceneInfra.modelingSend('Add start point')
},
sceneEntitiesManager.setupNoPointsListener({
sketchDetails,
afterClick: () => sceneInfra.modelingSend('Add start point'),
})
},
'add axis n grid': ({ sketchDetails }) => {
@ -1639,14 +1626,13 @@ export function isEditingExistingSketch({
// should check that the variable declaration is a pipeExpression
// and that the pipeExpression contains a "startProfileAt" callExpression
if (!sketchDetails?.sketchPathToNode) return false
const variableDeclaration = getNodeFromPath<VariableDeclarator>(
const variableDeclaration = expectNodeOnPath<VariableDeclarator>(
kclManager.ast,
sketchDetails.sketchPathToNode,
'VariableDeclarator'
)
if (err(variableDeclaration)) return false
if (variableDeclaration.node.type !== 'VariableDeclarator') return false
const pipeExpression = variableDeclaration.node.init
const pipeExpression = variableDeclaration.init
if (pipeExpression.type !== 'PipeExpression') return false
const hasStartProfileAt = pipeExpression.body.some(
(item) =>
@ -1668,5 +1654,5 @@ export function canRectangleTool({
// This should not be returning false, and it should be caught
// but we need to simulate old behavior to move on.
if (err(node)) return false
return node.node?.declarations?.[0]?.init.type !== 'PipeExpression'
return node.stopAtNode?.declarations?.[0]?.init.type !== 'PipeExpression'
}

View File

@ -86,7 +86,7 @@ export function useDemoCode() {
await kclManager.executeCode(true).then(() => {
kclManager.isFirstRender = false
})
codeManager.writeToFile()
await codeManager.writeToFile()
})
}, [editorManager.editorView])
}

View File

@ -1,9 +1,7 @@
# Each test can have at most 4 threads, but if its name contains "serial_test_", then it
# also requires 4 threads.
# This means such tests run one at a time, with 4 threads.
[test-groups]
serial-integration = { max-threads = 4 }
# If a test uses the engine, we want to limit the number that can run in parallel.
# This way we don't start and stop too many engine instances, putting pressure on our cloud.
uses-engine = { max-threads = 4 }
[profile.default]
slow-timeout = { period = "30s", terminate-after = 1 }
@ -12,13 +10,15 @@ slow-timeout = { period = "30s", terminate-after = 1 }
slow-timeout = { period = "50s", terminate-after = 5 }
[[profile.default.overrides]]
filter = "test(serial_test_)"
test-group = "serial-integration"
# If a test starts with kcl_test_, then it uses the engine. So, limit its parallelism.
filter = "test(kcl_test_)"
test-group = "uses-engine"
threads-required = 2
[[profile.ci.overrides]]
filter = "test(serial_test_)"
test-group = "serial-integration"
# If a test starts with kcl_test_, then it uses the engine. So, limit its parallelism.
filter = "test(kcl_test_)"
test-group = "uses-engine"
threads-required = 2
[[profile.default.overrides]]

View File

@ -406,9 +406,9 @@ dependencies = [
[[package]]
name = "clap"
version = "4.5.11"
version = "4.5.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "35723e6a11662c2afb578bcf0b88bf6ea8e21282a953428f240574fcc3a2b5b3"
checksum = "0fbb260a053428790f3de475e304ff84cdbc4face759ea7a3e64c1edd938a7fc"
dependencies = [
"clap_builder",
"clap_derive",
@ -416,9 +416,9 @@ dependencies = [
[[package]]
name = "clap_builder"
version = "4.5.11"
version = "4.5.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49eb96cbfa7cfa35017b7cd548c75b14c3118c98b423041d70562665e07fb0fa"
checksum = "64b17d7ea74e9f833c7dbf2cbe4fb12ff26783eda4782a8975b72f895c9b4d99"
dependencies = [
"anstream",
"anstyle",
@ -430,9 +430,9 @@ dependencies = [
[[package]]
name = "clap_derive"
version = "4.5.11"
version = "4.5.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d029b67f89d30bbb547c89fd5161293c0aec155fc691d7924b64550662db93e"
checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0"
dependencies = [
"heck 0.5.0",
"proc-macro2",
@ -718,7 +718,7 @@ dependencies = [
[[package]]
name = "derive-docs"
version = "0.1.20"
version = "0.1.21"
dependencies = [
"Inflector",
"anyhow",
@ -1391,7 +1391,7 @@ dependencies = [
[[package]]
name = "kcl-lib"
version = "0.2.2"
version = "0.2.3"
dependencies = [
"anyhow",
"approx",
@ -1460,7 +1460,7 @@ dependencies = [
[[package]]
name = "kcl-test-server"
version = "0.1.3"
version = "0.1.4"
dependencies = [
"anyhow",
"hyper",
@ -1473,9 +1473,9 @@ dependencies = [
[[package]]
name = "kittycad"
version = "0.3.8"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d95daf74937915b31aa164ba7b34a5d1e0f6a82de748addd926b4dc6c2760c44"
checksum = "36b87a9cca545825ba18005c1944b8525fac28867d99984178bf22c79fb5ec25"
dependencies = [
"anyhow",
"async-trait",
@ -3128,9 +3128,9 @@ dependencies = [
[[package]]
name = "toml"
version = "0.8.16"
version = "0.8.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81967dd0dd2c1ab0bc3468bd7caecc32b8a4aa47d0c8c695d8c2b2108168d62c"
checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e"
dependencies = [
"serde",
"serde_spanned",
@ -3140,24 +3140,24 @@ dependencies = [
[[package]]
name = "toml_datetime"
version = "0.6.7"
version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8fb9f64314842840f1d940ac544da178732128f1c78c21772e876579e0da1db"
checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41"
dependencies = [
"serde",
]
[[package]]
name = "toml_edit"
version = "0.22.17"
version = "0.22.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d9f8729f5aea9562aac1cc0441f5d6de3cff1ee0c5d67293eeca5eb36ee7c16"
checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d"
dependencies = [
"indexmap 2.2.5",
"serde",
"serde_spanned",
"toml_datetime",
"winnow 0.6.5",
"winnow 0.6.18",
]
[[package]]
@ -3851,9 +3851,9 @@ dependencies = [
[[package]]
name = "winnow"
version = "0.6.5"
version = "0.6.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dffa400e67ed5a4dd237983829e66475f0a4a26938c4b04c21baede6262215b8"
checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f"
dependencies = [
"memchr",
]

View File

@ -11,13 +11,13 @@ crate-type = ["cdylib"]
[dependencies]
bson = { version = "2.11.0", features = ["uuid-1", "chrono"] }
clap = "4.5.11"
clap = "4.5.13"
gloo-utils = "0.2.0"
kcl-lib = { path = "kcl" }
kittycad.workspace = true
serde_json = "1.0.121"
tokio = { version = "1.39.2", features = ["sync"] }
toml = "0.8.16"
toml = "0.8.19"
uuid = { version = "1.10.0", features = ["v4", "js", "serde"] }
wasm-bindgen = "0.2.91"
wasm-bindgen-futures = "0.4.42"
@ -69,7 +69,7 @@ members = [
]
[workspace.dependencies]
kittycad = { version = "0.3.8", default-features = false, features = ["js", "requests"] }
kittycad = { version = "0.3.9", default-features = false, features = ["js", "requests"] }
kittycad-modeling-session = "0.1.4"
[[test]]

View File

@ -1,7 +1,7 @@
[package]
name = "derive-docs"
description = "A tool for generating documentation from Rust derive macros"
version = "0.1.20"
version = "0.1.21"
edition = "2021"
license = "MIT"
repository = "https://github.com/KittyCAD/modeling-app"

View File

@ -766,79 +766,10 @@ fn generate_code_block_test(fn_name: &str, code_block: &str, index: usize) -> pr
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
async fn #test_name() {
let user_agent = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
let http_client = reqwest::Client::builder()
.user_agent(user_agent)
// For file conversions we need this to be long.
.timeout(std::time::Duration::from_secs(600))
.connect_timeout(std::time::Duration::from_secs(60));
let ws_client = reqwest::Client::builder()
.user_agent(user_agent)
// For file conversions we need this to be long.
.timeout(std::time::Duration::from_secs(600))
.connect_timeout(std::time::Duration::from_secs(60))
.connection_verbose(true)
.tcp_keepalive(std::time::Duration::from_secs(600))
.http1_only();
let token = std::env::var("KITTYCAD_API_TOKEN").expect("KITTYCAD_API_TOKEN not set");
// Create the client.
let mut client = kittycad::Client::new_from_reqwest(token, http_client, ws_client);
// Set a local engine address if it's set.
if let Ok(addr) = std::env::var("LOCAL_ENGINE_ADDR") {
client.set_base_url(addr);
}
let tokens = crate::token::lexer(#code_block).unwrap();
let parser = crate::parser::Parser::new(tokens);
let program = parser.ast().unwrap();
let ctx = crate::executor::ExecutorContext::new(&client, Default::default()).await.unwrap();
ctx.run(&program, None).await.unwrap();
// Zoom to fit.
ctx.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
crate::executor::SourceRange::default(),
kittycad::types::ModelingCmd::ZoomToFit {
object_ids: Default::default(),
padding: 0.1,
},
)
.await.unwrap();
// Send a snapshot request to the engine.
let resp = ctx
.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
crate::executor::SourceRange::default(),
kittycad::types::ModelingCmd::TakeSnapshot {
format: kittycad::types::ImageFormat::Png,
},
)
.await.unwrap();
// Create a temporary file to write the output to.
let output_file = std::env::temp_dir().join(format!("kcl_output_{}.png", uuid::Uuid::new_v4()));
if let kittycad::types::OkWebSocketResponseData::Modeling {
modeling_response: kittycad::types::OkModelingCmdResponse::TakeSnapshot { data },
} = &resp
{
// Save the snapshot locally.
std::fs::write(&output_file, &data.contents.0).unwrap();
} else {
panic!("Unexpected response from engine: {:?}", resp);
}
// Read the output file.
let actual = image::io::Reader::open(output_file).unwrap().decode().unwrap();
twenty_twenty::assert_image(&format!("tests/outputs/{}.png", #test_name_str), &actual, 0.99);
let code = #code_block;
// Note, `crate` must be kcl_lib
let result = crate::test_server::execute_and_snapshot(code, crate::settings::types::UnitLength::Mm).await.unwrap();
twenty_twenty::assert_image(&format!("tests/outputs/{}.png", #test_name_str), &result, 0.99);
}
}
}

View File

@ -21,71 +21,14 @@ mod test_examples_someFn {
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
async fn serial_test_example_someFn0() {
let user_agent = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
let http_client = reqwest::Client::builder()
.user_agent(user_agent)
.timeout(std::time::Duration::from_secs(600))
.connect_timeout(std::time::Duration::from_secs(60));
let ws_client = reqwest::Client::builder()
.user_agent(user_agent)
.timeout(std::time::Duration::from_secs(600))
.connect_timeout(std::time::Duration::from_secs(60))
.connection_verbose(true)
.tcp_keepalive(std::time::Duration::from_secs(600))
.http1_only();
let token = std::env::var("KITTYCAD_API_TOKEN").expect("KITTYCAD_API_TOKEN not set");
let mut client = kittycad::Client::new_from_reqwest(token, http_client, ws_client);
if let Ok(addr) = std::env::var("LOCAL_ENGINE_ADDR") {
client.set_base_url(addr);
}
let tokens = crate::token::lexer("someFn()").unwrap();
let parser = crate::parser::Parser::new(tokens);
let program = parser.ast().unwrap();
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
.await
.unwrap();
ctx.run(&program, None).await.unwrap();
ctx.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
crate::executor::SourceRange::default(),
kittycad::types::ModelingCmd::ZoomToFit {
object_ids: Default::default(),
padding: 0.1,
},
)
.await
.unwrap();
let resp = ctx
.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
crate::executor::SourceRange::default(),
kittycad::types::ModelingCmd::TakeSnapshot {
format: kittycad::types::ImageFormat::Png,
},
)
.await
.unwrap();
let output_file =
std::env::temp_dir().join(format!("kcl_output_{}.png", uuid::Uuid::new_v4()));
if let kittycad::types::OkWebSocketResponseData::Modeling {
modeling_response: kittycad::types::OkModelingCmdResponse::TakeSnapshot { data },
} = &resp
{
std::fs::write(&output_file, &data.contents.0).unwrap();
} else {
panic!("Unexpected response from engine: {:?}", resp);
}
let actual = image::io::Reader::open(output_file)
.unwrap()
.decode()
.unwrap();
let code = "someFn()";
let result =
crate::test_server::execute_and_snapshot(code, crate::settings::types::UnitLength::Mm)
.await
.unwrap();
twenty_twenty::assert_image(
&format!("tests/outputs/{}.png", "serial_test_example_someFn0"),
&actual,
&result,
0.99,
);
}

View File

@ -21,71 +21,14 @@ mod test_examples_someFn {
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
async fn serial_test_example_someFn0() {
let user_agent = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
let http_client = reqwest::Client::builder()
.user_agent(user_agent)
.timeout(std::time::Duration::from_secs(600))
.connect_timeout(std::time::Duration::from_secs(60));
let ws_client = reqwest::Client::builder()
.user_agent(user_agent)
.timeout(std::time::Duration::from_secs(600))
.connect_timeout(std::time::Duration::from_secs(60))
.connection_verbose(true)
.tcp_keepalive(std::time::Duration::from_secs(600))
.http1_only();
let token = std::env::var("KITTYCAD_API_TOKEN").expect("KITTYCAD_API_TOKEN not set");
let mut client = kittycad::Client::new_from_reqwest(token, http_client, ws_client);
if let Ok(addr) = std::env::var("LOCAL_ENGINE_ADDR") {
client.set_base_url(addr);
}
let tokens = crate::token::lexer("someFn()").unwrap();
let parser = crate::parser::Parser::new(tokens);
let program = parser.ast().unwrap();
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
.await
.unwrap();
ctx.run(&program, None).await.unwrap();
ctx.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
crate::executor::SourceRange::default(),
kittycad::types::ModelingCmd::ZoomToFit {
object_ids: Default::default(),
padding: 0.1,
},
)
.await
.unwrap();
let resp = ctx
.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
crate::executor::SourceRange::default(),
kittycad::types::ModelingCmd::TakeSnapshot {
format: kittycad::types::ImageFormat::Png,
},
)
.await
.unwrap();
let output_file =
std::env::temp_dir().join(format!("kcl_output_{}.png", uuid::Uuid::new_v4()));
if let kittycad::types::OkWebSocketResponseData::Modeling {
modeling_response: kittycad::types::OkModelingCmdResponse::TakeSnapshot { data },
} = &resp
{
std::fs::write(&output_file, &data.contents.0).unwrap();
} else {
panic!("Unexpected response from engine: {:?}", resp);
}
let actual = image::io::Reader::open(output_file)
.unwrap()
.decode()
.unwrap();
let code = "someFn()";
let result =
crate::test_server::execute_and_snapshot(code, crate::settings::types::UnitLength::Mm)
.await
.unwrap();
twenty_twenty::assert_image(
&format!("tests/outputs/{}.png", "serial_test_example_someFn0"),
&actual,
&result,
0.99,
);
}

View File

@ -21,71 +21,14 @@ mod test_examples_show {
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
async fn serial_test_example_show0() {
let user_agent = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
let http_client = reqwest::Client::builder()
.user_agent(user_agent)
.timeout(std::time::Duration::from_secs(600))
.connect_timeout(std::time::Duration::from_secs(60));
let ws_client = reqwest::Client::builder()
.user_agent(user_agent)
.timeout(std::time::Duration::from_secs(600))
.connect_timeout(std::time::Duration::from_secs(60))
.connection_verbose(true)
.tcp_keepalive(std::time::Duration::from_secs(600))
.http1_only();
let token = std::env::var("KITTYCAD_API_TOKEN").expect("KITTYCAD_API_TOKEN not set");
let mut client = kittycad::Client::new_from_reqwest(token, http_client, ws_client);
if let Ok(addr) = std::env::var("LOCAL_ENGINE_ADDR") {
client.set_base_url(addr);
}
let tokens = crate::token::lexer("This is another code block.\nyes sirrr.\nshow").unwrap();
let parser = crate::parser::Parser::new(tokens);
let program = parser.ast().unwrap();
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
.await
.unwrap();
ctx.run(&program, None).await.unwrap();
ctx.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
crate::executor::SourceRange::default(),
kittycad::types::ModelingCmd::ZoomToFit {
object_ids: Default::default(),
padding: 0.1,
},
)
.await
.unwrap();
let resp = ctx
.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
crate::executor::SourceRange::default(),
kittycad::types::ModelingCmd::TakeSnapshot {
format: kittycad::types::ImageFormat::Png,
},
)
.await
.unwrap();
let output_file =
std::env::temp_dir().join(format!("kcl_output_{}.png", uuid::Uuid::new_v4()));
if let kittycad::types::OkWebSocketResponseData::Modeling {
modeling_response: kittycad::types::OkModelingCmdResponse::TakeSnapshot { data },
} = &resp
{
std::fs::write(&output_file, &data.contents.0).unwrap();
} else {
panic!("Unexpected response from engine: {:?}", resp);
}
let actual = image::io::Reader::open(output_file)
.unwrap()
.decode()
.unwrap();
let code = "This is another code block.\nyes sirrr.\nshow";
let result =
crate::test_server::execute_and_snapshot(code, crate::settings::types::UnitLength::Mm)
.await
.unwrap();
twenty_twenty::assert_image(
&format!("tests/outputs/{}.png", "serial_test_example_show0"),
&actual,
&result,
0.99,
);
}
@ -111,71 +54,14 @@ mod test_examples_show {
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
async fn serial_test_example_show1() {
let user_agent = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
let http_client = reqwest::Client::builder()
.user_agent(user_agent)
.timeout(std::time::Duration::from_secs(600))
.connect_timeout(std::time::Duration::from_secs(60));
let ws_client = reqwest::Client::builder()
.user_agent(user_agent)
.timeout(std::time::Duration::from_secs(600))
.connect_timeout(std::time::Duration::from_secs(60))
.connection_verbose(true)
.tcp_keepalive(std::time::Duration::from_secs(600))
.http1_only();
let token = std::env::var("KITTYCAD_API_TOKEN").expect("KITTYCAD_API_TOKEN not set");
let mut client = kittycad::Client::new_from_reqwest(token, http_client, ws_client);
if let Ok(addr) = std::env::var("LOCAL_ENGINE_ADDR") {
client.set_base_url(addr);
}
let tokens = crate::token::lexer("This is code.\nIt does other shit.\nshow").unwrap();
let parser = crate::parser::Parser::new(tokens);
let program = parser.ast().unwrap();
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
.await
.unwrap();
ctx.run(&program, None).await.unwrap();
ctx.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
crate::executor::SourceRange::default(),
kittycad::types::ModelingCmd::ZoomToFit {
object_ids: Default::default(),
padding: 0.1,
},
)
.await
.unwrap();
let resp = ctx
.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
crate::executor::SourceRange::default(),
kittycad::types::ModelingCmd::TakeSnapshot {
format: kittycad::types::ImageFormat::Png,
},
)
.await
.unwrap();
let output_file =
std::env::temp_dir().join(format!("kcl_output_{}.png", uuid::Uuid::new_v4()));
if let kittycad::types::OkWebSocketResponseData::Modeling {
modeling_response: kittycad::types::OkModelingCmdResponse::TakeSnapshot { data },
} = &resp
{
std::fs::write(&output_file, &data.contents.0).unwrap();
} else {
panic!("Unexpected response from engine: {:?}", resp);
}
let actual = image::io::Reader::open(output_file)
.unwrap()
.decode()
.unwrap();
let code = "This is code.\nIt does other shit.\nshow";
let result =
crate::test_server::execute_and_snapshot(code, crate::settings::types::UnitLength::Mm)
.await
.unwrap();
twenty_twenty::assert_image(
&format!("tests/outputs/{}.png", "serial_test_example_show1"),
&actual,
&result,
0.99,
);
}

View File

@ -21,71 +21,14 @@ mod test_examples_show {
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
async fn serial_test_example_show0() {
let user_agent = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
let http_client = reqwest::Client::builder()
.user_agent(user_agent)
.timeout(std::time::Duration::from_secs(600))
.connect_timeout(std::time::Duration::from_secs(60));
let ws_client = reqwest::Client::builder()
.user_agent(user_agent)
.timeout(std::time::Duration::from_secs(600))
.connect_timeout(std::time::Duration::from_secs(60))
.connection_verbose(true)
.tcp_keepalive(std::time::Duration::from_secs(600))
.http1_only();
let token = std::env::var("KITTYCAD_API_TOKEN").expect("KITTYCAD_API_TOKEN not set");
let mut client = kittycad::Client::new_from_reqwest(token, http_client, ws_client);
if let Ok(addr) = std::env::var("LOCAL_ENGINE_ADDR") {
client.set_base_url(addr);
}
let tokens = crate::token::lexer("This is code.\nIt does other shit.\nshow").unwrap();
let parser = crate::parser::Parser::new(tokens);
let program = parser.ast().unwrap();
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
.await
.unwrap();
ctx.run(&program, None).await.unwrap();
ctx.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
crate::executor::SourceRange::default(),
kittycad::types::ModelingCmd::ZoomToFit {
object_ids: Default::default(),
padding: 0.1,
},
)
.await
.unwrap();
let resp = ctx
.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
crate::executor::SourceRange::default(),
kittycad::types::ModelingCmd::TakeSnapshot {
format: kittycad::types::ImageFormat::Png,
},
)
.await
.unwrap();
let output_file =
std::env::temp_dir().join(format!("kcl_output_{}.png", uuid::Uuid::new_v4()));
if let kittycad::types::OkWebSocketResponseData::Modeling {
modeling_response: kittycad::types::OkModelingCmdResponse::TakeSnapshot { data },
} = &resp
{
std::fs::write(&output_file, &data.contents.0).unwrap();
} else {
panic!("Unexpected response from engine: {:?}", resp);
}
let actual = image::io::Reader::open(output_file)
.unwrap()
.decode()
.unwrap();
let code = "This is code.\nIt does other shit.\nshow";
let result =
crate::test_server::execute_and_snapshot(code, crate::settings::types::UnitLength::Mm)
.await
.unwrap();
twenty_twenty::assert_image(
&format!("tests/outputs/{}.png", "serial_test_example_show0"),
&actual,
&result,
0.99,
);
}

View File

@ -22,72 +22,14 @@ mod test_examples_my_func {
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
async fn serial_test_example_my_func0() {
let user_agent = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
let http_client = reqwest::Client::builder()
.user_agent(user_agent)
.timeout(std::time::Duration::from_secs(600))
.connect_timeout(std::time::Duration::from_secs(60));
let ws_client = reqwest::Client::builder()
.user_agent(user_agent)
.timeout(std::time::Duration::from_secs(600))
.connect_timeout(std::time::Duration::from_secs(60))
.connection_verbose(true)
.tcp_keepalive(std::time::Duration::from_secs(600))
.http1_only();
let token = std::env::var("KITTYCAD_API_TOKEN").expect("KITTYCAD_API_TOKEN not set");
let mut client = kittycad::Client::new_from_reqwest(token, http_client, ws_client);
if let Ok(addr) = std::env::var("LOCAL_ENGINE_ADDR") {
client.set_base_url(addr);
}
let tokens =
crate::token::lexer("This is another code block.\nyes sirrr.\nmyFunc").unwrap();
let parser = crate::parser::Parser::new(tokens);
let program = parser.ast().unwrap();
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
.await
.unwrap();
ctx.run(&program, None).await.unwrap();
ctx.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
crate::executor::SourceRange::default(),
kittycad::types::ModelingCmd::ZoomToFit {
object_ids: Default::default(),
padding: 0.1,
},
)
.await
.unwrap();
let resp = ctx
.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
crate::executor::SourceRange::default(),
kittycad::types::ModelingCmd::TakeSnapshot {
format: kittycad::types::ImageFormat::Png,
},
)
.await
.unwrap();
let output_file =
std::env::temp_dir().join(format!("kcl_output_{}.png", uuid::Uuid::new_v4()));
if let kittycad::types::OkWebSocketResponseData::Modeling {
modeling_response: kittycad::types::OkModelingCmdResponse::TakeSnapshot { data },
} = &resp
{
std::fs::write(&output_file, &data.contents.0).unwrap();
} else {
panic!("Unexpected response from engine: {:?}", resp);
}
let actual = image::io::Reader::open(output_file)
.unwrap()
.decode()
.unwrap();
let code = "This is another code block.\nyes sirrr.\nmyFunc";
let result =
crate::test_server::execute_and_snapshot(code, crate::settings::types::UnitLength::Mm)
.await
.unwrap();
twenty_twenty::assert_image(
&format!("tests/outputs/{}.png", "serial_test_example_my_func0"),
&actual,
&result,
0.99,
);
}
@ -113,71 +55,14 @@ mod test_examples_my_func {
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
async fn serial_test_example_my_func1() {
let user_agent = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
let http_client = reqwest::Client::builder()
.user_agent(user_agent)
.timeout(std::time::Duration::from_secs(600))
.connect_timeout(std::time::Duration::from_secs(60));
let ws_client = reqwest::Client::builder()
.user_agent(user_agent)
.timeout(std::time::Duration::from_secs(600))
.connect_timeout(std::time::Duration::from_secs(60))
.connection_verbose(true)
.tcp_keepalive(std::time::Duration::from_secs(600))
.http1_only();
let token = std::env::var("KITTYCAD_API_TOKEN").expect("KITTYCAD_API_TOKEN not set");
let mut client = kittycad::Client::new_from_reqwest(token, http_client, ws_client);
if let Ok(addr) = std::env::var("LOCAL_ENGINE_ADDR") {
client.set_base_url(addr);
}
let tokens = crate::token::lexer("This is code.\nIt does other shit.\nmyFunc").unwrap();
let parser = crate::parser::Parser::new(tokens);
let program = parser.ast().unwrap();
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
.await
.unwrap();
ctx.run(&program, None).await.unwrap();
ctx.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
crate::executor::SourceRange::default(),
kittycad::types::ModelingCmd::ZoomToFit {
object_ids: Default::default(),
padding: 0.1,
},
)
.await
.unwrap();
let resp = ctx
.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
crate::executor::SourceRange::default(),
kittycad::types::ModelingCmd::TakeSnapshot {
format: kittycad::types::ImageFormat::Png,
},
)
.await
.unwrap();
let output_file =
std::env::temp_dir().join(format!("kcl_output_{}.png", uuid::Uuid::new_v4()));
if let kittycad::types::OkWebSocketResponseData::Modeling {
modeling_response: kittycad::types::OkModelingCmdResponse::TakeSnapshot { data },
} = &resp
{
std::fs::write(&output_file, &data.contents.0).unwrap();
} else {
panic!("Unexpected response from engine: {:?}", resp);
}
let actual = image::io::Reader::open(output_file)
.unwrap()
.decode()
.unwrap();
let code = "This is code.\nIt does other shit.\nmyFunc";
let result =
crate::test_server::execute_and_snapshot(code, crate::settings::types::UnitLength::Mm)
.await
.unwrap();
twenty_twenty::assert_image(
&format!("tests/outputs/{}.png", "serial_test_example_my_func1"),
&actual,
&result,
0.99,
);
}

View File

@ -22,72 +22,14 @@ mod test_examples_line_to {
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
async fn serial_test_example_line_to0() {
let user_agent = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
let http_client = reqwest::Client::builder()
.user_agent(user_agent)
.timeout(std::time::Duration::from_secs(600))
.connect_timeout(std::time::Duration::from_secs(60));
let ws_client = reqwest::Client::builder()
.user_agent(user_agent)
.timeout(std::time::Duration::from_secs(600))
.connect_timeout(std::time::Duration::from_secs(60))
.connection_verbose(true)
.tcp_keepalive(std::time::Duration::from_secs(600))
.http1_only();
let token = std::env::var("KITTYCAD_API_TOKEN").expect("KITTYCAD_API_TOKEN not set");
let mut client = kittycad::Client::new_from_reqwest(token, http_client, ws_client);
if let Ok(addr) = std::env::var("LOCAL_ENGINE_ADDR") {
client.set_base_url(addr);
}
let tokens =
crate::token::lexer("This is another code block.\nyes sirrr.\nlineTo").unwrap();
let parser = crate::parser::Parser::new(tokens);
let program = parser.ast().unwrap();
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
.await
.unwrap();
ctx.run(&program, None).await.unwrap();
ctx.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
crate::executor::SourceRange::default(),
kittycad::types::ModelingCmd::ZoomToFit {
object_ids: Default::default(),
padding: 0.1,
},
)
.await
.unwrap();
let resp = ctx
.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
crate::executor::SourceRange::default(),
kittycad::types::ModelingCmd::TakeSnapshot {
format: kittycad::types::ImageFormat::Png,
},
)
.await
.unwrap();
let output_file =
std::env::temp_dir().join(format!("kcl_output_{}.png", uuid::Uuid::new_v4()));
if let kittycad::types::OkWebSocketResponseData::Modeling {
modeling_response: kittycad::types::OkModelingCmdResponse::TakeSnapshot { data },
} = &resp
{
std::fs::write(&output_file, &data.contents.0).unwrap();
} else {
panic!("Unexpected response from engine: {:?}", resp);
}
let actual = image::io::Reader::open(output_file)
.unwrap()
.decode()
.unwrap();
let code = "This is another code block.\nyes sirrr.\nlineTo";
let result =
crate::test_server::execute_and_snapshot(code, crate::settings::types::UnitLength::Mm)
.await
.unwrap();
twenty_twenty::assert_image(
&format!("tests/outputs/{}.png", "serial_test_example_line_to0"),
&actual,
&result,
0.99,
);
}
@ -113,71 +55,14 @@ mod test_examples_line_to {
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
async fn serial_test_example_line_to1() {
let user_agent = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
let http_client = reqwest::Client::builder()
.user_agent(user_agent)
.timeout(std::time::Duration::from_secs(600))
.connect_timeout(std::time::Duration::from_secs(60));
let ws_client = reqwest::Client::builder()
.user_agent(user_agent)
.timeout(std::time::Duration::from_secs(600))
.connect_timeout(std::time::Duration::from_secs(60))
.connection_verbose(true)
.tcp_keepalive(std::time::Duration::from_secs(600))
.http1_only();
let token = std::env::var("KITTYCAD_API_TOKEN").expect("KITTYCAD_API_TOKEN not set");
let mut client = kittycad::Client::new_from_reqwest(token, http_client, ws_client);
if let Ok(addr) = std::env::var("LOCAL_ENGINE_ADDR") {
client.set_base_url(addr);
}
let tokens = crate::token::lexer("This is code.\nIt does other shit.\nlineTo").unwrap();
let parser = crate::parser::Parser::new(tokens);
let program = parser.ast().unwrap();
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
.await
.unwrap();
ctx.run(&program, None).await.unwrap();
ctx.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
crate::executor::SourceRange::default(),
kittycad::types::ModelingCmd::ZoomToFit {
object_ids: Default::default(),
padding: 0.1,
},
)
.await
.unwrap();
let resp = ctx
.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
crate::executor::SourceRange::default(),
kittycad::types::ModelingCmd::TakeSnapshot {
format: kittycad::types::ImageFormat::Png,
},
)
.await
.unwrap();
let output_file =
std::env::temp_dir().join(format!("kcl_output_{}.png", uuid::Uuid::new_v4()));
if let kittycad::types::OkWebSocketResponseData::Modeling {
modeling_response: kittycad::types::OkModelingCmdResponse::TakeSnapshot { data },
} = &resp
{
std::fs::write(&output_file, &data.contents.0).unwrap();
} else {
panic!("Unexpected response from engine: {:?}", resp);
}
let actual = image::io::Reader::open(output_file)
.unwrap()
.decode()
.unwrap();
let code = "This is code.\nIt does other shit.\nlineTo";
let result =
crate::test_server::execute_and_snapshot(code, crate::settings::types::UnitLength::Mm)
.await
.unwrap();
twenty_twenty::assert_image(
&format!("tests/outputs/{}.png", "serial_test_example_line_to1"),
&actual,
&result,
0.99,
);
}

View File

@ -21,71 +21,14 @@ mod test_examples_min {
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
async fn serial_test_example_min0() {
let user_agent = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
let http_client = reqwest::Client::builder()
.user_agent(user_agent)
.timeout(std::time::Duration::from_secs(600))
.connect_timeout(std::time::Duration::from_secs(60));
let ws_client = reqwest::Client::builder()
.user_agent(user_agent)
.timeout(std::time::Duration::from_secs(600))
.connect_timeout(std::time::Duration::from_secs(60))
.connection_verbose(true)
.tcp_keepalive(std::time::Duration::from_secs(600))
.http1_only();
let token = std::env::var("KITTYCAD_API_TOKEN").expect("KITTYCAD_API_TOKEN not set");
let mut client = kittycad::Client::new_from_reqwest(token, http_client, ws_client);
if let Ok(addr) = std::env::var("LOCAL_ENGINE_ADDR") {
client.set_base_url(addr);
}
let tokens = crate::token::lexer("This is another code block.\nyes sirrr.\nmin").unwrap();
let parser = crate::parser::Parser::new(tokens);
let program = parser.ast().unwrap();
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
.await
.unwrap();
ctx.run(&program, None).await.unwrap();
ctx.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
crate::executor::SourceRange::default(),
kittycad::types::ModelingCmd::ZoomToFit {
object_ids: Default::default(),
padding: 0.1,
},
)
.await
.unwrap();
let resp = ctx
.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
crate::executor::SourceRange::default(),
kittycad::types::ModelingCmd::TakeSnapshot {
format: kittycad::types::ImageFormat::Png,
},
)
.await
.unwrap();
let output_file =
std::env::temp_dir().join(format!("kcl_output_{}.png", uuid::Uuid::new_v4()));
if let kittycad::types::OkWebSocketResponseData::Modeling {
modeling_response: kittycad::types::OkModelingCmdResponse::TakeSnapshot { data },
} = &resp
{
std::fs::write(&output_file, &data.contents.0).unwrap();
} else {
panic!("Unexpected response from engine: {:?}", resp);
}
let actual = image::io::Reader::open(output_file)
.unwrap()
.decode()
.unwrap();
let code = "This is another code block.\nyes sirrr.\nmin";
let result =
crate::test_server::execute_and_snapshot(code, crate::settings::types::UnitLength::Mm)
.await
.unwrap();
twenty_twenty::assert_image(
&format!("tests/outputs/{}.png", "serial_test_example_min0"),
&actual,
&result,
0.99,
);
}
@ -111,71 +54,14 @@ mod test_examples_min {
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
async fn serial_test_example_min1() {
let user_agent = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
let http_client = reqwest::Client::builder()
.user_agent(user_agent)
.timeout(std::time::Duration::from_secs(600))
.connect_timeout(std::time::Duration::from_secs(60));
let ws_client = reqwest::Client::builder()
.user_agent(user_agent)
.timeout(std::time::Duration::from_secs(600))
.connect_timeout(std::time::Duration::from_secs(60))
.connection_verbose(true)
.tcp_keepalive(std::time::Duration::from_secs(600))
.http1_only();
let token = std::env::var("KITTYCAD_API_TOKEN").expect("KITTYCAD_API_TOKEN not set");
let mut client = kittycad::Client::new_from_reqwest(token, http_client, ws_client);
if let Ok(addr) = std::env::var("LOCAL_ENGINE_ADDR") {
client.set_base_url(addr);
}
let tokens = crate::token::lexer("This is code.\nIt does other shit.\nmin").unwrap();
let parser = crate::parser::Parser::new(tokens);
let program = parser.ast().unwrap();
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
.await
.unwrap();
ctx.run(&program, None).await.unwrap();
ctx.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
crate::executor::SourceRange::default(),
kittycad::types::ModelingCmd::ZoomToFit {
object_ids: Default::default(),
padding: 0.1,
},
)
.await
.unwrap();
let resp = ctx
.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
crate::executor::SourceRange::default(),
kittycad::types::ModelingCmd::TakeSnapshot {
format: kittycad::types::ImageFormat::Png,
},
)
.await
.unwrap();
let output_file =
std::env::temp_dir().join(format!("kcl_output_{}.png", uuid::Uuid::new_v4()));
if let kittycad::types::OkWebSocketResponseData::Modeling {
modeling_response: kittycad::types::OkModelingCmdResponse::TakeSnapshot { data },
} = &resp
{
std::fs::write(&output_file, &data.contents.0).unwrap();
} else {
panic!("Unexpected response from engine: {:?}", resp);
}
let actual = image::io::Reader::open(output_file)
.unwrap()
.decode()
.unwrap();
let code = "This is code.\nIt does other shit.\nmin";
let result =
crate::test_server::execute_and_snapshot(code, crate::settings::types::UnitLength::Mm)
.await
.unwrap();
twenty_twenty::assert_image(
&format!("tests/outputs/{}.png", "serial_test_example_min1"),
&actual,
&result,
0.99,
);
}

View File

@ -21,71 +21,14 @@ mod test_examples_show {
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
async fn serial_test_example_show0() {
let user_agent = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
let http_client = reqwest::Client::builder()
.user_agent(user_agent)
.timeout(std::time::Duration::from_secs(600))
.connect_timeout(std::time::Duration::from_secs(60));
let ws_client = reqwest::Client::builder()
.user_agent(user_agent)
.timeout(std::time::Duration::from_secs(600))
.connect_timeout(std::time::Duration::from_secs(60))
.connection_verbose(true)
.tcp_keepalive(std::time::Duration::from_secs(600))
.http1_only();
let token = std::env::var("KITTYCAD_API_TOKEN").expect("KITTYCAD_API_TOKEN not set");
let mut client = kittycad::Client::new_from_reqwest(token, http_client, ws_client);
if let Ok(addr) = std::env::var("LOCAL_ENGINE_ADDR") {
client.set_base_url(addr);
}
let tokens = crate::token::lexer("This is code.\nIt does other shit.\nshow").unwrap();
let parser = crate::parser::Parser::new(tokens);
let program = parser.ast().unwrap();
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
.await
.unwrap();
ctx.run(&program, None).await.unwrap();
ctx.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
crate::executor::SourceRange::default(),
kittycad::types::ModelingCmd::ZoomToFit {
object_ids: Default::default(),
padding: 0.1,
},
)
.await
.unwrap();
let resp = ctx
.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
crate::executor::SourceRange::default(),
kittycad::types::ModelingCmd::TakeSnapshot {
format: kittycad::types::ImageFormat::Png,
},
)
.await
.unwrap();
let output_file =
std::env::temp_dir().join(format!("kcl_output_{}.png", uuid::Uuid::new_v4()));
if let kittycad::types::OkWebSocketResponseData::Modeling {
modeling_response: kittycad::types::OkModelingCmdResponse::TakeSnapshot { data },
} = &resp
{
std::fs::write(&output_file, &data.contents.0).unwrap();
} else {
panic!("Unexpected response from engine: {:?}", resp);
}
let actual = image::io::Reader::open(output_file)
.unwrap()
.decode()
.unwrap();
let code = "This is code.\nIt does other shit.\nshow";
let result =
crate::test_server::execute_and_snapshot(code, crate::settings::types::UnitLength::Mm)
.await
.unwrap();
twenty_twenty::assert_image(
&format!("tests/outputs/{}.png", "serial_test_example_show0"),
&actual,
&result,
0.99,
);
}

View File

@ -21,71 +21,14 @@ mod test_examples_import {
#[tokio::test(flavor = "multi_thread", worker_threads = 5)]
async fn serial_test_example_import0() {
let user_agent = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
let http_client = reqwest::Client::builder()
.user_agent(user_agent)
.timeout(std::time::Duration::from_secs(600))
.connect_timeout(std::time::Duration::from_secs(60));
let ws_client = reqwest::Client::builder()
.user_agent(user_agent)
.timeout(std::time::Duration::from_secs(600))
.connect_timeout(std::time::Duration::from_secs(60))
.connection_verbose(true)
.tcp_keepalive(std::time::Duration::from_secs(600))
.http1_only();
let token = std::env::var("KITTYCAD_API_TOKEN").expect("KITTYCAD_API_TOKEN not set");
let mut client = kittycad::Client::new_from_reqwest(token, http_client, ws_client);
if let Ok(addr) = std::env::var("LOCAL_ENGINE_ADDR") {
client.set_base_url(addr);
}
let tokens = crate::token::lexer("This is code.\nIt does other shit.\nimport").unwrap();
let parser = crate::parser::Parser::new(tokens);
let program = parser.ast().unwrap();
let ctx = crate::executor::ExecutorContext::new(&client, Default::default())
.await
.unwrap();
ctx.run(&program, None).await.unwrap();
ctx.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
crate::executor::SourceRange::default(),
kittycad::types::ModelingCmd::ZoomToFit {
object_ids: Default::default(),
padding: 0.1,
},
)
.await
.unwrap();
let resp = ctx
.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
crate::executor::SourceRange::default(),
kittycad::types::ModelingCmd::TakeSnapshot {
format: kittycad::types::ImageFormat::Png,
},
)
.await
.unwrap();
let output_file =
std::env::temp_dir().join(format!("kcl_output_{}.png", uuid::Uuid::new_v4()));
if let kittycad::types::OkWebSocketResponseData::Modeling {
modeling_response: kittycad::types::OkModelingCmdResponse::TakeSnapshot { data },
} = &resp
{
std::fs::write(&output_file, &data.contents.0).unwrap();
} else {
panic!("Unexpected response from engine: {:?}", resp);
}
let actual = image::io::Reader::open(output_file)
.unwrap()
.decode()
.unwrap();
let code = "This is code.\nIt does other shit.\nimport";
let result =
crate::test_server::execute_and_snapshot(code, crate::settings::types::UnitLength::Mm)
.await
.unwrap();
twenty_twenty::assert_image(
&format!("tests/outputs/{}.png", "serial_test_example_import0"),
&actual,
&result,
0.99,
);
}

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