Compare commits

...

33 Commits

Author SHA1 Message Date
777b225066 Cut release v0.21.8 (#2498)
Co-authored-by: Jess Frazelle <jessfraz@users.noreply.github.com>
2024-05-23 18:01:54 -07:00
ae6373e4f5 actually test that we dont exit sketch mode on first escape (#2501)
* actually test that we dont exit sketch mode on first escape

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

* better test

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

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2024-05-24 00:23:15 +00:00
87979b17cf zoom to fit on load (#2201)
* zoom to fit on load

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

* updates

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

* lint

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

* add zoom to fit calls to the correct places

* update comment

* clean up comment

* add snapshot test zoom to git

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

* updates

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

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

* subscribe to camera updates from zoom to fit

* fix types

* partial test fix

* updatges

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

* fix another test

* remove my enhancements

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

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
Co-authored-by: Kurt Hutten Irev-Dev <k.hutten@protonmail.ch>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-05-24 00:05:54 +00:00
4be63e7331 Allow any value to start a pipe expression (#2496)
Relaxes an arbitrary restriction. Previously KCL pipelines couldn't start
with a number, e.g. `2 |> double(%)`. Now they can.
2024-05-23 16:06:30 -07:00
56d930c4f2 Handle export errors with empty scene or KCL errors (#2477)
* Update Cargo.lock

* Handle bad or empty scene export

Log error and send toast to user

* fmt
2024-05-23 16:03:34 -07:00
d48eb0c66c add plugin for saving scoped permissions will help with dialog behvior (#2497)
* build with persisted scope

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

* more scopes

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

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2024-05-23 14:23:14 -07:00
a69d7d03d0 Check the winnow ParseError before indexing (#2491)
* Check the winnow ParseError before indexing

From the winnow docs at[1]

> The location in ParseError::input where parsing failed
>
> Note: This is an offset, not an index, and may point to the end of input
> (input.len()) on eof errors.

This will bounds check the index before slicing into the `input` vec,
and return an EOF erorr rather than an unknown token error.

[1]: https://docs.rs/winnow/latest/winnow/error/struct.ParseError.html#method.offset

I have a hunch somewhere something is mixing up bytes and chars (more
specifically, a codepoint or grapheme), which is causing bounds to go
past the end of the list since something is talking byte indexes and
the other is dealing with char/codepoint indexes.

For now this is going to fix the crash, but the EOF error may be masking
an actual bad token error in some cases? Our code looks right, so I'm
not quite sure what is going on in the winnow internals here.

Signed-off-by: Paul R. Tagliamonte <paul@kittycad.io>
2024-05-23 16:27:54 -04:00
max
00a8273173 Add Client-Side Gizmo (#2354)
* draft #2279

Add client side gizmo #2279, work in progress

* draft #2279

unreliableSubscriptions

* draft #2279

nice Gizmo

* blue ring

give the canvas a round shape and a border, wrapping rounded div element around the canvas

* Refactor Gizmo Component

Extracted reusable constants
Modularized the code
Simplified the useEffect logic
Added TypeScript type annotations
Improved overall code structure and readability

* remove old gizmo

* fmt

* styling and relocation

 Add className "pointer-events-none" to gizmo wrapper div (for now to prevent context menu)
 Make LowerRightControls container element have these classNames: flex flex-col items-end gap-3
 Move gizmo into LowerRightControls.tsx as the first child of the section element
 Remove the fixed styling from the gizmo div so it flows in flexbox

* fmt

* fix camera up problem

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

* up tweak

* Revert "up tweak"

This reverts commit a53a0ef240.

* test tweak

* tweak test

---------

Co-authored-by: Kurt Hutten Irev-Dev <k.hutten@protonmail.ch>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Frank Noirot <frank@kittycad.io>
2024-05-24 06:02:25 +10:00
51868f892b Deduplicate executor code (#2494)
There are many places in the executor codebase which evaluate an AST expression and produce a KCL memory item. They could be deduplicated and put into one central location.

Fixes <https://github.com/KittyCAD/modeling-app/issues/1931>.
2024-05-23 14:50:22 -05:00
8e9286a747 Fix the fuzzer to work with the changed API (#2493)
Simplify the fuzzer a bit

This is the same code, but we'll offload the string parsing to the fuzz
lib, and we can inline the `if Ok(v)`

Signed-off-by: Paul R. Tagliamonte <paul@kittycad.io>
2024-05-23 09:12:40 -07:00
023ed1a687 Home page touch-ups (#2135)
* Save part images when navigating home

* Load part images in project cards if available

* Polish home page

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

* Merge branch 'main' into franknoirot/project-images

* Mostly restored link + form functionality

* Working cards with images

* Comment out project image stuff

* Little style tweaks

* Remove unused imports

* More minor styling tweaks

* Merge branch 'main' into franknoirot/project-images

* Was using the wrong imported `Project` type

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

* Revert any docs changes

* Revert wasm-lib divergences

* Move ProjectCard into its component folder

* Remove unused hook useSaveVideoFrame

* Remove "hideOnLevel" config from theme setting

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-05-23 11:47:02 -04:00
5b7d707b26 playwright test and framework for network stuff (#2480)
* playwright test and framework for network bullshit

 chrome protocol docs for params you can send

 https://chromedevtools.github.io/devtools-protocol/1-3/Network/#method-emulateNetworkConditions

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

* fmt

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

* skip on webkit

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

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2024-05-23 02:20:40 -07:00
5b95194aa7 fix test hotkey (#2490) 2024-05-23 15:44:19 +10:00
6080a99e73 Bump @react-hook/resize-observer from 1.2.6 to 2.0.1 (#2486)
Bumps [@react-hook/resize-observer](https://github.com/jaredLunde/react-hook) from 1.2.6 to 2.0.1.
- [Commits](https://github.com/jaredLunde/react-hook/commits)

---
updated-dependencies:
- dependency-name: "@react-hook/resize-observer"
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-23 05:22:24 +00:00
5106c49e21 bump kittycad (#2481) 2024-05-23 15:09:40 +10:00
25f18845c7 Update point-and-click sketch close code generation to use explicit lines (#2489)
* Modify sketch profile completion to use `profileStart` utilties

* Fix up playwright tests

* Rerun CI
2024-05-23 00:53:15 -04:00
0a7f1a41fc Bump vscode-jsonrpc from 8.2.0 to 8.2.1 (#2484)
Bumps [vscode-jsonrpc](https://github.com/Microsoft/vscode-languageserver-node/tree/HEAD/jsonrpc) from 8.2.0 to 8.2.1.
- [Release notes](https://github.com/Microsoft/vscode-languageserver-node/releases)
- [Commits](https://github.com/Microsoft/vscode-languageserver-node/commits/release/jsonrpc/8.2.1/jsonrpc)

---
updated-dependencies:
- dependency-name: vscode-jsonrpc
  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-05-22 21:31:34 -07:00
1625b58577 Bump @tauri-apps/api from 2.0.0-beta.8 to 2.0.0-beta.12 (#2483)
Bumps [@tauri-apps/api](https://github.com/tauri-apps/tauri) from 2.0.0-beta.8 to 2.0.0-beta.12.
- [Release notes](https://github.com/tauri-apps/tauri/releases)
- [Commits](https://github.com/tauri-apps/tauri/compare/@tauri-apps/api-v2.0.0-beta.8...@tauri-apps/api-v2.0.0-beta.12)

---
updated-dependencies:
- dependency-name: "@tauri-apps/api"
  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-05-22 21:31:21 -07:00
ab6115c4e2 Bump ws from 8.16.0 to 8.17.0 (#2482)
Bumps [ws](https://github.com/websockets/ws) from 8.16.0 to 8.17.0.
- [Release notes](https://github.com/websockets/ws/releases)
- [Commits](https://github.com/websockets/ws/compare/8.16.0...8.17.0)

---
updated-dependencies:
- dependency-name: ws
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-22 21:30:55 -07:00
fe621240c3 use tauri command to run commands (#2475)
* use tauri command to run commands

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

* add capabilities

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

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2024-05-22 17:44:13 -07:00
97faf5ae2b Simplify the pentagon test (#2474)
* plumbus fixes

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

* Simplify the pentagon test

* Fix up triangle png

* Triangle plumbuses now face the camera

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
Co-authored-by: Jess Frazelle <github@jessfraz.com>
2024-05-22 16:50:54 -07:00
e3b9a6e5d8 Port forward to ts-rs 8.1 (currently: git only; waiting for 8.1.1+) (#2443)
Port forward to ts-rs 8.1

We're just waiting on a release that includes a PR that we sent[1] for this
to use the cargo version. For now we'll have to use the git release.

[1]: c5109a00e4
2024-05-22 14:22:07 -04:00
e94b1bc12a Add failing multi-sketch file (#1466)
* Add failing multi-sketch file

* Fix e2e lint

* fmt fml

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

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
Co-authored-by: Jess Frazelle <jessfraz@users.noreply.github.com>
Co-authored-by: Jess Frazelle <github@jessfraz.com>
2024-05-22 10:19:29 -07:00
c0eff5bc14 Cut release v0.21.7 (#2466) 2024-05-22 13:06:07 -04:00
b0f92c2f6d remove printlns from stdlib (#2467)
Signed-off-by: Jess Frazelle <github@jessfraz.com>
2024-05-22 09:43:42 -07:00
718873b3bb updating kcl examples (#2386)
* updating kcl examples

* generate images

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

* add new

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

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
Co-authored-by: Jess Frazelle <jessfraz@users.noreply.github.com>
Co-authored-by: Jess Frazelle <github@jessfraz.com>
2024-05-22 09:15:38 -07:00
9f815eecc1 bump kcl-lib I think my last merge reverted it somehow (#2465) 2024-05-22 15:57:26 +00:00
0384e5e6c6 Add keyboard shortcuts for sketch and modeling tools (#2419)
* Add keyboard shortcuts for sketch and modeling tools

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

* Add a playwright test

* skip linux

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

* fmt fml

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

* Give more generous test timeout for worst case engine runs

* Fix up test mouse clicks after zoom bug fixes

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Jess Frazelle <jessfraz@users.noreply.github.com>
Co-authored-by: Jess Frazelle <github@jessfraz.com>
2024-05-22 11:07:02 -04:00
48ef0885b7 fix xz-plane (#2376)
* fix xz-plane

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

* images

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

* empty

* update docs

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

* fix

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

* updates

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

* update tests

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

* scene infra fixes

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

* images

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

* revert

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

* fix tests

* more test fix

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

* trigger ci

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
Co-authored-by: Kurt Hutten Irev-Dev <k.hutten@protonmail.ch>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-05-21 23:35:33 -07:00
3b2731f924 Bump react and @types/react (#2458) 2024-05-21 23:04:39 -07:00
bf4e04f9f1 Bump @tauri-apps/plugin-os from 2.0.0-beta.2 to 2.0.0-beta.3 (#2456) 2024-05-21 23:03:50 -07:00
24475bbcdf add more rust file tests (#2452)
* addd more rust file tests

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

* updates

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

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2024-05-21 20:39:29 -07:00
bcca736a8d Fix rename project directory (#2451)
* make rust function with lots of tests

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

* pull thru function to tauri and app

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

* one more test;

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

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2024-05-21 19:23:43 -07:00
194 changed files with 3444 additions and 1558 deletions

View File

@ -115,7 +115,7 @@ jobs:
git fetch origin
echo ${{ github.head_ref }}
git checkout ${{ github.head_ref }}
# TODO when safari works on ubuntu remove the os part of the commit message
# TODO when webkit works on ubuntu remove the os part of the commit message
git commit -am "A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)" || true
git push
git push origin ${{ github.head_ref }}
@ -181,7 +181,7 @@ jobs:
- name: build web
run: yarn build:local
- name: Run macos/safari flow
# safari doesn't work on Ubuntu because of the same reason tauri doesn't (webRTC issues)
# webkit doesn't work on Ubuntu because of the same reason tauri doesn't (webRTC issues)
# TODO remove this and the matrix and run all tests on ubuntu when this is fixed
run: yarn playwright test --project="webkit" e2e/playwright/flow-tests.spec.ts
env:

View File

@ -21,7 +21,7 @@ abs(num: number) -> number
```js
const myAngle = -120
const sketch001 = startSketchOn('-XZ')
const sketch001 = startSketchOn('XZ')
|> startProfileAt([0, 0], %)
|> line([8, 0], %)
|> angledLine({ angle: abs(myAngle), length: 5 }, %)

File diff suppressed because one or more lines are too long

View File

@ -15,7 +15,7 @@ angleToMatchLengthX(segment_name: string, to: number, sketch_group: SketchGroup)
### Examples
```js
const sketch001 = startSketchOn('-XZ')
const sketch001 = startSketchOn('XZ')
|> startProfileAt([0, 0], %)
|> line([2, 5], %, 'seg01')
|> angledLineToX([

View File

@ -15,7 +15,7 @@ angleToMatchLengthY(segment_name: string, to: number, sketch_group: SketchGroup)
### Examples
```js
const sketch001 = startSketchOn('-XZ')
const sketch001 = startSketchOn('XZ')
|> startProfileAt([0, 0], %)
|> line([1, 2], %, 'seg01')
|> angledLine({

View File

@ -15,7 +15,7 @@ angledLine(data: AngledLineData, sketch_group: SketchGroup, tag?: String) -> Ske
### Examples
```js
const exampleSketch = startSketchOn('-XZ')
const exampleSketch = startSketchOn('XZ')
|> startProfileAt([0, 0], %)
|> yLineTo(15, %)
|> angledLine({ angle: 30, length: 15 }, %)

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -15,7 +15,7 @@ angledLineThatIntersects(data: AngledLineThatIntersectsData, sketch_group: Sketc
### Examples
```js
const exampleSketch = startSketchOn('-XZ')
const exampleSketch = startSketchOn('XZ')
|> startProfileAt([0, 0], %)
|> lineTo([5, 10], %)
|> lineTo([-10, 10], %, "lineToIntersect")

View File

@ -15,7 +15,7 @@ angledLineToX(data: AngledLineToData, sketch_group: SketchGroup, tag?: String) -
### Examples
```js
const exampleSketch = startSketchOn('-XZ')
const exampleSketch = startSketchOn('XZ')
|> startProfileAt([0, 0], %)
|> angledLineToX({ angle: 30, to: 10 }, %)
|> line([0, 10], %)

View File

@ -15,7 +15,7 @@ angledLineToY(data: AngledLineToData, sketch_group: SketchGroup, tag?: String) -
### Examples
```js
const exampleSketch = startSketchOn('-XZ')
const exampleSketch = startSketchOn('XZ')
|> startProfileAt([0, 0], %)
|> angledLineToY({ angle: 60, to: 20 }, %)
|> line([-20, 0], %)

View File

@ -15,7 +15,7 @@ arc(data: ArcData, sketch_group: SketchGroup, tag?: String) -> SketchGroup
### Examples
```js
const exampleSketch = startSketchOn('-XZ')
const exampleSketch = startSketchOn('XZ')
|> startProfileAt([0, 0], %)
|> line([10, 0], %)
|> arc({

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -15,7 +15,7 @@ bezierCurve(data: BezierData, sketch_group: SketchGroup, tag?: String) -> Sketch
### Examples
```js
const exampleSketch = startSketchOn('-XZ')
const exampleSketch = startSketchOn('XZ')
|> startProfileAt([0, 0], %)
|> line([0, 10], %)
|> bezierCurve({

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -15,7 +15,7 @@ lastSegX(sketch_group: SketchGroup) -> number
### Examples
```js
const exampleSketch = startSketchOn("-XZ")
const exampleSketch = startSketchOn("XZ")
|> startProfileAt([0, 0], %)
|> line([5, 0], %)
|> line([20, 5], %)

View File

@ -15,7 +15,7 @@ lastSegY(sketch_group: SketchGroup) -> number
### Examples
```js
const exampleSketch = startSketchOn("-XZ")
const exampleSketch = startSketchOn("XZ")
|> startProfileAt([0, 0], %)
|> line([5, 0], %)
|> line([20, 5], %)

File diff suppressed because one or more lines are too long

View File

@ -15,7 +15,7 @@ lineTo(to: [number], sketch_group: SketchGroup, tag?: String) -> SketchGroup
### Examples
```js
const exampleSketch = startSketchOn("-XZ")
const exampleSketch = startSketchOn("XZ")
|> startProfileAt([0, 0], %)
|> lineTo([10, 0], %)
|> lineTo([0, 10], %)

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -15,7 +15,7 @@ patternCircular2d(data: CircularPattern2dData, sketch_group: SketchGroup) -> [Sk
### Examples
```js
const exampleSketch = startSketchOn('-XZ')
const exampleSketch = startSketchOn('XZ')
|> startProfileAt([.5, 25], %)
|> line([0, 5], %)
|> line([-1, 0], %)

View File

@ -15,7 +15,7 @@ patternCircular3d(data: CircularPattern3dData, extrude_group: ExtrudeGroup) -> [
### Examples
```js
const exampleSketch = startSketchOn('-XZ')
const exampleSketch = startSketchOn('XZ')
|> circle([0, 0], 1, %)
const example = extrude(-5, exampleSketch)

View File

@ -15,7 +15,7 @@ patternLinear2d(data: LinearPattern2dData, sketch_group_set: SketchGroupSet) ->
### Examples
```js
const exampleSketch = startSketchOn('-XZ')
const exampleSketch = startSketchOn('XZ')
|> circle([0, 0], 1, %)
|> patternLinear2d({
axis: [1, 0],

View File

@ -15,7 +15,7 @@ patternLinear3d(data: LinearPattern3dData, extrude_group: ExtrudeGroup) -> [Extr
### Examples
```js
const exampleSketch = startSketchOn('-XZ')
const exampleSketch = startSketchOn('XZ')
|> startProfileAt([0, 0], %)
|> line([0, 2], %)
|> line([3, 1], %)

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -15,7 +15,7 @@ segAng(segment_name: string, sketch_group: SketchGroup) -> number
### Examples
```js
const exampleSketch = startSketchOn('-XZ')
const exampleSketch = startSketchOn('XZ')
|> startProfileAt([0, 0], %)
|> line([10, 0], %)
|> line([5, 10], %, 'seg01')

View File

@ -15,7 +15,7 @@ segEndX(segment_name: string, sketch_group: SketchGroup) -> number
### Examples
```js
const exampleSketch = startSketchOn('-XZ')
const exampleSketch = startSketchOn('XZ')
|> startProfileAt([0, 0], %)
|> line([20, 0], %, "thing")
|> line([0, 5], %)

View File

@ -15,7 +15,7 @@ segEndY(segment_name: string, sketch_group: SketchGroup) -> number
### Examples
```js
const exampleSketch = startSketchOn('-XZ')
const exampleSketch = startSketchOn('XZ')
|> startProfileAt([0, 0], %)
|> line([20, 0], %)
|> line([0, 3], %, "thing")

View File

@ -15,7 +15,7 @@ segLen(segment_name: string, sketch_group: SketchGroup) -> number
### Examples
```js
const exampleSketch = startSketchOn("-XZ")
const exampleSketch = startSketchOn("XZ")
|> startProfileAt([0, 0], %)
|> angledLine({ angle: 60, length: 10 }, %, "thing")
|> tangentialArc({ offset: -120, radius: 5 }, %)

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -29,7 +29,7 @@
"unpublished": false,
"deprecated": false,
"examples": [
"const myAngle = -120\n\nconst sketch001 = startSketchOn('-XZ')\n |> startProfileAt([0, 0], %)\n |> line([8, 0], %)\n |> angledLine({ angle: abs(myAngle), length: 5 }, %)\n |> line([-5, 0], %)\n |> angledLine({ angle: myAngle, length: 5 }, %)\n |> close(%)\n\nconst baseExtrusion = extrude(5, sketch001)"
"const myAngle = -120\n\nconst sketch001 = startSketchOn('XZ')\n |> startProfileAt([0, 0], %)\n |> line([8, 0], %)\n |> angledLine({ angle: abs(myAngle), length: 5 }, %)\n |> line([-5, 0], %)\n |> angledLine({ angle: myAngle, length: 5 }, %)\n |> close(%)\n\nconst baseExtrusion = extrude(5, sketch001)"
]
},
{
@ -62,7 +62,7 @@
"unpublished": false,
"deprecated": false,
"examples": [
"const myVar = acos(0.5)"
"const sketch001 = startSketchOn('XZ')\n |> startProfileAt([0, 0], %)\n |> angledLine({\n angle: toDegrees(acos(0.5)),\n length: 10\n }, %)\n |> line([5, 0], %)\n |> lineTo([12, 0], %)\n |> close(%)\n\nconst extrude001 = extrude(5, sketch001)"
]
},
{
@ -1068,7 +1068,7 @@
"unpublished": false,
"deprecated": false,
"examples": [
"const sketch001 = startSketchOn('-XZ')\n |> startProfileAt([0, 0], %)\n |> line([2, 5], %, 'seg01')\n |> angledLineToX([\n -angleToMatchLengthX('seg01', 7, %),\n 10\n ], %)\n |> close(%)\n\nconst extrusion = extrude(5, sketch001)"
"const sketch001 = startSketchOn('XZ')\n |> startProfileAt([0, 0], %)\n |> line([2, 5], %, 'seg01')\n |> angledLineToX([\n -angleToMatchLengthX('seg01', 7, %),\n 10\n ], %)\n |> close(%)\n\nconst extrusion = extrude(5, sketch001)"
]
},
{
@ -2074,7 +2074,7 @@
"unpublished": false,
"deprecated": false,
"examples": [
"const sketch001 = startSketchOn('-XZ')\n |> startProfileAt([0, 0], %)\n |> line([1, 2], %, 'seg01')\n |> angledLine({\n angle: angleToMatchLengthY('seg01', 15, %),\n length: 5\n }, %)\n |> yLineTo(0, %)\n |> close(%)\n\nconst extrusion = extrude(5, sketch001)"
"const sketch001 = startSketchOn('XZ')\n |> startProfileAt([0, 0], %)\n |> line([1, 2], %, 'seg01')\n |> angledLine({\n angle: angleToMatchLengthY('seg01', 15, %),\n length: 5\n }, %)\n |> yLineTo(0, %)\n |> close(%)\n\nconst extrusion = extrude(5, sketch001)"
]
},
{
@ -4070,7 +4070,7 @@
"unpublished": false,
"deprecated": false,
"examples": [
"const exampleSketch = startSketchOn('-XZ')\n |> startProfileAt([0, 0], %)\n |> yLineTo(15, %)\n |> angledLine({ angle: 30, length: 15 }, %)\n |> line([8, -10], %)\n |> yLineTo(0, %)\n |> close(%)\n\nconst example = extrude(10, exampleSketch)"
"const exampleSketch = startSketchOn('XZ')\n |> startProfileAt([0, 0], %)\n |> yLineTo(15, %)\n |> angledLine({ angle: 30, length: 15 }, %)\n |> line([8, -10], %)\n |> yLineTo(0, %)\n |> close(%)\n\nconst example = extrude(10, exampleSketch)"
]
},
{
@ -10048,7 +10048,7 @@
"unpublished": false,
"deprecated": false,
"examples": [
"const exampleSketch = startSketchOn('-XZ')\n |> startProfileAt([0, 0], %)\n |> lineTo([5, 10], %)\n |> lineTo([-10, 10], %, \"lineToIntersect\")\n |> lineTo([0, 20], %)\n |> angledLineThatIntersects({\n angle: 80,\n intersectTag: 'lineToIntersect',\n offset: 10\n }, %)\n |> close(%)\n\nconst example = extrude(10, exampleSketch)"
"const exampleSketch = startSketchOn('XZ')\n |> startProfileAt([0, 0], %)\n |> lineTo([5, 10], %)\n |> lineTo([-10, 10], %, \"lineToIntersect\")\n |> lineTo([0, 20], %)\n |> angledLineThatIntersects({\n angle: 80,\n intersectTag: 'lineToIntersect',\n offset: 10\n }, %)\n |> close(%)\n\nconst example = extrude(10, exampleSketch)"
]
},
{
@ -12029,7 +12029,7 @@
"unpublished": false,
"deprecated": false,
"examples": [
"const exampleSketch = startSketchOn('-XZ')\n |> startProfileAt([0, 0], %)\n |> angledLineToX({ angle: 30, to: 10 }, %)\n |> line([0, 10], %)\n |> line([-10, 0], %)\n |> close(%)\n\nconst example = extrude(10, exampleSketch)"
"const exampleSketch = startSketchOn('XZ')\n |> startProfileAt([0, 0], %)\n |> angledLineToX({ angle: 30, to: 10 }, %)\n |> line([0, 10], %)\n |> line([-10, 0], %)\n |> close(%)\n\nconst example = extrude(10, exampleSketch)"
]
},
{
@ -14010,7 +14010,7 @@
"unpublished": false,
"deprecated": false,
"examples": [
"const exampleSketch = startSketchOn('-XZ')\n |> startProfileAt([0, 0], %)\n |> angledLineToY({ angle: 60, to: 20 }, %)\n |> line([-20, 0], %)\n |> angledLineToY({ angle: 70, to: 10 }, %)\n |> close(%)\n\nconst example = extrude(10, exampleSketch)"
"const exampleSketch = startSketchOn('XZ')\n |> startProfileAt([0, 0], %)\n |> angledLineToY({ angle: 60, to: 20 }, %)\n |> line([-20, 0], %)\n |> angledLineToY({ angle: 70, to: 10 }, %)\n |> close(%)\n\nconst example = extrude(10, exampleSketch)"
]
},
{
@ -16038,7 +16038,7 @@
"unpublished": false,
"deprecated": false,
"examples": [
"const exampleSketch = startSketchOn('-XZ')\n |> startProfileAt([0, 0], %)\n |> line([10, 0], %)\n |> arc({\n angle_start: 0,\n angle_end: 280,\n radius: 16\n }, %)\n |> close(%)"
"const exampleSketch = startSketchOn('XZ')\n |> startProfileAt([0, 0], %)\n |> line([10, 0], %)\n |> arc({\n angle_start: 0,\n angle_end: 280,\n radius: 16\n }, %)\n |> close(%)"
]
},
{
@ -16071,7 +16071,7 @@
"unpublished": false,
"deprecated": false,
"examples": [
"const myVar = asin(0.5)"
"const sketch001 = startSketchOn('XZ')\n |> startProfileAt([0, 0], %)\n |> angledLine({\n angle: toDegrees(asin(0.5)),\n length: 20\n }, %)\n |> yLineTo(0, %)\n |> close(%)\n\nconst extrude001 = extrude(5, sketch001)"
]
},
{
@ -16104,7 +16104,7 @@
"unpublished": false,
"deprecated": false,
"examples": [
"const myVar = atan(1.0)"
"const sketch001 = startSketchOn('XZ')\n |> startProfileAt([0, 0], %)\n |> angledLine({\n angle: toDegrees(atan(1.25)),\n length: 20\n }, %)\n |> yLineTo(0, %)\n |> close(%)\n\nconst extrude001 = extrude(5, sketch001)"
]
},
{
@ -18106,7 +18106,7 @@
"unpublished": false,
"deprecated": false,
"examples": [
"const exampleSketch = startSketchOn('-XZ')\n |> startProfileAt([0, 0], %)\n |> line([0, 10], %)\n |> bezierCurve({\n to: [10, 10],\n control1: [5, 0],\n control2: [5, 10]\n }, %)\n |> lineTo([10, 0], %)\n |> close(%)\n\nconst example = extrude(10, exampleSketch)"
"const exampleSketch = startSketchOn('XZ')\n |> startProfileAt([0, 0], %)\n |> line([0, 10], %)\n |> bezierCurve({\n to: [10, 10],\n control1: [5, 0],\n control2: [5, 10]\n }, %)\n |> lineTo([10, 0], %)\n |> close(%)\n\nconst example = extrude(10, exampleSketch)"
]
},
{
@ -18139,7 +18139,7 @@
"unpublished": false,
"deprecated": false,
"examples": [
"const myVar = ceil(4.5)"
"const sketch001 = startSketchOn('XZ')\n |> startProfileAt([0, 0], %)\n |> lineTo([12, 10], %)\n |> line([ceil(7.02986), 0], %)\n |> yLineTo(0, %)\n |> close(%)\n\nconst extrude001 = extrude(5, sketch001)"
]
},
{
@ -20424,7 +20424,8 @@
"unpublished": false,
"deprecated": false,
"examples": [
"const exampleSketch = startSketchOn(\"-XZ\")\n |> circle([0, 0], 10, %)\n\nconst example = extrude(5, exampleSketch)"
"const exampleSketch = startSketchOn(\"-XZ\")\n |> circle([0, 0], 10, %)\n\nconst example = extrude(5, exampleSketch)",
"const exampleSketch = startSketchOn(\"XZ\")\n |> startProfileAt([-15, 0], %)\n |> line([30, 0], %)\n |> line([0, 30], %)\n |> line([-30, 0], %)\n |> close(%)\n |> hole(circle([0, 15], 5, %), %)\n\nconst example = extrude(5, exampleSketch)"
]
},
{
@ -22414,7 +22415,7 @@
"unpublished": false,
"deprecated": false,
"examples": [
"const anotherVar = cos(2 * pi())"
"const exampleSketch = startSketchOn(\"XZ\")\n |> startProfileAt([0, 0], %)\n |> angledLine({\n angle: 30,\n length: 3 / cos(toRadians(30))\n }, %)\n |> yLineTo(0, %)\n |> close(%)\n\nconst example = extrude(5, exampleSketch)"
]
},
{
@ -22437,7 +22438,7 @@
"unpublished": false,
"deprecated": false,
"examples": [
"const myVar = e()"
"const exampleSketch = startSketchOn(\"XZ\")\n |> startProfileAt([0, 0], %)\n |> angledLine({ angle: 30, length: 2 * e() ^ 2 }, %)\n |> yLineTo(0, %)\n |> close(%)\n\nconst example = extrude(10, exampleSketch)"
]
},
{
@ -25953,8 +25954,8 @@
"unpublished": false,
"deprecated": false,
"examples": [
"const example = startSketchOn('-XZ')\n |> startProfileAt([0, 0], %)\n |> line([10, 0], %)\n |> arc({\n angle_end: 0,\n angle_start: 120,\n radius: 5\n }, %)\n |> line([5, 0], %)\n |> line([0, 10], %)\n |> bezierCurve({\n control1: [-10, 0],\n control2: [2, 10],\n to: [-5, 10]\n }, %)\n |> line([-5, -2], %)\n |> close(%)\n |> extrude(10, %)",
"const exampleSketch = startSketchOn('-XZ')\n |> startProfileAt([-10, 0], %)\n |> arc({\n angle_end: -60,\n angle_start: 120,\n radius: 5\n }, %)\n |> line([10, 0], %)\n |> line([5, 0], %)\n |> bezierCurve({\n control1: [-3, 0],\n control2: [2, 10],\n to: [-5, 10]\n }, %)\n |> line([-4, 10], %)\n |> line([-5, -2], %)\n |> close(%)\n\nconst example = extrude(10, exampleSketch)"
"const example = startSketchOn('XZ')\n |> startProfileAt([0, 0], %)\n |> line([10, 0], %)\n |> arc({\n angle_end: 0,\n angle_start: 120,\n radius: 5\n }, %)\n |> line([5, 0], %)\n |> line([0, 10], %)\n |> bezierCurve({\n control1: [-10, 0],\n control2: [2, 10],\n to: [-5, 10]\n }, %)\n |> line([-5, -2], %)\n |> close(%)\n |> extrude(10, %)",
"const exampleSketch = startSketchOn('XZ')\n |> startProfileAt([-10, 0], %)\n |> arc({\n angle_end: -60,\n angle_start: 120,\n radius: 5\n }, %)\n |> line([10, 0], %)\n |> line([5, 0], %)\n |> bezierCurve({\n control1: [-3, 0],\n control2: [2, 10],\n to: [-5, 10]\n }, %)\n |> line([-4, 10], %)\n |> line([-5, -2], %)\n |> close(%)\n\nconst example = extrude(10, exampleSketch)"
]
},
{
@ -27550,7 +27551,7 @@
"unpublished": false,
"deprecated": false,
"examples": [
"const myVar = floor(4.5)"
"const sketch001 = startSketchOn('XZ')\n |> startProfileAt([0, 0], %)\n |> lineTo([12, 10], %)\n |> line([floor(7.02986), 0], %)\n |> yLineTo(0, %)\n |> close(%)\n\nconst extrude001 = extrude(5, sketch001)"
]
},
{
@ -28336,7 +28337,7 @@
"unpublished": false,
"deprecated": false,
"examples": [
"const box = startSketchOn('XZ')\n |> startProfileAt([0, 0], %)\n |> line([0, 10], %, 'revolveAxis')\n |> line([10, 0], %)\n |> line([0, -10], %)\n |> close(%)\n |> extrude(10, %)\n\nconst revolution = startSketchOn('XZ')\n |> startProfileAt([-10, 0], %)\n |> line([0, 10], %)\n |> line([2, 0], %)\n |> line([0, -10], %)\n |> close(%)\n |> revolve({\n axis: getEdge('revolveAxis', box),\n angle: 90\n }, %)"
"const box = startSketchOn('XZ')\n |> startProfileAt([0, 0], %)\n |> line([0, 10], %, 'revolveAxis')\n |> line([10, 0], %)\n |> line([0, -10], %)\n |> close(%)\n |> extrude(10, %)\n\nconst revolution = startSketchOn(box, \"revolveAxis\")\n |> startProfileAt([5, 10], %)\n |> line([0, 10], %)\n |> line([2, 0], %)\n |> line([0, -10], %)\n |> close(%)\n |> revolve({\n axis: getEdge('revolveAxis', box),\n angle: 90\n }, %)"
]
},
{
@ -36161,7 +36162,7 @@
"deprecated": false,
"examples": [
"const exampleSketch = startSketchOn('XY')\n |> startProfileAt([0, 0], %)\n |> line([0, 5], %)\n |> line([5, 0], %)\n |> line([0, -5], %)\n |> close(%)\n |> hole(circle([1, 1], .25, %), %)\n |> hole(circle([1, 4], .25, %), %)\n\nconst example = extrude(1, exampleSketch)",
"fn squareHoleSketch = () => {\n const squareSketch = startSketchOn('-XZ')\n |> startProfileAt([-1, -1], %)\n |> line([2, 0], %)\n |> line([0, 2], %)\n |> line([-2, 0], %)\n |> close(%)\n return squareSketch\n}\n\nconst exampleSketch = startSketchOn('-XZ')\n |> circle([0, 0], 3, %)\n |> hole(squareHoleSketch(), %)"
"fn squareHoleSketch = () => {\n const squareSketch = startSketchOn('-XZ')\n |> startProfileAt([-1, -1], %)\n |> line([2, 0], %)\n |> line([0, 2], %)\n |> line([-2, 0], %)\n |> close(%)\n return squareSketch\n}\n\nconst exampleSketch = startSketchOn('-XZ')\n |> circle([0, 0], 3, %)\n |> hole(squareHoleSketch(), %)\nconst example = extrude(1, exampleSketch)"
]
},
{
@ -37807,7 +37808,7 @@
"unpublished": false,
"deprecated": false,
"examples": [
"const exampleSketch = startSketchOn(\"-XZ\")\n |> startProfileAt([0, 0], %)\n |> line([5, 0], %)\n |> line([20, 5], %)\n |> line([0, lastSegX(%)], %)\n |> line([-15, 0], %)\n |> close(%)\n\nconst example = extrude(5, exampleSketch)"
"const exampleSketch = startSketchOn(\"XZ\")\n |> startProfileAt([0, 0], %)\n |> line([5, 0], %)\n |> line([20, 5], %)\n |> line([0, lastSegX(%)], %)\n |> line([-15, 0], %)\n |> close(%)\n\nconst example = extrude(5, exampleSketch)"
]
},
{
@ -38796,7 +38797,7 @@
"unpublished": false,
"deprecated": false,
"examples": [
"const exampleSketch = startSketchOn(\"-XZ\")\n |> startProfileAt([0, 0], %)\n |> line([5, 0], %)\n |> line([20, 5], %)\n |> line([0, lastSegY(%)], %)\n |> line([-15, 0], %)\n |> close(%)\n\nconst example = extrude(5, exampleSketch)"
"const exampleSketch = startSketchOn(\"XZ\")\n |> startProfileAt([0, 0], %)\n |> line([5, 0], %)\n |> line([20, 5], %)\n |> line([0, lastSegY(%)], %)\n |> line([-15, 0], %)\n |> close(%)\n\nconst example = extrude(5, exampleSketch)"
]
},
{
@ -40892,7 +40893,8 @@
"unpublished": false,
"deprecated": false,
"examples": [
"const exampleSketch = startSketchOn(\"-XZ\")\n |> startProfileAt([0, 0], %)\n |> line([10, 0], %)\n |> line([0, 10], %)\n |> line([-10, 0], %)\n |> close(%)\n\nconst example = extrude(5, exampleSketch)"
"const exampleSketch = startSketchOn(\"XZ\")\n |> startProfileAt([0, 0], %)\n |> line([25, 15], %)\n |> line([5, -6], %)\n |> line([-10, -10], %)\n |> close(%)\n\nconst example = extrude(5, exampleSketch)",
"const exampleSketch = startSketchOn(\"XZ\")\n |> startProfileAt([0, 0], %)\n |> line([10, 0], %)\n |> line([0, 10], %)\n |> line([-10, 0], %)\n |> close(%)\n\nconst example = extrude(5, exampleSketch)"
]
},
{
@ -42862,7 +42864,7 @@
"unpublished": false,
"deprecated": false,
"examples": [
"const exampleSketch = startSketchOn(\"-XZ\")\n |> startProfileAt([0, 0], %)\n |> lineTo([10, 0], %)\n |> lineTo([0, 10], %)\n |> lineTo([-10, 0], %)\n |> close(%)\n\nconst example = extrude(5, exampleSketch)"
"const exampleSketch = startSketchOn(\"XZ\")\n |> startProfileAt([0, 0], %)\n |> lineTo([10, 0], %)\n |> lineTo([0, 10], %)\n |> lineTo([-10, 0], %)\n |> close(%)\n\nconst example = extrude(5, exampleSketch)"
]
},
{
@ -42895,7 +42897,7 @@
"unpublished": false,
"deprecated": false,
"examples": [
"const myVar = ln(4)"
"const exampleSketch = startSketchOn(\"XZ\")\n |> startProfileAt([0, 0], %)\n |> line([ln(100), 15], %)\n |> line([5, -6], %)\n |> line([-10, -10], %)\n |> close(%)\n\nconst example = extrude(5, exampleSketch)"
]
},
{
@ -42937,7 +42939,7 @@
"unpublished": false,
"deprecated": false,
"examples": [
"const myVar = log(4, 2)"
"const exampleSketch = startSketchOn(\"XZ\")\n |> startProfileAt([0, 0], %)\n |> line([log(100, 5), 0], %)\n |> line([5, 8], %)\n |> line([-10, 0], %)\n |> close(%)\n\nconst example = extrude(5, exampleSketch)"
]
},
{
@ -42970,7 +42972,7 @@
"unpublished": false,
"deprecated": false,
"examples": [
"const myVar = log10(4)"
"const exampleSketch = startSketchOn(\"XZ\")\n |> startProfileAt([0, 0], %)\n |> line([log10(100), 0], %)\n |> line([5, 8], %)\n |> line([-10, 0], %)\n |> close(%)\n\nconst example = extrude(5, exampleSketch)"
]
},
{
@ -43003,7 +43005,7 @@
"unpublished": false,
"deprecated": false,
"examples": [
"const myVar = log2(4)"
"const exampleSketch = startSketchOn(\"XZ\")\n |> startProfileAt([0, 0], %)\n |> line([log2(100), 0], %)\n |> line([5, 8], %)\n |> line([-10, 0], %)\n |> close(%)\n\nconst example = extrude(5, exampleSketch)"
]
},
{
@ -43039,7 +43041,7 @@
"unpublished": false,
"deprecated": false,
"examples": [
"const myVar = max(4, 5, 6)"
"const exampleSketch = startSketchOn(\"XZ\")\n |> startProfileAt([0, 0], %)\n |> angledLine({\n angle: 70,\n length: max(15, 31, 4, 13, 22)\n }, %)\n |> line([20, 0], %)\n |> close(%)\n\nconst example = extrude(5, exampleSketch)"
]
},
{
@ -43075,7 +43077,7 @@
"unpublished": false,
"deprecated": false,
"examples": [
"const myVar = min(4, 5, 6)"
"const exampleSketch = startSketchOn(\"XZ\")\n |> startProfileAt([0, 0], %)\n |> angledLine({\n angle: 70,\n length: min(15, 31, 4, 13, 22)\n }, %)\n |> line([20, 0], %)\n |> close(%)\n\nconst example = extrude(5, exampleSketch)"
]
},
{
@ -45067,7 +45069,7 @@
"unpublished": false,
"deprecated": false,
"examples": [
"const exampleSketch = startSketchOn('-XZ')\n |> startProfileAt([.5, 25], %)\n |> line([0, 5], %)\n |> line([-1, 0], %)\n |> line([0, -5], %)\n |> close(%)\n |> patternCircular2d({\n center: [0, 0],\n repetitions: 12,\n arcDegrees: 360,\n rotateDuplicates: true\n }, %)\n\nconst example = extrude(1, exampleSketch)"
"const exampleSketch = startSketchOn('XZ')\n |> startProfileAt([.5, 25], %)\n |> line([0, 5], %)\n |> line([-1, 0], %)\n |> line([0, -5], %)\n |> close(%)\n |> patternCircular2d({\n center: [0, 0],\n repetitions: 12,\n arcDegrees: 360,\n rotateDuplicates: true\n }, %)\n\nconst example = extrude(1, exampleSketch)"
]
},
{
@ -46648,7 +46650,7 @@
"unpublished": false,
"deprecated": false,
"examples": [
"const exampleSketch = startSketchOn('-XZ')\n |> circle([0, 0], 1, %)\n\nconst example = extrude(-5, exampleSketch)\n |> patternCircular3d({\n axis: [1, -1, 0],\n center: [10, -20, 0],\n repetitions: 10,\n arcDegrees: 360,\n rotateDuplicates: true\n }, %)"
"const exampleSketch = startSketchOn('XZ')\n |> circle([0, 0], 1, %)\n\nconst example = extrude(-5, exampleSketch)\n |> patternCircular3d({\n axis: [1, -1, 0],\n center: [10, -20, 0],\n repetitions: 10,\n arcDegrees: 360,\n rotateDuplicates: true\n }, %)"
]
},
{
@ -49626,7 +49628,7 @@
"unpublished": false,
"deprecated": false,
"examples": [
"const exampleSketch = startSketchOn('-XZ')\n |> circle([0, 0], 1, %)\n |> patternLinear2d({\n axis: [1, 0],\n repetitions: 6,\n distance: 4\n }, %)\n\nconst example = extrude(1, exampleSketch)"
"const exampleSketch = startSketchOn('XZ')\n |> circle([0, 0], 1, %)\n |> patternLinear2d({\n axis: [1, 0],\n repetitions: 6,\n distance: 4\n }, %)\n\nconst example = extrude(1, exampleSketch)"
]
},
{
@ -51191,7 +51193,7 @@
"unpublished": false,
"deprecated": false,
"examples": [
"const exampleSketch = startSketchOn('-XZ')\n |> startProfileAt([0, 0], %)\n |> line([0, 2], %)\n |> line([3, 1], %)\n |> line([0, -4], %)\n |> close(%)\n\nconst example = extrude(1, exampleSketch)\n |> patternLinear3d({\n axis: [1, 0, 1],\n repetitions: 6,\n distance: 6\n }, %)"
"const exampleSketch = startSketchOn('XZ')\n |> startProfileAt([0, 0], %)\n |> line([0, 2], %)\n |> line([3, 1], %)\n |> line([0, -4], %)\n |> close(%)\n\nconst example = extrude(1, exampleSketch)\n |> patternLinear3d({\n axis: [1, 0, 1],\n repetitions: 6,\n distance: 6\n }, %)"
]
},
{
@ -51214,7 +51216,7 @@
"unpublished": false,
"deprecated": false,
"examples": [
"const myVar = pi() * 3.0"
"const circumference = 70\n\nconst exampleSketch = startSketchOn(\"XZ\")\n |> circle([0, 0], circumference / (2 * pi()), %)\n\nconst example = extrude(5, exampleSketch)"
]
},
{
@ -51256,7 +51258,7 @@
"unpublished": false,
"deprecated": false,
"examples": [
"const myVar = pow(4, 2)"
"const exampleSketch = startSketchOn(\"XZ\")\n |> startProfileAt([0, 0], %)\n |> angledLine({ angle: 50, length: pow(5, 2) }, %)\n |> yLineTo(0, %)\n |> close(%)\n\nconst example = extrude(5, exampleSketch)"
]
},
{
@ -57090,7 +57092,7 @@
"unpublished": false,
"deprecated": false,
"examples": [
"const exampleSketch = startSketchOn('-XZ')\n |> startProfileAt([0, 0], %)\n |> line([10, 0], %)\n |> line([5, 10], %, 'seg01')\n |> line([-10, 0], %)\n |> angledLine([segAng('seg01', %), 10], %)\n |> line([-10, 0], %)\n |> angledLine([segAng('seg01', %), -15], %)\n |> close(%)\n\nconst example = extrude(4, exampleSketch)"
"const exampleSketch = startSketchOn('XZ')\n |> startProfileAt([0, 0], %)\n |> line([10, 0], %)\n |> line([5, 10], %, 'seg01')\n |> line([-10, 0], %)\n |> angledLine([segAng('seg01', %), 10], %)\n |> line([-10, 0], %)\n |> angledLine([segAng('seg01', %), -15], %)\n |> close(%)\n\nconst example = extrude(4, exampleSketch)"
]
},
{
@ -58087,7 +58089,7 @@
"unpublished": false,
"deprecated": false,
"examples": [
"const exampleSketch = startSketchOn('-XZ')\n |> startProfileAt([0, 0], %)\n |> line([20, 0], %, \"thing\")\n |> line([0, 5], %)\n |> line([segEndX(\"thing\", %), 0], %)\n |> line([-20, 10], %)\n |> close(%)\n\nconst example = extrude(5, exampleSketch)"
"const exampleSketch = startSketchOn('XZ')\n |> startProfileAt([0, 0], %)\n |> line([20, 0], %, \"thing\")\n |> line([0, 5], %)\n |> line([segEndX(\"thing\", %), 0], %)\n |> line([-20, 10], %)\n |> close(%)\n\nconst example = extrude(5, exampleSketch)"
]
},
{
@ -59084,7 +59086,7 @@
"unpublished": false,
"deprecated": false,
"examples": [
"const exampleSketch = startSketchOn('-XZ')\n |> startProfileAt([0, 0], %)\n |> line([20, 0], %)\n |> line([0, 3], %, \"thing\")\n |> line([-10, 0], %)\n |> line([0, segEndY(\"thing\", %)], %)\n |> line([-10, 0], %)\n |> close(%)\n\nconst example = extrude(5, exampleSketch)"
"const exampleSketch = startSketchOn('XZ')\n |> startProfileAt([0, 0], %)\n |> line([20, 0], %)\n |> line([0, 3], %, \"thing\")\n |> line([-10, 0], %)\n |> line([0, segEndY(\"thing\", %)], %)\n |> line([-10, 0], %)\n |> close(%)\n\nconst example = extrude(5, exampleSketch)"
]
},
{
@ -60081,7 +60083,7 @@
"unpublished": false,
"deprecated": false,
"examples": [
"const exampleSketch = startSketchOn(\"-XZ\")\n |> startProfileAt([0, 0], %)\n |> angledLine({ angle: 60, length: 10 }, %, \"thing\")\n |> tangentialArc({ offset: -120, radius: 5 }, %)\n |> angledLine({\n angle: -60,\n length: segLen(\"thing\", %)\n }, %)\n |> close(%)\n\nconst example = extrude(5, exampleSketch)"
"const exampleSketch = startSketchOn(\"XZ\")\n |> startProfileAt([0, 0], %)\n |> angledLine({ angle: 60, length: 10 }, %, \"thing\")\n |> tangentialArc({ offset: -120, radius: 5 }, %)\n |> angledLine({\n angle: -60,\n length: segLen(\"thing\", %)\n }, %)\n |> close(%)\n\nconst example = extrude(5, exampleSketch)"
]
},
{
@ -60114,7 +60116,7 @@
"unpublished": false,
"deprecated": false,
"examples": [
"const myVar = sin(2 * pi())"
"const exampleSketch = startSketchOn(\"XZ\")\n |> startProfileAt([0, 0], %)\n |> angledLine({\n angle: 50,\n length: 15 / sin(toDegrees(135))\n }, %)\n |> yLineTo(0, %)\n |> close(%)\n\nconst example = extrude(5, exampleSketch)"
]
},
{
@ -60147,7 +60149,7 @@
"unpublished": false,
"deprecated": false,
"examples": [
"const myVar = sqrt(4)"
"const exampleSketch = startSketchOn(\"XZ\")\n |> startProfileAt([0, 0], %)\n |> angledLine({ angle: 50, length: sqrt(2500) }, %)\n |> yLineTo(0, %)\n |> close(%)\n\nconst example = extrude(5, exampleSketch)"
]
},
{
@ -61456,7 +61458,7 @@
"unpublished": false,
"deprecated": false,
"examples": [
"const exampleSketch = startSketchOn('-XZ')\n |> startProfileAt([0, 0], %)\n |> line([10, 0], %)\n |> line([0, 10], %)\n |> line([-10, 0], %)\n |> close(%)\n\nconst example = extrude(5, exampleSketch)",
"const exampleSketch = startSketchOn('XZ')\n |> startProfileAt([0, 0], %)\n |> line([10, 0], %)\n |> line([0, 10], %)\n |> line([-10, 0], %)\n |> close(%)\n\nconst example = extrude(5, exampleSketch)",
"const exampleSketch = startSketchOn('-XZ')\n |> startProfileAt([10, 10], %)\n |> line([10, 0], %)\n |> line([0, 10], %)\n |> line([-10, 0], %)\n |> close(%)\n\nconst example = extrude(5, exampleSketch)",
"const exampleSketch = startSketchOn('-XZ')\n |> startProfileAt([-10, 23], %)\n |> line([10, 0], %)\n |> line([0, 10], %)\n |> line([-10, 0], %)\n |> close(%)\n\nconst example = extrude(5, exampleSketch)"
]
@ -63762,7 +63764,7 @@
"unpublished": false,
"deprecated": false,
"examples": [
"const myVar = tan(2 * pi())"
"const exampleSketch = startSketchOn(\"XZ\")\n |> startProfileAt([0, 0], %)\n |> angledLine({ angle: 50, length: 50 * tan(1 / 2) }, %)\n |> yLineTo(0, %)\n |> close(%)\n\nconst example = extrude(5, exampleSketch)"
]
},
{
@ -65757,7 +65759,7 @@
"unpublished": false,
"deprecated": false,
"examples": [
"const exampleSketch = startSketchOn('-XZ')\n |> startProfileAt([0, 0], %)\n |> angledLine({ angle: 60, length: 10 }, %)\n |> tangentialArc({ radius: 10, offset: -120 }, %)\n |> angledLine({ angle: -60, length: 10 }, %)\n |> close(%)\n\nconst example = extrude(10, exampleSketch)"
"const exampleSketch = startSketchOn('XZ')\n |> startProfileAt([0, 0], %)\n |> angledLine({ angle: 60, length: 10 }, %)\n |> tangentialArc({ radius: 10, offset: -120 }, %)\n |> angledLine({ angle: -60, length: 10 }, %)\n |> close(%)\n\nconst example = extrude(10, exampleSketch)"
]
},
{
@ -67727,7 +67729,7 @@
"unpublished": false,
"deprecated": false,
"examples": [
"const exampleSketch = startSketchOn('-XZ')\n |> startProfileAt([0, 0], %)\n |> angledLine({ angle: 60, length: 10 }, %)\n |> tangentialArcTo([15, 15], %)\n |> line([10, -15], %)\n |> close(%)\n\nconst example = extrude(10, exampleSketch)"
"const exampleSketch = startSketchOn('XZ')\n |> startProfileAt([0, 0], %)\n |> angledLine({ angle: 60, length: 10 }, %)\n |> tangentialArcTo([15, 15], %)\n |> line([10, -15], %)\n |> close(%)\n\nconst example = extrude(10, exampleSketch)"
]
},
{
@ -67750,7 +67752,7 @@
"unpublished": false,
"deprecated": false,
"examples": [
"const myVar = tau()"
"const exampleSketch = startSketchOn(\"XZ\")\n |> startProfileAt([0, 0], %)\n |> angledLine({ angle: 50, length: 10 * tau() }, %)\n |> yLineTo(0, %)\n |> close(%)\n\nconst example = extrude(5, exampleSketch)"
]
},
{
@ -67783,7 +67785,7 @@
"unpublished": false,
"deprecated": false,
"examples": [
"const myVar = toDegrees(2 * pi())"
"const exampleSketch = startSketchOn(\"XZ\")\n |> startProfileAt([0, 0], %)\n |> angledLine({\n angle: 50,\n length: 70 * cos(toDegrees(pi() / 4))\n }, %)\n |> yLineTo(0, %)\n |> close(%)\n\nconst example = extrude(5, exampleSketch)"
]
},
{
@ -67816,7 +67818,7 @@
"unpublished": false,
"deprecated": false,
"examples": [
"const myVar = toRadians(180)"
"const exampleSketch = startSketchOn(\"XZ\")\n |> startProfileAt([0, 0], %)\n |> angledLine({\n angle: 50,\n length: 70 * cos(toRadians(45))\n }, %)\n |> yLineTo(0, %)\n |> close(%)\n\nconst example = extrude(5, exampleSketch)"
]
},
{
@ -69781,7 +69783,7 @@
"unpublished": false,
"deprecated": false,
"examples": [
"const exampleSketch = startSketchOn('-XZ')\n |> startProfileAt([0, 0], %)\n |> xLine(15, %)\n |> angledLine({ angle: 80, length: 15 }, %)\n |> line([8, -10], %)\n |> xLine(10, %)\n |> angledLine({ angle: 120, length: 30 }, %)\n |> xLine(-15, %)\n |> close(%)\n\nconst example = extrude(10, exampleSketch)"
"const exampleSketch = startSketchOn('XZ')\n |> startProfileAt([0, 0], %)\n |> xLine(15, %)\n |> angledLine({ angle: 80, length: 15 }, %)\n |> line([8, -10], %)\n |> xLine(10, %)\n |> angledLine({ angle: 120, length: 30 }, %)\n |> xLine(-15, %)\n |> close(%)\n\nconst example = extrude(10, exampleSketch)"
]
},
{
@ -71746,7 +71748,7 @@
"unpublished": false,
"deprecated": false,
"examples": [
"const exampleSketch = startSketchOn('-XZ')\n |> startProfileAt([0, 0], %)\n |> xLineTo(15, %)\n |> angledLine({ angle: 80, length: 15 }, %)\n |> line([8, -10], %)\n |> xLineTo(40, %)\n |> angledLine({ angle: 135, length: 30 }, %)\n |> xLineTo(10, %)\n |> close(%)\n\nconst example = extrude(10, exampleSketch)"
"const exampleSketch = startSketchOn('XZ')\n |> startProfileAt([0, 0], %)\n |> xLineTo(15, %)\n |> angledLine({ angle: 80, length: 15 }, %)\n |> line([8, -10], %)\n |> xLineTo(40, %)\n |> angledLine({ angle: 135, length: 30 }, %)\n |> xLineTo(10, %)\n |> close(%)\n\nconst example = extrude(10, exampleSketch)"
]
},
{
@ -73711,7 +73713,7 @@
"unpublished": false,
"deprecated": false,
"examples": [
"const exampleSketch = startSketchOn('-XZ')\n |> startProfileAt([0, 0], %)\n |> yLine(15, %)\n |> angledLine({ angle: 30, length: 15 }, %)\n |> line([8, -10], %)\n |> yLine(-5, %)\n |> close(%)\n\nconst example = extrude(10, exampleSketch)"
"const exampleSketch = startSketchOn('XZ')\n |> startProfileAt([0, 0], %)\n |> yLine(15, %)\n |> angledLine({ angle: 30, length: 15 }, %)\n |> line([8, -10], %)\n |> yLine(-5, %)\n |> close(%)\n\nconst example = extrude(10, exampleSketch)"
]
},
{
@ -75676,7 +75678,7 @@
"unpublished": false,
"deprecated": false,
"examples": [
"startSketchOn('XZ')\n |> startProfileAt([0, 0], %)\n |> yLineTo(10, %, \"edge1\")\n |> line([10, 10], %)\n |> close(%, \"edge2\")\n |> extrude(10, %)\n |> fillet({ radius: 2, tags: [\"edge2\"] }, %)"
"const exampleSketch = startSketchOn(\"XZ\")\n |> startProfileAt([0, 0], %)\n |> angledLine({ angle: 50, length: 45 }, %)\n |> yLineTo(0, %)\n |> close(%)\n\nconst example = extrude(5, exampleSketch)"
]
}
]

File diff suppressed because one or more lines are too long

View File

@ -15,7 +15,7 @@ tangentialArc(data: TangentialArcData, sketch_group: SketchGroup, tag?: String)
### Examples
```js
const exampleSketch = startSketchOn('-XZ')
const exampleSketch = startSketchOn('XZ')
|> startProfileAt([0, 0], %)
|> angledLine({ angle: 60, length: 10 }, %)
|> tangentialArc({ radius: 10, offset: -120 }, %)

View File

@ -15,7 +15,7 @@ tangentialArcTo(to: [number], sketch_group: SketchGroup, tag?: String) -> Sketch
### Examples
```js
const exampleSketch = startSketchOn('-XZ')
const exampleSketch = startSketchOn('XZ')
|> startProfileAt([0, 0], %)
|> angledLine({ angle: 60, length: 10 }, %)
|> tangentialArcTo([15, 15], %)

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -15,7 +15,7 @@ xLine(length: number, sketch_group: SketchGroup, tag?: String) -> SketchGroup
### Examples
```js
const exampleSketch = startSketchOn('-XZ')
const exampleSketch = startSketchOn('XZ')
|> startProfileAt([0, 0], %)
|> xLine(15, %)
|> angledLine({ angle: 80, length: 15 }, %)

View File

@ -15,7 +15,7 @@ xLineTo(to: number, sketch_group: SketchGroup, tag?: String) -> SketchGroup
### Examples
```js
const exampleSketch = startSketchOn('-XZ')
const exampleSketch = startSketchOn('XZ')
|> startProfileAt([0, 0], %)
|> xLineTo(15, %)
|> angledLine({ angle: 80, length: 15 }, %)

View File

@ -15,7 +15,7 @@ yLine(length: number, sketch_group: SketchGroup, tag?: String) -> SketchGroup
### Examples
```js
const exampleSketch = startSketchOn('-XZ')
const exampleSketch = startSketchOn('XZ')
|> startProfileAt([0, 0], %)
|> yLine(15, %)
|> angledLine({ angle: 30, length: 15 }, %)

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 224 KiB

After

Width:  |  Height:  |  Size: 249 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 224 KiB

After

Width:  |  Height:  |  Size: 249 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 224 KiB

After

Width:  |  Height:  |  Size: 249 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 165 KiB

After

Width:  |  Height:  |  Size: 171 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 165 KiB

After

Width:  |  Height:  |  Size: 171 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 165 KiB

After

Width:  |  Height:  |  Size: 171 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 165 KiB

After

Width:  |  Height:  |  Size: 171 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 224 KiB

After

Width:  |  Height:  |  Size: 249 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 165 KiB

After

Width:  |  Height:  |  Size: 171 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 165 KiB

After

Width:  |  Height:  |  Size: 171 KiB

File diff suppressed because it is too large Load Diff

View File

@ -44,7 +44,7 @@ test.setTimeout(60_000)
test('exports of each format should work', async ({ page, context }) => {
// FYI this test doesn't work with only engine running locally
// And you will need to have the KittyCAD CLI installed
const u = getUtils(page)
const u = await getUtils(page)
await context.addInitScript(async () => {
;(window as any).playwrightSkipFilePicker = true
localStorage.setItem(
@ -369,7 +369,7 @@ const extrudeDefaultPlane = async (context: any, page: any, plane: string) => {
localStorage.setItem('persistCode', code)
})
const u = getUtils(page)
const u = await getUtils(page)
await page.setViewportSize({ width: 1200, height: 500 })
await page.goto('/')
await u.waitForAuthSkipAppStart()
@ -424,7 +424,7 @@ test.describe('extrude on default planes should be stable', () => {
})
test('Draft segments should look right', async ({ page, context }) => {
const u = getUtils(page)
const u = await getUtils(page)
await page.setViewportSize({ width: 1200, height: 500 })
const PUR = 400 / 37.5 //pixeltoUnitRatio
await page.goto('/')
@ -447,7 +447,7 @@ test('Draft segments should look right', async ({ page, context }) => {
await page.mouse.click(700, 200)
await expect(page.locator('.cm-content')).toHaveText(
`const part001 = startSketchOn('-XZ')`
`const part001 = startSketchOn('XZ')`
)
await page.waitForTimeout(300) // TODO detect animation ending, or disable animation
@ -455,7 +455,7 @@ test('Draft segments should look right', async ({ page, context }) => {
const startXPx = 600
await page.mouse.click(startXPx + PUR * 10, 500 - PUR * 10)
await expect(page.locator('.cm-content'))
.toHaveText(`const part001 = startSketchOn('-XZ')
.toHaveText(`const part001 = startSketchOn('XZ')
|> startProfileAt([9.06, -12.22], %)`)
await page.waitForTimeout(100)
@ -469,7 +469,7 @@ test('Draft segments should look right', async ({ page, context }) => {
await page.waitForTimeout(100)
await expect(page.locator('.cm-content'))
.toHaveText(`const part001 = startSketchOn('-XZ')
.toHaveText(`const part001 = startSketchOn('XZ')
|> startProfileAt([9.06, -12.22], %)
|> line([9.14, 0], %)`)
@ -483,7 +483,7 @@ test('Draft segments should look right', async ({ page, context }) => {
})
test('Draft rectangles should look right', async ({ page, context }) => {
const u = getUtils(page)
const u = await getUtils(page)
await page.setViewportSize({ width: 1200, height: 500 })
const PUR = 400 / 37.5 //pixeltoUnitRatio
await page.goto('/')
@ -506,7 +506,7 @@ test('Draft rectangles should look right', async ({ page, context }) => {
await page.mouse.click(700, 200)
await expect(page.locator('.cm-content')).toHaveText(
`const part001 = startSketchOn('-XZ')`
`const part001 = startSketchOn('XZ')`
)
await page.waitForTimeout(500) // TODO detect animation ending, or disable animation
@ -530,7 +530,7 @@ test('Draft rectangles should look right', async ({ page, context }) => {
test.describe('Client side scene scale should match engine scale', () => {
test('Inch scale', async ({ page }) => {
const u = getUtils(page)
const u = await getUtils(page)
await page.setViewportSize({ width: 1200, height: 500 })
const PUR = 400 / 37.5 //pixeltoUnitRatio
await page.goto('/')
@ -555,7 +555,7 @@ test.describe('Client side scene scale should match engine scale', () => {
await page.mouse.click(700, 200)
await expect(page.locator('.cm-content')).toHaveText(
`const part001 = startSketchOn('-XZ')`
`const part001 = startSketchOn('XZ')`
)
await page.waitForTimeout(300) // TODO detect animation ending, or disable animation
@ -563,7 +563,7 @@ test.describe('Client side scene scale should match engine scale', () => {
const startXPx = 600
await page.mouse.click(startXPx + PUR * 10, 500 - PUR * 10)
await expect(page.locator('.cm-content'))
.toHaveText(`const part001 = startSketchOn('-XZ')
.toHaveText(`const part001 = startSketchOn('XZ')
|> startProfileAt([9.06, -12.22], %)`)
await page.waitForTimeout(100)
@ -573,7 +573,7 @@ test.describe('Client side scene scale should match engine scale', () => {
await page.waitForTimeout(100)
await expect(page.locator('.cm-content'))
.toHaveText(`const part001 = startSketchOn('-XZ')
.toHaveText(`const part001 = startSketchOn('XZ')
|> startProfileAt([9.06, -12.22], %)
|> line([9.14, 0], %)`)
@ -583,7 +583,7 @@ test.describe('Client side scene scale should match engine scale', () => {
await page.mouse.click(startXPx + PUR * 30, 500 - PUR * 20)
await expect(page.locator('.cm-content'))
.toHaveText(`const part001 = startSketchOn('-XZ')
.toHaveText(`const part001 = startSketchOn('XZ')
|> startProfileAt([9.06, -12.22], %)
|> line([9.14, 0], %)
|> tangentialArcTo([27.34, -3.08], %)`)
@ -633,7 +633,7 @@ test.describe('Client side scene scale should match engine scale', () => {
}),
}
)
const u = getUtils(page)
const u = await getUtils(page)
await page.setViewportSize({ width: 1200, height: 500 })
const PUR = 400 / 37.5 //pixeltoUnitRatio
await page.goto('/')
@ -658,7 +658,7 @@ test.describe('Client side scene scale should match engine scale', () => {
await page.mouse.click(700, 200)
await expect(page.locator('.cm-content')).toHaveText(
`const part001 = startSketchOn('-XZ')`
`const part001 = startSketchOn('XZ')`
)
await page.waitForTimeout(300) // TODO detect animation ending, or disable animation
@ -666,7 +666,7 @@ test.describe('Client side scene scale should match engine scale', () => {
const startXPx = 600
await page.mouse.click(startXPx + PUR * 10, 500 - PUR * 10)
await expect(page.locator('.cm-content'))
.toHaveText(`const part001 = startSketchOn('-XZ')
.toHaveText(`const part001 = startSketchOn('XZ')
|> startProfileAt([230.03, -310.32], %)`)
await page.waitForTimeout(100)
@ -676,7 +676,7 @@ test.describe('Client side scene scale should match engine scale', () => {
await page.waitForTimeout(100)
await expect(page.locator('.cm-content'))
.toHaveText(`const part001 = startSketchOn('-XZ')
.toHaveText(`const part001 = startSketchOn('XZ')
|> startProfileAt([230.03, -310.32], %)
|> line([232.2, 0], %)`)
@ -686,7 +686,7 @@ test.describe('Client side scene scale should match engine scale', () => {
await page.mouse.click(startXPx + PUR * 30, 500 - PUR * 20)
await expect(page.locator('.cm-content'))
.toHaveText(`const part001 = startSketchOn('-XZ')
.toHaveText(`const part001 = startSketchOn('XZ')
|> startProfileAt([230.03, -310.32], %)
|> line([232.2, 0], %)
|> tangentialArcTo([694.43, -78.12], %)`)
@ -719,7 +719,7 @@ test.describe('Client side scene scale should match engine scale', () => {
})
test('Sketch on face with none z-up', async ({ page, context }) => {
const u = getUtils(page)
const u = await getUtils(page)
await context.addInitScript(async (KCL_DEFAULT_LENGTH) => {
localStorage.setItem(
'persistCode',
@ -773,3 +773,76 @@ const part002 = startSketchOn(part001, 'seg01')
maxDiffPixels: 100,
})
})
test('Zoom to fit on load - solid 2d', async ({ page, context }) => {
const u = await getUtils(page)
await context.addInitScript(async () => {
localStorage.setItem(
'persistCode',
`const part001 = startSketchOn('XY')
|> startProfileAt([-10, -10], %)
|> line([20, 0], %)
|> line([0, 20], %)
|> line([-20, 0], %)
|> close(%)
`
)
}, KCL_DEFAULT_LENGTH)
await page.setViewportSize({ width: 1200, height: 500 })
await page.goto('/')
await u.waitForAuthSkipAppStart()
await u.openDebugPanel()
// wait for execution done
await expect(
page.locator('[data-message-type="execution-done"]')
).toHaveCount(2)
await u.closeDebugPanel()
// Wait for the second extrusion to appear
// TODO: Find a way to truly know that the objects have finished
// rendering, because an execution-done message is not sufficient.
await page.waitForTimeout(1000)
await expect(page).toHaveScreenshot({
maxDiffPixels: 100,
})
})
test('Zoom to fit on load - solid 3d', async ({ page, context }) => {
const u = await getUtils(page)
await context.addInitScript(async () => {
localStorage.setItem(
'persistCode',
`const part001 = startSketchOn('XY')
|> startProfileAt([-10, -10], %)
|> line([20, 0], %)
|> line([0, 20], %)
|> line([-20, 0], %)
|> close(%)
|> extrude(10, %)
`
)
}, KCL_DEFAULT_LENGTH)
await page.setViewportSize({ width: 1200, height: 500 })
await page.goto('/')
await u.waitForAuthSkipAppStart()
await u.openDebugPanel()
// wait for execution done
await expect(
page.locator('[data-message-type="execution-done"]')
).toHaveCount(2)
await u.closeDebugPanel()
// Wait for the second extrusion to appear
// TODO: Find a way to truly know that the objects have finished
// rendering, because an execution-done message is not sufficient.
await page.waitForTimeout(1000)
await expect(page).toHaveScreenshot({
maxDiffPixels: 100,
})
})

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 42 KiB

View File

@ -1,8 +1,9 @@
import { expect, Page } from '@playwright/test'
import { test, expect, Page } from '@playwright/test'
import { EngineCommand } from '../../src/lang/std/engineConnection'
import fsp from 'fs/promises'
import pixelMatch from 'pixelmatch'
import { PNG } from 'pngjs'
import { Protocol } from 'playwright-core/types/protocol'
async function waitForPageLoad(page: Page) {
// wait for 'Loading stream...' spinner
@ -93,7 +94,12 @@ async function waitForCmdReceive(page: Page, commandType: string) {
.waitFor()
}
export function getUtils(page: Page) {
export async function getUtils(page: Page) {
const cdpSession =
process.platform === 'darwin'
? null
: await page.context().newCDPSession(page)
return {
waitForAuthSkipAppStart: () => waitForPageLoad(page),
removeCurrentCode: () => removeCurrentCode(page),
@ -180,6 +186,17 @@ export function getUtils(page: Page) {
}
}, 50)
}),
emulateNetworkConditions: async (
networkOptions: Protocol.Network.emulateNetworkConditionsParameters
) => {
// Skip on non-Chromium browsers, since we need to use the CDP.
test.skip(
cdpSession === null,
'Network emulation is only supported in Chromium'
)
cdpSession?.send('Network.emulateNetworkConditions', networkOptions)
},
}
}

View File

@ -1,6 +1,6 @@
{
"name": "untitled-app",
"version": "0.21.6",
"version": "0.21.8",
"private": true,
"dependencies": {
"@codemirror/autocomplete": "^6.16.0",
@ -10,16 +10,16 @@
"@fortawesome/react-fontawesome": "^0.2.0",
"@headlessui/react": "^1.7.19",
"@headlessui/tailwindcss": "^0.2.0",
"@kittycad/lib": "^0.0.60",
"@kittycad/lib": "^0.0.63",
"@lezer/javascript": "^1.4.9",
"@open-rpc/client-js": "^1.8.1",
"@react-hook/resize-observer": "^1.2.6",
"@react-hook/resize-observer": "^2.0.1",
"@replit/codemirror-interact": "^6.3.1",
"@tauri-apps/api": "2.0.0-beta.8",
"@tauri-apps/api": "2.0.0-beta.12",
"@tauri-apps/plugin-dialog": "^2.0.0-beta.2",
"@tauri-apps/plugin-fs": "^2.0.0-beta.3",
"@tauri-apps/plugin-http": "^2.0.0-beta.2",
"@tauri-apps/plugin-os": "^2.0.0-beta.2",
"@tauri-apps/plugin-os": "^2.0.0-beta.3",
"@tauri-apps/plugin-process": "^2.0.0-beta.2",
"@tauri-apps/plugin-shell": "^2.0.0-beta.2",
"@tauri-apps/plugin-updater": "^2.0.0-beta.3",
@ -29,7 +29,7 @@
"@ts-stack/markdown": "^1.5.0",
"@tweenjs/tween.js": "^23.1.1",
"@types/node": "^18.19.31",
"@types/react": "^18.2.77",
"@types/react": "^18.3.2",
"@types/react-dom": "^18.2.25",
"@uiw/react-codemirror": "^4.21.25",
"@xstate/inspect": "^0.8.0",
@ -45,7 +45,7 @@
"jszip": "^3.10.1",
"node-fetch": "^3.3.2",
"re-resizable": "^6.9.11",
"react": "^18.2.0",
"react": "^18.3.1",
"react-dom": "^18.2.0",
"react-hot-toast": "^2.4.1",
"react-hotkeys-hook": "^4.5.0",
@ -61,11 +61,11 @@
"ua-parser-js": "^1.0.37",
"uuid": "^9.0.1",
"vitest": "^1.6.0",
"vscode-jsonrpc": "^8.1.0",
"vscode-jsonrpc": "^8.2.1",
"vscode-languageserver-protocol": "^3.17.5",
"wasm-pack": "^0.12.1",
"web-vitals": "^3.5.2",
"ws": "^8.16.0",
"ws": "^8.17.0",
"xstate": "^4.38.2",
"zustand": "^4.5.2"
},

34
src-tauri/Cargo.lock generated
View File

@ -195,6 +195,7 @@ dependencies = [
"tauri-plugin-http",
"tauri-plugin-log",
"tauri-plugin-os",
"tauri-plugin-persisted-scope",
"tauri-plugin-process",
"tauri-plugin-shell",
"tauri-plugin-updater",
@ -2567,7 +2568,7 @@ dependencies = [
[[package]]
name = "kcl-lib"
version = "0.1.55"
version = "0.1.57"
dependencies = [
"anyhow",
"approx",
@ -5370,9 +5371,9 @@ dependencies = [
[[package]]
name = "tauri-plugin-fs"
version = "2.0.0-beta.6"
version = "2.0.0-beta.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "609f53d90f08808679ecdd81455d9a4d0053291b92780695569f7400fdba27d5"
checksum = "35377195c6923beda5f29482a16b492d431de964389fca9aaf81a0f7e908023f"
dependencies = [
"anyhow",
"glob",
@ -5447,6 +5448,22 @@ dependencies = [
"thiserror",
]
[[package]]
name = "tauri-plugin-persisted-scope"
version = "2.0.0-beta.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b600c870217ec082b0f3482935a8edad347d18e8cd7d422a74bc92d035c0e394"
dependencies = [
"aho-corasick",
"bincode",
"log",
"serde",
"serde_json",
"tauri",
"tauri-plugin-fs",
"thiserror",
]
[[package]]
name = "tauri-plugin-process"
version = "2.0.0-beta.3"
@ -6059,9 +6076,8 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
[[package]]
name = "ts-rs"
version = "7.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc2cae1fc5d05d47aa24b64f9a4f7cba24cdc9187a2084dd97ac57bef5eccae6"
version = "8.1.0"
source = "git+https://github.com/Aleph-Alpha/ts-rs#f898578d80d3e2a54080c1c046c45f9eaa2435c3"
dependencies = [
"chrono",
"thiserror",
@ -6072,11 +6088,9 @@ dependencies = [
[[package]]
name = "ts-rs-macros"
version = "7.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73f7f9b821696963053a89a7bd8b292dc34420aea8294d7b225274d488f3ec92"
version = "8.1.0"
source = "git+https://github.com/Aleph-Alpha/ts-rs#f898578d80d3e2a54080c1c046c45f9eaa2435c3"
dependencies = [
"Inflector",
"proc-macro2",
"quote",
"syn 2.0.65",

View File

@ -28,6 +28,7 @@ tauri-plugin-fs = { version = "2.0.0-beta.6" }
tauri-plugin-http = { version = "2.0.0-beta.6" }
tauri-plugin-log = { version = "2.0.0-beta.4" }
tauri-plugin-os = { version = "2.0.0-beta.2" }
tauri-plugin-persisted-scope = { version = "2.0.0-beta.7" }
tauri-plugin-process = { version = "2.0.0-beta.2" }
tauri-plugin-shell = { version = "2.0.0-beta.2" }
tauri-plugin-updater = { version = "2.0.0-beta.4" }

View File

@ -32,6 +32,15 @@
{
"identifier": "fs:scope",
"allow": [
{
"path": "$TEMP"
},
{
"path": "$TEMP/**/*"
},
{
"path": "$HOME"
},
{
"path": "$HOME/**/*"
},
@ -56,6 +65,33 @@
]
},
"shell:allow-open",
{
"identifier": "shell:allow-execute",
"allow": [
{
"name": "open",
"cmd": "open",
"args": [
"-R",
{
"validator": "\\S+"
}
],
"sidecar": false
},
{
"name": "explorer",
"cmd": "explorer",
"args": [
"/select",
{
"validator": "\\S+"
}
],
"sidecar": false
}
]
},
"dialog:allow-open",
"dialog:allow-save",
"dialog:allow-message",

View File

@ -18,13 +18,21 @@ use oauth2::TokenResponse;
use tauri::{ipc::InvokeError, Manager};
use tauri_plugin_cli::CliExt;
use tauri_plugin_shell::ShellExt;
use tokio::process::Command;
const DEFAULT_HOST: &str = "https://api.zoo.dev";
const SETTINGS_FILE_NAME: &str = "settings.toml";
const PROJECT_SETTINGS_FILE_NAME: &str = "project.toml";
const PROJECT_FOLDER: &str = "zoo-modeling-app-projects";
#[tauri::command]
async fn rename_project_directory(project_path: &str, new_name: &str) -> Result<PathBuf, InvokeError> {
let project_dir = std::path::Path::new(project_path);
kcl_lib::settings::types::file::rename_project_directory(project_dir, new_name)
.await
.map_err(InvokeError::from_anyhow)
}
#[tauri::command]
fn get_initial_default_dir(app: tauri::AppHandle) -> Result<PathBuf, InvokeError> {
let dir = match app.path().document_dir() {
@ -323,10 +331,20 @@ async fn get_user(token: &str, hostname: &str) -> Result<kittycad::types::User,
/// From this GitHub comment: https://github.com/tauri-apps/tauri/issues/4062#issuecomment-1338048169
/// But with the Linux support removed since we don't need it for now.
#[tauri::command]
fn show_in_folder(path: &str) -> Result<(), InvokeError> {
fn show_in_folder(app: tauri::AppHandle, path: &str) -> Result<(), InvokeError> {
// Check if the file exists.
// If it doesn't, return an error.
if !Path::new(path).exists() {
return Err(InvokeError::from_anyhow(anyhow::anyhow!(
"The file `{}` does not exist",
path
)));
}
#[cfg(not(unix))]
{
Command::new("explorer")
app.shell()
.command("explorer")
.args(["/select,", path]) // The comma after select is not a typo
.spawn()
.map_err(|e| InvokeError::from_anyhow(e.into()))?;
@ -334,7 +352,8 @@ fn show_in_folder(path: &str) -> Result<(), InvokeError> {
#[cfg(unix)]
{
Command::new("open")
app.shell()
.command("open")
.args(["-R", path])
.spawn()
.map_err(|e| InvokeError::from_anyhow(e.into()))?;
@ -389,6 +408,7 @@ fn main() -> Result<()> {
write_app_settings_file,
read_project_settings_file,
write_project_settings_file,
rename_project_directory,
])
.plugin(tauri_plugin_cli::init())
.plugin(tauri_plugin_deep_link::init())
@ -405,6 +425,7 @@ fn main() -> Result<()> {
.build(),
)
.plugin(tauri_plugin_os::init())
.plugin(tauri_plugin_persisted_scope::init())
.plugin(tauri_plugin_process::init())
.plugin(tauri_plugin_shell::init())
.setup(|app| {

View File

@ -74,5 +74,5 @@
}
},
"productName": "Zoo Modeling App",
"version": "0.21.6"
"version": "0.21.8"
}

View File

@ -58,9 +58,8 @@ export function App() {
const {
app: { onboardingStatus },
} = settings.context
const { state, send } = useModelingContext()
const { state } = useModelingContext()
useHotkeys('esc', () => send('Cancel'))
useHotkeys('backspace', (e) => {
e.preventDefault()
})

View File

@ -12,6 +12,8 @@ import {
} from 'components/NetworkHealthIndicator'
import { useStore } from 'useStore'
import { ActionButtonDropdown } from 'components/ActionButtonDropdown'
import { useHotkeys } from 'react-hotkeys-hook'
import Tooltip from 'components/Tooltip'
export const Toolbar = () => {
const { commandBarSend } = useCommandsContext()
@ -40,6 +42,56 @@ export const Toolbar = () => {
const disableAllButtons =
overallState !== NetworkHealthState.Ok || isExecuting || !isStreamReady
useHotkeys(
'l',
() =>
state.matches('Sketch.Line tool')
? send('CancelSketch')
: send('Equip Line tool'),
{ enabled: !disableAllButtons, scopes: ['sketch'] }
)
useHotkeys(
'a',
() =>
state.matches('Sketch.Tangential arc to')
? send('CancelSketch')
: send('Equip tangential arc to'),
{ enabled: !disableAllButtons, scopes: ['sketch'] }
)
useHotkeys(
'r',
() =>
state.matches('Sketch.Rectangle tool')
? send('CancelSketch')
: send('Equip rectangle tool'),
{ enabled: !disableAllButtons, scopes: ['sketch'] }
)
useHotkeys(
's',
() =>
state.nextEvents.includes('Enter sketch') && pathId
? send({ type: 'Enter sketch' })
: send({ type: 'Enter sketch', data: { forceNewSketch: true } }),
{ enabled: !disableAllButtons, scopes: ['modeling'] }
)
useHotkeys(
'esc',
() =>
state.matches('Sketch.SketchIdle')
? send('Cancel')
: send('CancelSketch'),
{ enabled: !disableAllButtons, scopes: ['sketch'] }
)
useHotkeys(
'e',
() =>
commandBarSend({
type: 'Find and select command',
data: { name: 'Extrude', ownerMachine: 'modeling' },
}),
{ enabled: !disableAllButtons, scopes: ['modeling'] }
)
function handleToolbarButtonsWheelEvent(ev: WheelEvent<HTMLSpanElement>) {
const span = toolbarButtonsRef.current
if (!span) {
@ -77,6 +129,13 @@ export const Toolbar = () => {
disabled={disableAllButtons}
>
<span data-testid="start-sketch">Start Sketch</span>
<Tooltip
delay={1250}
position="bottom"
className="!px-2 !text-xs"
>
Shortcut: S
</Tooltip>
</ActionButton>
</li>
)}
@ -94,6 +153,13 @@ export const Toolbar = () => {
disabled={disableAllButtons}
>
Edit Sketch
<Tooltip
delay={1250}
position="bottom"
className="!px-2 !text-xs"
>
Shortcut: S
</Tooltip>
</ActionButton>
</li>
)}
@ -111,6 +177,13 @@ export const Toolbar = () => {
disabled={disableAllButtons}
>
Exit Sketch
<Tooltip
delay={1250}
position="bottom"
className="!px-2 !text-xs"
>
Shortcut: Esc
</Tooltip>
</ActionButton>
</li>
)}
@ -134,6 +207,13 @@ export const Toolbar = () => {
disabled={disableAllButtons}
>
Line
<Tooltip
delay={1250}
position="bottom"
className="!px-2 !text-xs"
>
Shortcut: L
</Tooltip>
</ActionButton>
</li>
<li className="contents" key="tangential-arc-button">
@ -158,6 +238,13 @@ export const Toolbar = () => {
}
>
Tangential Arc
<Tooltip
delay={1250}
position="bottom"
className="!px-2 !text-xs"
>
Shortcut: A
</Tooltip>
</ActionButton>
</li>
<li className="contents" key="rectangle-button">
@ -187,6 +274,13 @@ export const Toolbar = () => {
}
>
Rectangle
<Tooltip
delay={1250}
position="bottom"
className="!px-2 !text-xs"
>
Shortcut: R
</Tooltip>
</ActionButton>
</li>
</>
@ -264,6 +358,13 @@ export const Toolbar = () => {
}}
>
Extrude
<Tooltip
delay={1250}
position="bottom"
className="!px-2 !text-xs"
>
Shortcut: E
</Tooltip>
</ActionButton>
</li>
)}

View File

@ -20,6 +20,7 @@ import {
EngineCommand,
Subscription,
EngineCommandManager,
UnreliableSubscription,
} from 'lang/std/engineConnection'
import { uuidv4 } from 'lib/utils'
import { deg2Rad } from 'lib/utils2d'
@ -232,9 +233,19 @@ export class CameraControls {
this.update()
this._usePerspectiveCamera()
const cb: Subscription<
'default_camera_zoom' | 'camera_drag_end' | 'default_camera_get_settings'
>['callback'] = ({ data, type }) => {
type CallBackParam = Parameters<
(
| Subscription<
| 'default_camera_zoom'
| 'camera_drag_end'
| 'default_camera_get_settings'
| 'zoom_to_fit'
>
| UnreliableSubscription<'camera_drag_move'>
)['callback']
>[0]
const cb = ({ data, type }: CallBackParam) => {
const camSettings = data.settings
this.camera.position.set(
camSettings.pos.x,
@ -246,7 +257,13 @@ export class CameraControls {
camSettings.center.y,
camSettings.center.z
)
this.camera.up.set(camSettings.up.x, camSettings.up.y, camSettings.up.z)
const quat = new Quaternion(
camSettings.orientation.x,
camSettings.orientation.y,
camSettings.orientation.z,
camSettings.orientation.w
).invert()
this.camera.up.copy(new Vector3(0, 1, 0).applyQuaternion(quat))
if (this.camera instanceof PerspectiveCamera && camSettings.ortho) {
this.useOrthographicCamera()
}
@ -287,6 +304,14 @@ export class CameraControls {
event: 'default_camera_get_settings',
callback: cb,
})
this.engineCommandManager.subscribeTo({
event: 'zoom_to_fit',
callback: cb,
})
this.engineCommandManager.subscribeToUnreliable({
event: 'camera_drag_move',
callback: cb,
})
})
}

View File

@ -69,6 +69,7 @@ import {
tangentialArcToSegment,
} from './segments'
import {
addCallExpressionsToPipe,
addCloseToPipe,
addNewSketchLn,
changeSketchArguments,
@ -536,10 +537,34 @@ export class SceneEntities {
let modifiedAst
if (profileStart) {
modifiedAst = addCloseToPipe({
const lastSegment = sketchGroup.value.slice(-1)[0]
modifiedAst = addCallExpressionsToPipe({
node: kclManager.ast,
programMemory: kclManager.programMemory,
pathToNode: sketchPathToNode,
expressions: [
createCallExpressionStdLib(
lastSegment.type === 'TangentialArcTo'
? 'tangentialArcTo'
: 'lineTo',
[
createArrayExpression([
createCallExpressionStdLib('profileStartX', [
createPipeSubstitution(),
]),
createCallExpressionStdLib('profileStartY', [
createPipeSubstitution(),
]),
]),
createPipeSubstitution(),
]
),
],
})
modifiedAst = addCloseToPipe({
node: modifiedAst,
programMemory: kclManager.programMemory,
pathToNode: sketchPathToNode,
})
} else if (intersection2d) {
const lastSegment = sketchGroup.value.slice(-1)[0]
@ -560,13 +585,17 @@ export class SceneEntities {
}
await kclManager.executeAstMock(modifiedAst)
this.setUpDraftSegment(
sketchPathToNode,
forward,
up,
origin,
segmentName
)
if (profileStart) {
sceneInfra.modelingSend({ type: 'CancelSketch' })
} else {
this.setUpDraftSegment(
sketchPathToNode,
forward,
up,
origin,
segmentName
)
}
},
onMove: (args) => {
this.onDragSegment({
@ -1396,7 +1425,7 @@ export class SceneEntities {
zAxis = posNorm ? [1, 0, 0] : [-1, 0, 0]
yAxis = [0, 0, 1]
} else if (type === XZ_PLANE) {
planeString = posNorm ? 'XZ' : '-XZ'
planeString = posNorm ? '-XZ' : 'XZ'
zAxis = posNorm ? [0, 1, 0] : [0, -1, 0]
yAxis = [0, 0, 1]
}

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