Compare commits

...

32 Commits

Author SHA1 Message Date
182865014e try 2024-04-25 10:05:22 +10:00
2452eede0b omg 2024-04-25 09:59:51 +10:00
98442b9ec2 tweak 2024-04-25 09:55:52 +10:00
fb1c8036f6 try debug again 2024-04-25 09:50:22 +10:00
2918612d4b trying shit 2024-04-25 09:47:40 +10:00
abbd065c2c typo 2024-04-25 09:45:00 +10:00
23e29b024f trigger ci 2024-04-25 09:41:31 +10:00
807adac371 more tweaks 2024-04-25 09:36:36 +10:00
03eb8dca32 debug code 2024-04-25 09:35:22 +10:00
e3358f8251 more tweaks 2024-04-25 09:26:26 +10:00
49ea3991b2 another tweak 2024-04-25 09:20:14 +10:00
f32f0e2717 debug 2024-04-25 09:09:00 +10:00
0363e4f4e0 tweak 2024-04-25 08:59:53 +10:00
5e60dbd5e8 speed up playw tests by skipping wasm:build 2024-04-25 08:57:25 +10:00
379f154a5c more parallel playw tests (#2179) 2024-04-25 07:00:41 +10:00
60c4969322 Adding dark edge lines in light mode + enabling SSAO (#2219)
* adding dark edge lines in light mode + enabling SSAO

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

* Rerun CI

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Frank Noirot <frank@zoo.dev>
Co-authored-by: Frank Noirot <frank@kittycad.io>
2024-04-24 16:59:25 -04:00
cc6dee8ad4 Make it impossible to crash app while extruding (#2224)
Co-authored-by: Kurt Hutten <k.hutten@protonmail.ch>
2024-04-24 16:34:56 -04:00
2fc7c0d5fd fix gizmo (#2221) 2024-04-24 20:09:39 +00:00
bf2dcd808f Bump tauri-plugin-http from 2.0.0-beta.5 to 2.0.0-beta.6 in /src-tauri (#2222)
Bumps [tauri-plugin-http](https://github.com/tauri-apps/plugins-workspace) from 2.0.0-beta.5 to 2.0.0-beta.6.
- [Release notes](https://github.com/tauri-apps/plugins-workspace/releases)
- [Commits](https://github.com/tauri-apps/plugins-workspace/compare/fs-v2.0.0-beta.5...fs-v2.0.0-beta.6)

---
updated-dependencies:
- dependency-name: tauri-plugin-http
  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-04-24 05:54:18 -04:00
ee21e486d4 math u32 fix (#2218)
* math fix

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)

* empty

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

* empty

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-04-23 22:59:12 +00:00
b5a3eb9e9c Bump tauri-build from 2.0.0-beta.12 to 2.0.0-beta.13 in /src-tauri (#2204)
Bumps [tauri-build](https://github.com/tauri-apps/tauri) from 2.0.0-beta.12 to 2.0.0-beta.13.
- [Release notes](https://github.com/tauri-apps/tauri/releases)
- [Commits](https://github.com/tauri-apps/tauri/compare/tauri-build-v2.0.0-beta.12...tauri-build-v2.0.0-beta.13)

---
updated-dependencies:
- dependency-name: tauri-build
  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-04-23 20:57:23 +00:00
c85645c9f2 Bump tauri-plugin-dialog from 2.0.0-beta.5 to 2.0.0-beta.6 in /src-tauri (#2203)
Bumps [tauri-plugin-dialog](https://github.com/tauri-apps/plugins-workspace) from 2.0.0-beta.5 to 2.0.0-beta.6.
- [Release notes](https://github.com/tauri-apps/plugins-workspace/releases)
- [Commits](https://github.com/tauri-apps/plugins-workspace/compare/fs-v2.0.0-beta.5...fs-v2.0.0-beta.6)

---
updated-dependencies:
- dependency-name: tauri-plugin-dialog
  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-04-23 18:48:00 +00:00
cfa4dd2e33 Bump kittycad-modeling-cmds from 0.2.20 to 0.2.21 in /src/wasm-lib (#2199)
Bumps [kittycad-modeling-cmds](https://github.com/KittyCAD/modeling-api) from 0.2.20 to 0.2.21.
- [Commits](https://github.com/KittyCAD/modeling-api/compare/kittycad-modeling-cmds-0.2.20...kittycad-modeling-cmds-0.2.21)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-23 17:55:03 +00:00
c620f7269c Patterns fixes (2d) (#2197)
* updates

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

* patterns fixes

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

* fix docs

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

* better autocomplete

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

* fix

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

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2024-04-23 17:31:20 +00:00
2d8d29b345 Bump tauri-plugin-fs from 2.0.0-beta.5 to 2.0.0-beta.6 in /src-tauri (#2205)
Bumps [tauri-plugin-fs](https://github.com/tauri-apps/plugins-workspace) from 2.0.0-beta.5 to 2.0.0-beta.6.
- [Release notes](https://github.com/tauri-apps/plugins-workspace/releases)
- [Commits](https://github.com/tauri-apps/plugins-workspace/compare/fs-v2.0.0-beta.5...fs-v2.0.0-beta.6)

---
updated-dependencies:
- dependency-name: tauri-plugin-fs
  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-04-23 16:56:00 +00:00
00da062586 bump kittycad.rs (#2196)
* update lib

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

* fix tests

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

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2024-04-23 03:46:54 +00:00
aafbaf6c50 human speed completions (#2193)
* human speed completions

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

* add slowness

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

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

* empty

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-04-23 00:21:24 +00:00
2894c84a4e fix recast (#2194)
* fix recast

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

* fixes

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

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2024-04-22 17:14:20 -07:00
c01084feb0 Zoom to fit rust side (#2195)
* zoom to fit

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

* zoom to fit

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

* docs

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-04-22 17:14:10 -07:00
c461db5f54 fix const completion (#2192)
Signed-off-by: Jess Frazelle <github@jessfraz.com>
2024-04-22 21:53:49 +00:00
03fcb73aca Bump kittycad-modeling-cmds from 0.2.19 to 0.2.20 in /src/wasm-lib (#2186)
Bumps [kittycad-modeling-cmds](https://github.com/KittyCAD/modeling-api) from 0.2.19 to 0.2.20.
- [Commits](https://github.com/KittyCAD/modeling-api/compare/kittycad-modeling-cmds-0.2.19...kittycad-modeling-cmds-0.2.20)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jess Frazelle <jessfraz@users.noreply.github.com>
2024-04-22 20:09:53 +00:00
8065e7e51a Bump thiserror from 1.0.58 to 1.0.59 in /src/wasm-lib (#2187)
Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.58 to 1.0.59.
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/1.0.58...1.0.59)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jess Frazelle <jessfraz@users.noreply.github.com>
2024-04-22 18:46:00 +00:00
261 changed files with 6051 additions and 2869 deletions

View File

@ -1,5 +1,6 @@
VITE_KC_API_WS_MODELING_URL=wss://api.dev.zoo.dev/ws/modeling/commands
VITE_KC_API_BASE_URL=https://api.dev.zoo.dev
VITE_KC_SITE_BASE_URL=https://dev.zoo.dev
VITE_KC_WASM_OVERRIDE_URL=""
VITE_KC_SKIP_AUTH=false
VITE_KC_CONNECTION_TIMEOUT_MS=5000

View File

@ -1,5 +1,6 @@
VITE_KC_API_WS_MODELING_URL=wss://api.zoo.dev/ws/modeling/commands
VITE_KC_API_BASE_URL=https://api.zoo.dev
VITE_KC_SITE_BASE_URL=https://zoo.dev
VITE_KC_WASM_OVERRIDE_URL=""
VITE_KC_SKIP_AUTH=false
VITE_KC_CONNECTION_TIMEOUT_MS=15000

View File

@ -14,9 +14,31 @@ permissions:
pull-requests: write
jobs:
check-wasm-lib-changes:
runs-on: ubuntu-latest
outputs:
url: ${{ steps.set-output.outputs.url }}
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0 # Fetches all history for all branches and tags
- name: Check for changes in src/wasm-lib
id: set-output
run: |
if git diff --quiet origin/main...HEAD -- src/wasm-lib; then
echo "url=https://app.zoo.dev" >> $GITHUB_OUTPUT
echo "No changes detected in src/wasm-lib"
else
echo "Changes detected in src/wasm-lib"
echo "url=" >> $GITHUB_OUTPUT
fi
playwright-ubuntu:
timeout-minutes: 60
runs-on: ubuntu-latest-8-cores
needs: check-wasm-lib-changes
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
@ -28,13 +50,19 @@ jobs:
run: yarn
- name: Install Playwright Browsers
run: yarn playwright install --with-deps
- name: Print WASM Lib Changes URL
run: |
echo "WASM Lib Changes URL: ${{ needs.check-wasm-lib-changes.outputs.url }}"
- name: Setup Rust
if: ${{ needs.check-wasm-lib-changes.outputs.url }} == ''
uses: dtolnay/rust-toolchain@stable
- name: Cache wasm
if: ${{ needs.check-wasm-lib-changes.outputs.url }} == ''
uses: Swatinem/rust-cache@v2
with:
workspaces: './src/wasm-lib'
- name: build wasm
if: ${{ needs.check-wasm-lib-changes.outputs.url }} == ''
run: yarn build:wasm
- name: build web
run: yarn build:local
@ -44,6 +72,7 @@ jobs:
CI: true
token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
snapshottoken: ${{ secrets.KITTYCAD_API_TOKEN }}
WASM_OVERRIDE: ${{ steps.check-wasm-lib-changes.outputs.url }}
- uses: actions/upload-artifact@v3
if: always()
with:
@ -79,6 +108,7 @@ jobs:
env:
CI: true
token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
WASM_OVERRIDE: ${{ steps.check-wasm-lib-changes.outputs.url }}
- uses: actions/upload-artifact@v3
if: always()
with:
@ -89,6 +119,7 @@ jobs:
playwright-macos:
timeout-minutes: 60
runs-on: macos-14
needs: check-wasm-lib-changes
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
@ -100,12 +131,15 @@ jobs:
- name: Install Playwright Browsers
run: yarn playwright install --with-deps
- name: Setup Rust
if: needs.check-wasm-lib-changes.outputs.url == ''
uses: dtolnay/rust-toolchain@stable
- name: Cache wasm
if: needs.check-wasm-lib-changes.outputs.url == ''
uses: Swatinem/rust-cache@v2
with:
workspaces: './src/wasm-lib'
- name: build wasm
if: needs.check-wasm-lib-changes.outputs.url == ''
run: yarn build:wasm
- name: build web
run: yarn build:local
@ -116,6 +150,7 @@ jobs:
env:
CI: true
token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
WASM_OVERRIDE: ${{ steps.check-wasm-lib-changes.outputs.url }}
- uses: actions/upload-artifact@v3
if: always()
with:

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

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

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

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

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

@ -565,7 +565,9 @@ test('Auto complete works', async ({ page }) => {
await page.keyboard.press('Tab')
await page.keyboard.type('12')
await page.waitForTimeout(100)
await page.keyboard.press('Tab')
await page.waitForTimeout(100)
await page.keyboard.press('Tab')
await page.keyboard.press('Tab')
await page.keyboard.press('Enter')
@ -1033,6 +1035,7 @@ const part001 = startSketchOn('-XZ')
})
test('Can add multiple sketches', async ({ page }) => {
test.skip(process.platform === 'darwin', 'Can add multiple sketches')
const u = getUtils(page)
await page.setViewportSize({ width: 1200, height: 500 })
const PUR = 400 / 37.5 //pixeltoUnitRatio

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 46 KiB

View File

@ -7,6 +7,7 @@ export const TEST_SETTINGS = {
theme: Themes.Dark,
onboardingStatus: 'dismissed',
projectDirectory: '',
enableSSAO: false,
},
modeling: {
defaultUnit: 'in',

View File

@ -6,7 +6,7 @@ import { PNG } from 'pngjs'
async function waitForPageLoad(page: Page) {
// wait for 'Loading stream...' spinner
// await page.getByTestId('loading-stream').waitFor()
await page.getByTestId('loading-stream').waitFor()
// wait for all spinners to be gone
await page.getByTestId('loading').waitFor({ state: 'detached' })

View File

@ -18,7 +18,7 @@ export default defineConfig({
/* Retry on CI only */
retries: process.env.CI ? 3 : 0,
/* Opt out of parallel tests on CI. */
workers: process.env.CI ? 1 : 1,
workers: process.env.CI ? 2 : 1,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: 'html',
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
@ -72,7 +72,7 @@ export default defineConfig({
/* Run your local dev server before starting the tests */
webServer: {
command: 'yarn serve',
command: 'VITE_KC_WASM_OVERRIDE_URL=$WASM_OVERRIDE yarn serve',
// url: 'http://127.0.0.1:3000',
reuseExistingServer: !process.env.CI,
},

44
src-tauri/Cargo.lock generated
View File

@ -1592,7 +1592,7 @@ version = "0.18.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0bb0228f477c0900c880fd78c8759b95c7636dbd7842707f49e132378aa2acdc"
dependencies = [
"heck",
"heck 0.4.1",
"proc-macro-crate 2.0.2",
"proc-macro-error",
"proc-macro2",
@ -1735,6 +1735,12 @@ version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
[[package]]
name = "heck"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "hermit-abi"
version = "0.2.6"
@ -2199,9 +2205,9 @@ dependencies = [
[[package]]
name = "kittycad"
version = "0.2.67"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc460442c165c8e707b1154551cefd08938d10bb80c78940e10cd9869487c325"
checksum = "ddc922f0da3abc22661bf49423c9bfcc02ce6ae92dae007ede6990874789545b"
dependencies = [
"anyhow",
"async-trait",
@ -4322,7 +4328,7 @@ version = "0.24.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59"
dependencies = [
"heck",
"heck 0.4.1",
"proc-macro2",
"quote",
"rustversion",
@ -4411,7 +4417,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5fa6fb9ee296c0dc2df41a656ca7948546d061958115ddb0bcaae43ad0d17d2"
dependencies = [
"cfg-expr",
"heck",
"heck 0.4.1",
"pkg-config",
"toml 0.7.8",
"version-compare",
@ -4508,7 +4514,7 @@ dependencies = [
"getrandom 0.2.14",
"glob",
"gtk",
"heck",
"heck 0.4.1",
"http 1.1.0",
"jni",
"libc",
@ -4543,15 +4549,15 @@ dependencies = [
[[package]]
name = "tauri-build"
version = "2.0.0-beta.12"
version = "2.0.0-beta.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33de24aabe2b9c340d67005800cb6dd40aac5283126a42896fc8eec0b87cbe45"
checksum = "abcf98a9b4527567c3e5ca9723431d121e001c2145651b3fa044d22b5e025a7e"
dependencies = [
"anyhow",
"cargo_toml",
"dirs-next",
"glob",
"heck",
"heck 0.5.0",
"json-patch",
"schemars",
"semver",
@ -4596,7 +4602,7 @@ version = "2.0.0-beta.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b096f63f2724a1280ae0f5a34d0731de18ca18305e2ef6e5e9a39bb2710e8a85"
dependencies = [
"heck",
"heck 0.4.1",
"proc-macro2",
"quote",
"syn 2.0.48",
@ -4623,9 +4629,9 @@ dependencies = [
[[package]]
name = "tauri-plugin-dialog"
version = "2.0.0-beta.5"
version = "2.0.0-beta.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db4476c824a1488a52f4672d2b419a71fbf3dc97249013ef3c2c08fae2a23b71"
checksum = "87caf6f2b704b0d27b4c64ef1fdd1f6ef97e2f5293216e230ad1efe61de54131"
dependencies = [
"dunce",
"log",
@ -4641,9 +4647,9 @@ dependencies = [
[[package]]
name = "tauri-plugin-fs"
version = "2.0.0-beta.5"
version = "2.0.0-beta.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c138126392c350aa68554e3461529b02680062c9146ab7b41d3ef97a2deaf93b"
checksum = "609f53d90f08808679ecdd81455d9a4d0053291b92780695569f7400fdba27d5"
dependencies = [
"anyhow",
"glob",
@ -4660,9 +4666,9 @@ dependencies = [
[[package]]
name = "tauri-plugin-http"
version = "2.0.0-beta.5"
version = "2.0.0-beta.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f27b2c90ed5473e1c068f523927fa0024212bc3a3f3a47c2a9c0b10b4b2e3ee4"
checksum = "b7c32962a2e2141b3bc034e5c04f363635965e59435794b6bdcf97a027f0925a"
dependencies = [
"data-url",
"http 1.1.0",
@ -4800,16 +4806,16 @@ dependencies = [
[[package]]
name = "tauri-utils"
version = "2.0.0-beta.12"
version = "2.0.0-beta.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "760ac613d7f0de95067bcbcbcea175fe1df88fc4ab59c7f0b2cc2d01dc16a199"
checksum = "d4709765385f035338ecc330f3fba753b8ee283c659c235da9768949cdb25469"
dependencies = [
"brotli",
"cargo_metadata",
"ctor",
"dunce",
"glob",
"heck",
"heck 0.5.0",
"html5ever",
"infer",
"json-patch",

View File

@ -12,18 +12,18 @@ rust-version = "1.70"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[build-dependencies]
tauri-build = { version = "2.0.0-beta.12", features = [] }
tauri-build = { version = "2.0.0-beta.13", features = [] }
[dependencies]
anyhow = "1"
kittycad = "0.2.67"
kittycad = "0.3.0"
oauth2 = "4.4.2"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
tauri = { version = "2.0.0-beta.15", features = [ "devtools", "unstable"] }
tauri-plugin-dialog = { version = "2.0.0-beta.5" }
tauri-plugin-fs = { version = "2.0.0-beta.5" }
tauri-plugin-http = { version = "2.0.0-beta.5" }
tauri-plugin-dialog = { version = "2.0.0-beta.6" }
tauri-plugin-fs = { version = "2.0.0-beta.6" }
tauri-plugin-http = { version = "2.0.0-beta.6" }
tauri-plugin-os = { version = "2.0.0-beta.2" }
tauri-plugin-process = { version = "2.0.0-beta.2" }
tauri-plugin-shell = { version = "2.0.0-beta.2" }

View File

@ -3,13 +3,12 @@ import { useCommandsContext } from 'hooks/useCommandsContext'
import { useKclContext } from 'lang/KclProvider'
import { CommandArgument } from 'lib/commandTypes'
import {
ResolvedSelectionType,
canSubmitSelectionArg,
getSelectionType,
getSelectionTypeDisplayText,
} from 'lib/selections'
import { modelingMachine } from 'machines/modelingMachine'
import { useEffect, useRef, useState } from 'react'
import { useCallback, useEffect, useRef, useState } from 'react'
import { useHotkeys } from 'react-hotkeys-hook'
import { StateFrom } from 'xstate'
@ -30,13 +29,13 @@ function CommandBarSelectionInput({
const { commandBarState, commandBarSend } = useCommandsContext()
const [hasSubmitted, setHasSubmitted] = useState(false)
const selection = useSelector(arg.machineActor, selectionSelector)
const [selectionsByType, setSelectionsByType] = useState<
'none' | ResolvedSelectionType[]
>(
selection.codeBasedSelections[0]?.range[1] === code.length
const initSelectionsByType = useCallback(() => {
const selectionRangeEnd = selection.codeBasedSelections[0]?.range[1]
return !selectionRangeEnd || selectionRangeEnd === code.length
? 'none'
: getSelectionType(selection)
)
}, [selection, code])
const selectionsByType = initSelectionsByType()
const [canSubmitSelection, setCanSubmitSelection] = useState<boolean>(
canSubmitSelectionArg(selectionsByType, arg)
)
@ -51,17 +50,14 @@ function CommandBarSelectionInput({
inputRef.current?.focus()
}, [selection, inputRef])
useEffect(() => {
setSelectionsByType(
selection.codeBasedSelections[0]?.range[1] === code.length
? 'none'
: getSelectionType(selection)
)
}, [selection])
// Fast-forward through this arg if it's marked as skippable
// and we have a valid selection already
useEffect(() => {
console.log('selection input effect', {
selectionsByType,
canSubmitSelection,
arg,
})
setCanSubmitSelection(canSubmitSelectionArg(selectionsByType, arg))
const argValue = commandBarState.context.argumentsToSubmit[arg.name]
if (canSubmitSelection && arg.skip && argValue === undefined) {

View File

@ -77,7 +77,7 @@ export const ModelingMachineProvider = ({
auth,
settings: {
context: {
app: { theme },
app: { theme, enableSSAO },
modeling: { defaultUnit, highlightEdges },
},
},
@ -87,6 +87,7 @@ export const ModelingMachineProvider = ({
useSetupEngineManager(streamRef, token, {
theme: theme.current,
highlightEdges: highlightEdges.current,
enableSSAO: enableSSAO.current,
})
const { htmlRef } = useStore((s) => ({
htmlRef: s.htmlRef,
@ -267,10 +268,12 @@ export const ModelingMachineProvider = ({
'has valid extrude selection': ({ selectionRanges }) => {
// A user can begin extruding if they either have 1+ faces selected or nothing selected
// TODO: I believe this guard only allows for extruding a single face at a time
if (selectionRanges.codeBasedSelections.length < 1) return false
const isPipe = isSketchPipe(selectionRanges)
if (isSelectionLastLine(selectionRanges, codeManager.code))
if (
selectionRanges.codeBasedSelections.length === 0 ||
isSelectionLastLine(selectionRanges, codeManager.code)
)
return true
if (!isPipe) return false

View File

@ -16,7 +16,6 @@ import {
EditorView,
dropCursor,
drawSelection,
ViewUpdate,
} from '@codemirror/view'
import {
indentWithTab,
@ -191,9 +190,6 @@ export const KclEditorPane = () => {
return extensions
}, [kclLSP, copilotLSP, textWrapping.current, cursorBlinking.current])
let debounceTimer: ReturnType<typeof setTimeout> | null = null
const updateDelay = 100
return (
<div
id="code-mirror-override"
@ -206,17 +202,6 @@ export const KclEditorPane = () => {
onCreateEditor={(_editorView) =>
editorManager.setEditorView(_editorView)
}
onUpdate={(view: ViewUpdate) => {
// debounce the view update.
// otherwise it is laggy for typing.
if (debounceTimer) {
clearTimeout(debounceTimer)
}
debounceTimer = setTimeout(() => {
editorManager.handleOnViewUpdate(view)
}, updateDelay)
}}
indentWithTab={false}
basicSetup={false}
/>

View File

@ -7,7 +7,12 @@ import React, { createContext, useEffect } from 'react'
import useStateMachineCommands from '../hooks/useStateMachineCommands'
import { settingsMachine } from 'machines/settingsMachine'
import { toast } from 'react-hot-toast'
import { getThemeColorForEngine, setThemeClass, Themes } from 'lib/theme'
import {
getThemeColorForEngine,
getOppositeTheme,
setThemeClass,
Themes,
} from 'lib/theme'
import decamelize from 'decamelize'
import {
AnyStateMachine,
@ -99,6 +104,9 @@ export const SettingsAuthProviderBase = ({
{
context: loadedSettings,
actions: {
//TODO: batch all these and if that's difficult to do from tsx,
// make it easy to do
setClientSideSceneUnits: (context, event) => {
const newBaseUnit =
event.type === 'set.modeling.defaultUnit'
@ -115,6 +123,16 @@ export const SettingsAuthProviderBase = ({
color: getThemeColorForEngine(context.app.theme.current),
},
})
const opposingTheme = getOppositeTheme(context.app.theme.current)
engineCommandManager.sendSceneCommand({
cmd_id: uuidv4(),
type: 'modeling_cmd_req',
cmd: {
type: 'set_default_system_properties',
color: getThemeColorForEngine(opposingTheme),
},
})
},
setEngineEdges: (context) => {
engineCommandManager.sendSceneCommand({

View File

@ -39,6 +39,8 @@ const CompletionItemKindMap = Object.fromEntries(
) as Record<CompletionItemKind, string>
const changesDelay = 600
let debounceTimer: ReturnType<typeof setTimeout> | null = null
const updateDelay = 100
export class LanguageServerPlugin implements PluginValue {
public client: LanguageServerClient
@ -47,6 +49,7 @@ export class LanguageServerPlugin implements PluginValue {
public workspaceFolders: LSP.WorkspaceFolder[]
private documentVersion: number
private foldingRanges: LSP.FoldingRange[] | null = null
private viewUpdate: ViewUpdate | null = null
private _defferer = deferExecution((code: string) => {
try {
// Update the state (not the editor) with the new code.
@ -57,8 +60,9 @@ export class LanguageServerPlugin implements PluginValue {
},
contentChanges: [{ text: code }],
})
if (editorManager.editorView) {
//editorManager.handleOnViewUpdate(editorManager.editorView)
if (this.viewUpdate) {
editorManager.handleOnViewUpdate(this.viewUpdate)
}
} catch (e) {
console.error(e)
@ -83,14 +87,27 @@ export class LanguageServerPlugin implements PluginValue {
})
}
update({ docChanged }: ViewUpdate) {
if (!docChanged) return
update(viewUpdate: ViewUpdate) {
this.viewUpdate = viewUpdate
if (!viewUpdate.docChanged) {
// debounce the view update.
// otherwise it is laggy for typing.
if (debounceTimer) {
clearTimeout(debounceTimer)
}
debounceTimer = setTimeout(() => {
editorManager.handleOnViewUpdate(viewUpdate)
}, updateDelay)
return
}
const newCode = this.view.state.doc.toString()
codeManager.code = newCode
codeManager.writeToFile()
kclManager.executeCode()
this.sendChange({
documentText: newCode,
})

View File

@ -7,5 +7,7 @@ export const VITE_KC_API_BASE_URL = import.meta.env.VITE_KC_API_BASE_URL
export const VITE_KC_SITE_BASE_URL = import.meta.env.VITE_KC_SITE_BASE_URL
export const VITE_KC_CONNECTION_TIMEOUT_MS = import.meta.env
.VITE_KC_CONNECTION_TIMEOUT_MS
export const VITE_KC_WASM_OVERRIDE_URL = import.meta.env
.VITE_KC_WASM_OVERRIDE_URL
export const TEST = import.meta.env.TEST
export const DEV = import.meta.env.DEV

View File

@ -11,9 +11,11 @@ export function useSetupEngineManager(
settings = {
theme: Themes.System,
highlightEdges: true,
enableSSAO: true,
} as {
theme: Themes
highlightEdges: boolean
enableSSAO: boolean
}
) {
const {

View File

@ -4,7 +4,7 @@ import { Models } from '@kittycad/lib'
import { exportSave } from 'lib/exportSave'
import { uuidv4 } from 'lib/utils'
import { getNodePathFromSourceRange } from 'lang/queryAst'
import { Themes, getThemeColorForEngine } from 'lib/theme'
import { Themes, getThemeColorForEngine, getOppositeTheme } from 'lib/theme'
import { DefaultPlanes } from 'wasm-lib/kcl/bindings/DefaultPlanes'
let lastMessage = ''
@ -941,6 +941,7 @@ export class EngineCommandManager {
settings = {
theme: Themes.Dark,
highlightEdges: true,
enableSSAO: true,
},
}: {
setMediaStream: (stream: MediaStream) => void
@ -953,6 +954,7 @@ export class EngineCommandManager {
settings?: {
theme: Themes
highlightEdges: boolean
enableSSAO: boolean
}
}) {
this.makeDefaultPlanes = makeDefaultPlanes
@ -969,7 +971,8 @@ export class EngineCommandManager {
return
}
const url = `${VITE_KC_API_WS_MODELING_URL}?video_res_width=${width}&video_res_height=${height}`
const additionalSettings = settings.enableSSAO ? '&post_effect=ssao' : ''
const url = `${VITE_KC_API_WS_MODELING_URL}?video_res_width=${width}&video_res_height=${height}${additionalSettings}`
this.engineConnection = new EngineConnection({
engineCommandManager: this,
url,
@ -989,6 +992,18 @@ export class EngineCommandManager {
color: getThemeColorForEngine(settings.theme),
},
})
// Sets the default line colors
const opposingTheme = getOppositeTheme(settings.theme)
this.sendSceneCommand({
cmd_id: uuidv4(),
type: 'modeling_cmd_req',
cmd: {
type: 'set_default_system_properties',
color: getThemeColorForEngine(opposingTheme),
},
})
// Set the edge lines visibility
this.sendSceneCommand({
type: 'modeling_cmd_req',
@ -1326,6 +1341,17 @@ export class EngineCommandManager {
this.lastArtifactMap = this.artifactMap
this.artifactMap = {}
await this.initPlanes()
await this.sendSceneCommand({
type: 'modeling_cmd_req',
cmd_id: uuidv4(),
cmd: {
type: 'make_axes_gizmo',
clobber: false,
// If true, axes gizmo will be placed in the corner of the screen.
// If false, it will be placed at the origin of the scene.
gizmo_mode: true,
},
})
}
subscribeTo<T extends ModelTypes>({
event,

View File

@ -25,7 +25,7 @@ import { AppInfo } from 'wasm-lib/kcl/bindings/AppInfo'
import { CoreDumpManager } from 'lib/coredump'
import openWindow from 'lib/openWindow'
import { DefaultPlanes } from 'wasm-lib/kcl/bindings/DefaultPlanes'
import { TEST } from 'env'
import { TEST, VITE_KC_WASM_OVERRIDE_URL } from 'env'
export type { Program } from '../wasm-lib/kcl/bindings/Program'
export type { Value } from '../wasm-lib/kcl/bindings/Value'
@ -76,8 +76,9 @@ export type { MemoryItem } from '../wasm-lib/kcl/bindings/MemoryItem'
export type { ExtrudeSurface } from '../wasm-lib/kcl/bindings/ExtrudeSurface'
export const wasmUrl = () => {
const baseUrl =
typeof window === 'undefined'
const baseUrl = VITE_KC_WASM_OVERRIDE_URL
? VITE_KC_WASM_OVERRIDE_URL
: typeof window === 'undefined'
? 'http://127.0.0.1:3000'
: window.location.origin.includes('tauri://localhost')
? 'tauri://localhost' // custom protocol for macOS

View File

@ -420,7 +420,13 @@ export function getSelectionTypeDisplayText(
const selectionsByType = getSelectionType(selection)
return (selectionsByType as Exclude<typeof selectionsByType, 'none'>)
.map(([type, count]) => `${count} ${type}${count > 1 ? 's' : ''}`)
.map(
// Hack for showing "face" instead of "extrude-wall" in command bar text
([type, count]) =>
`${count} ${type.replace('extrude-wall', 'face')}${
count > 1 ? 's' : ''
}`
)
.join(', ')
}

View File

@ -156,6 +156,13 @@ export function createSettings() {
</div>
),
}),
enableSSAO: new Setting<boolean>({
defaultValue: true,
description:
'Whether or not Screen Space Ambient Occlusion (SSAO) is enabled',
validate: (v) => typeof v === 'boolean',
hideOnPlatform: 'both', //for now
}),
onboardingStatus: new Setting<string>({
defaultValue: '',
validate: (v) => typeof v === 'string',

View File

@ -23,6 +23,17 @@ export function setThemeClass(theme: Themes) {
}
}
// Returns the resolved theme in use (Dark || Light)
export function getResolvedTheme(theme: Themes) {
return theme === Themes.System ? getSystemTheme() : theme
}
// Returns the opposing theme
export function getOppositeTheme(theme: Themes) {
const resolvedTheme = getResolvedTheme(theme)
return resolvedTheme === Themes.Dark ? Themes.Light : Themes.Dark
}
/**
* The engine takes RGBA values from 0-1
* So we convert from the conventional 0-255 found in Figma
@ -30,7 +41,7 @@ export function setThemeClass(theme: Themes) {
* @returns { r: number, g: number, b: number, a: number }
*/
export function getThemeColorForEngine(theme: Themes) {
const resolvedTheme = theme === Themes.System ? getSystemTheme() : theme
const resolvedTheme = getResolvedTheme(theme)
const dark = 28 / 255
const light = 249 / 255
return resolvedTheme === Themes.Dark

View File

@ -31,9 +31,11 @@ export function useCalculateKclExpression({
newVariableInsertIndex: number
setNewVariableName: (a: string) => void
} {
const { programMemory } = useKclContext()
const { programMemory, code } = useKclContext()
const { context } = useModelingContext()
const selectionRange = context.selectionRanges.codeBasedSelections[0].range
const selectionRange:
| (typeof context.selectionRanges.codeBasedSelections)[number]['range']
| undefined = context.selectionRanges.codeBasedSelections[0]?.range
const inputRef = useRef<HTMLInputElement>(null)
const [availableVarInfo, setAvailableVarInfo] = useState<
ReturnType<typeof findAllPreviousVariables>
@ -67,7 +69,7 @@ export function useCalculateKclExpression({
} else {
setIsNewVariableNameUnique(true)
}
}, [newVariableName])
}, [programMemory, newVariableName])
useEffect(() => {
if (!programMemory || !selectionRange) return
@ -81,8 +83,8 @@ export function useCalculateKclExpression({
useEffect(() => {
const execAstAndSetResult = async () => {
const code = `const __result__ = ${value}`
const ast = parse(code)
const _code = `const __result__ = ${value}`
const ast = parse(_code)
const _programMem: any = { root: {}, return: null }
availableVarInfo.variables.forEach(({ key, value }) => {
_programMem.root[key] = { type: 'userVal', value, __meta: [] }
@ -111,7 +113,7 @@ export function useCalculateKclExpression({
setCalcResult('NAN')
setValueNode(null)
})
}, [value, availableVarInfo])
}, [value, availableVarInfo, code, kclManager.programMemory])
return {
valueNode,

View File

@ -6,10 +6,10 @@
serial-integration = { max-threads = 4 }
[profile.default]
slow-timeout = { period = "10s", terminate-after = 1 }
slow-timeout = { period = "30s", terminate-after = 1 }
[profile.ci]
slow-timeout = { period = "30s", terminate-after = 5 }
slow-timeout = { period = "50s", terminate-after = 5 }
[[profile.default.overrides]]
filter = "test(serial_test_)"

View File

@ -927,7 +927,7 @@ dependencies = [
[[package]]
name = "derive-docs"
version = "0.1.14"
version = "0.1.16"
dependencies = [
"Inflector",
"anyhow",
@ -1854,7 +1854,7 @@ dependencies = [
[[package]]
name = "kcl-lib"
version = "0.1.47"
version = "0.1.50"
dependencies = [
"anyhow",
"approx 0.5.1",
@ -1921,9 +1921,9 @@ dependencies = [
[[package]]
name = "kittycad"
version = "0.2.67"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc460442c165c8e707b1154551cefd08938d10bb80c78940e10cd9869487c325"
checksum = "ddc922f0da3abc22661bf49423c9bfcc02ce6ae92dae007ede6990874789545b"
dependencies = [
"anyhow",
"async-trait",
@ -1959,9 +1959,9 @@ dependencies = [
[[package]]
name = "kittycad-execution-plan"
version = "0.1.4"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acf8ffb148bd09de8889a8a2b3075a23ee86446c3a6e1c6dcf66b40fdc778158"
checksum = "ae99665cd699f8800da8ea4b01889c0c9c61619d2a9dc62d1d5028f1b21110bd"
dependencies = [
"bytes",
"gltf-json",
@ -2004,9 +2004,9 @@ dependencies = [
[[package]]
name = "kittycad-modeling-cmds"
version = "0.2.19"
version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "35bb4946fa7bbcfd5270448e31834286c62e30e0f4599ef102a5b63e63b1f50b"
checksum = "e326955e8f315590a1926c17ff6a6082d3013f472c881aba56d73bfa170cf5b3"
dependencies = [
"anyhow",
"chrono",
@ -2044,9 +2044,9 @@ dependencies = [
[[package]]
name = "kittycad-modeling-session"
version = "0.1.3"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bae9bc47fcc3cc30727b35e738c35666b97e1e5f48f3f4c60ddaeccb69b66559"
checksum = "241d45ca828af2953bf538f312a3e9d6fa7fe83055c90f6b6b9ffa76f53b6285"
dependencies = [
"futures",
"kittycad",
@ -3963,18 +3963,18 @@ dependencies = [
[[package]]
name = "thiserror"
version = "1.0.58"
version = "1.0.59"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297"
checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.58"
version = "1.0.59"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7"
checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66"
dependencies = [
"proc-macro2",
"quote",

View File

@ -61,12 +61,12 @@ members = [
]
[workspace.dependencies]
kittycad = { version = "0.2.67", default-features = false, features = ["js", "requests"] }
kittycad-execution-plan = "0.1.4"
kittycad = { version = "0.3.0", default-features = false, features = ["js", "requests"] }
kittycad-execution-plan = "0.1.5"
kittycad-execution-plan-macros = "0.1.9"
kittycad-execution-plan-traits = "0.1.14"
kittycad-modeling-cmds = "0.2.19"
kittycad-modeling-session = "0.1.3"
kittycad-modeling-cmds = "0.2.21"
kittycad-modeling-session = "0.1.4"
[[test]]
name = "executor"

View File

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

View File

@ -788,17 +788,14 @@ fn generate_code_block_test(
ctx.run(program, None).await.unwrap();
let (x, y) = crate::std::utils::get_camera_zoom_magnitude_per_unit_length(units);
// Zoom to fit.
ctx.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
crate::executor::SourceRange::default(),
kittycad::types::ModelingCmd::DefaultCameraLookAt {
center: kittycad::types::Point3D { x: 0.0, y: 0.0, z: 0.0 },
up: kittycad::types::Point3D { x: 0.0, y: 0.0, z: 1.0 },
vantage: kittycad::types::Point3D { x: 0.0, y: -x, z: y },
sequence: None,
kittycad::types::ModelingCmd::ZoomToFit {
object_ids: Default::default(),
padding: 0.1,
},
)
.await.unwrap();

View File

@ -33,28 +33,13 @@ mod test_examples_show {
.await
.unwrap();
ctx.run(program, None).await.unwrap();
let (x, y) = crate::std::utils::get_camera_zoom_magnitude_per_unit_length(units);
ctx.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
crate::executor::SourceRange::default(),
kittycad::types::ModelingCmd::DefaultCameraLookAt {
center: kittycad::types::Point3D {
x: 0.0,
y: 0.0,
z: 0.0,
},
up: kittycad::types::Point3D {
x: 0.0,
y: 0.0,
z: 1.0,
},
vantage: kittycad::types::Point3D {
x: 0.0,
y: -x,
z: y,
},
sequence: None,
kittycad::types::ModelingCmd::ZoomToFit {
object_ids: Default::default(),
padding: 0.1,
},
)
.await
@ -125,28 +110,13 @@ mod test_examples_show {
.await
.unwrap();
ctx.run(program, None).await.unwrap();
let (x, y) = crate::std::utils::get_camera_zoom_magnitude_per_unit_length(units);
ctx.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
crate::executor::SourceRange::default(),
kittycad::types::ModelingCmd::DefaultCameraLookAt {
center: kittycad::types::Point3D {
x: 0.0,
y: 0.0,
z: 0.0,
},
up: kittycad::types::Point3D {
x: 0.0,
y: 0.0,
z: 1.0,
},
vantage: kittycad::types::Point3D {
x: 0.0,
y: -x,
z: y,
},
sequence: None,
kittycad::types::ModelingCmd::ZoomToFit {
object_ids: Default::default(),
padding: 0.1,
},
)
.await

View File

@ -33,28 +33,13 @@ mod test_examples_show {
.await
.unwrap();
ctx.run(program, None).await.unwrap();
let (x, y) = crate::std::utils::get_camera_zoom_magnitude_per_unit_length(units);
ctx.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
crate::executor::SourceRange::default(),
kittycad::types::ModelingCmd::DefaultCameraLookAt {
center: kittycad::types::Point3D {
x: 0.0,
y: 0.0,
z: 0.0,
},
up: kittycad::types::Point3D {
x: 0.0,
y: 0.0,
z: 1.0,
},
vantage: kittycad::types::Point3D {
x: 0.0,
y: -x,
z: y,
},
sequence: None,
kittycad::types::ModelingCmd::ZoomToFit {
object_ids: Default::default(),
padding: 0.1,
},
)
.await

View File

@ -34,28 +34,13 @@ mod test_examples_my_func {
.await
.unwrap();
ctx.run(program, None).await.unwrap();
let (x, y) = crate::std::utils::get_camera_zoom_magnitude_per_unit_length(units);
ctx.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
crate::executor::SourceRange::default(),
kittycad::types::ModelingCmd::DefaultCameraLookAt {
center: kittycad::types::Point3D {
x: 0.0,
y: 0.0,
z: 0.0,
},
up: kittycad::types::Point3D {
x: 0.0,
y: 0.0,
z: 1.0,
},
vantage: kittycad::types::Point3D {
x: 0.0,
y: -x,
z: y,
},
sequence: None,
kittycad::types::ModelingCmd::ZoomToFit {
object_ids: Default::default(),
padding: 0.1,
},
)
.await
@ -126,28 +111,13 @@ mod test_examples_my_func {
.await
.unwrap();
ctx.run(program, None).await.unwrap();
let (x, y) = crate::std::utils::get_camera_zoom_magnitude_per_unit_length(units);
ctx.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
crate::executor::SourceRange::default(),
kittycad::types::ModelingCmd::DefaultCameraLookAt {
center: kittycad::types::Point3D {
x: 0.0,
y: 0.0,
z: 0.0,
},
up: kittycad::types::Point3D {
x: 0.0,
y: 0.0,
z: 1.0,
},
vantage: kittycad::types::Point3D {
x: 0.0,
y: -x,
z: y,
},
sequence: None,
kittycad::types::ModelingCmd::ZoomToFit {
object_ids: Default::default(),
padding: 0.1,
},
)
.await

View File

@ -35,28 +35,13 @@ mod test_examples_import {
.await
.unwrap();
ctx.run(program, None).await.unwrap();
let (x, y) = crate::std::utils::get_camera_zoom_magnitude_per_unit_length(units);
ctx.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
crate::executor::SourceRange::default(),
kittycad::types::ModelingCmd::DefaultCameraLookAt {
center: kittycad::types::Point3D {
x: 0.0,
y: 0.0,
z: 0.0,
},
up: kittycad::types::Point3D {
x: 0.0,
y: 0.0,
z: 1.0,
},
vantage: kittycad::types::Point3D {
x: 0.0,
y: -x,
z: y,
},
sequence: None,
kittycad::types::ModelingCmd::ZoomToFit {
object_ids: Default::default(),
padding: 0.1,
},
)
.await
@ -128,28 +113,13 @@ mod test_examples_import {
.await
.unwrap();
ctx.run(program, None).await.unwrap();
let (x, y) = crate::std::utils::get_camera_zoom_magnitude_per_unit_length(units);
ctx.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
crate::executor::SourceRange::default(),
kittycad::types::ModelingCmd::DefaultCameraLookAt {
center: kittycad::types::Point3D {
x: 0.0,
y: 0.0,
z: 0.0,
},
up: kittycad::types::Point3D {
x: 0.0,
y: 0.0,
z: 1.0,
},
vantage: kittycad::types::Point3D {
x: 0.0,
y: -x,
z: y,
},
sequence: None,
kittycad::types::ModelingCmd::ZoomToFit {
object_ids: Default::default(),
padding: 0.1,
},
)
.await

View File

@ -34,28 +34,13 @@ mod test_examples_line_to {
.await
.unwrap();
ctx.run(program, None).await.unwrap();
let (x, y) = crate::std::utils::get_camera_zoom_magnitude_per_unit_length(units);
ctx.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
crate::executor::SourceRange::default(),
kittycad::types::ModelingCmd::DefaultCameraLookAt {
center: kittycad::types::Point3D {
x: 0.0,
y: 0.0,
z: 0.0,
},
up: kittycad::types::Point3D {
x: 0.0,
y: 0.0,
z: 1.0,
},
vantage: kittycad::types::Point3D {
x: 0.0,
y: -x,
z: y,
},
sequence: None,
kittycad::types::ModelingCmd::ZoomToFit {
object_ids: Default::default(),
padding: 0.1,
},
)
.await
@ -126,28 +111,13 @@ mod test_examples_line_to {
.await
.unwrap();
ctx.run(program, None).await.unwrap();
let (x, y) = crate::std::utils::get_camera_zoom_magnitude_per_unit_length(units);
ctx.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
crate::executor::SourceRange::default(),
kittycad::types::ModelingCmd::DefaultCameraLookAt {
center: kittycad::types::Point3D {
x: 0.0,
y: 0.0,
z: 0.0,
},
up: kittycad::types::Point3D {
x: 0.0,
y: 0.0,
z: 1.0,
},
vantage: kittycad::types::Point3D {
x: 0.0,
y: -x,
z: y,
},
sequence: None,
kittycad::types::ModelingCmd::ZoomToFit {
object_ids: Default::default(),
padding: 0.1,
},
)
.await

View File

@ -33,28 +33,13 @@ mod test_examples_min {
.await
.unwrap();
ctx.run(program, None).await.unwrap();
let (x, y) = crate::std::utils::get_camera_zoom_magnitude_per_unit_length(units);
ctx.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
crate::executor::SourceRange::default(),
kittycad::types::ModelingCmd::DefaultCameraLookAt {
center: kittycad::types::Point3D {
x: 0.0,
y: 0.0,
z: 0.0,
},
up: kittycad::types::Point3D {
x: 0.0,
y: 0.0,
z: 1.0,
},
vantage: kittycad::types::Point3D {
x: 0.0,
y: -x,
z: y,
},
sequence: None,
kittycad::types::ModelingCmd::ZoomToFit {
object_ids: Default::default(),
padding: 0.1,
},
)
.await
@ -125,28 +110,13 @@ mod test_examples_min {
.await
.unwrap();
ctx.run(program, None).await.unwrap();
let (x, y) = crate::std::utils::get_camera_zoom_magnitude_per_unit_length(units);
ctx.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
crate::executor::SourceRange::default(),
kittycad::types::ModelingCmd::DefaultCameraLookAt {
center: kittycad::types::Point3D {
x: 0.0,
y: 0.0,
z: 0.0,
},
up: kittycad::types::Point3D {
x: 0.0,
y: 0.0,
z: 1.0,
},
vantage: kittycad::types::Point3D {
x: 0.0,
y: -x,
z: y,
},
sequence: None,
kittycad::types::ModelingCmd::ZoomToFit {
object_ids: Default::default(),
padding: 0.1,
},
)
.await

View File

@ -33,28 +33,13 @@ mod test_examples_show {
.await
.unwrap();
ctx.run(program, None).await.unwrap();
let (x, y) = crate::std::utils::get_camera_zoom_magnitude_per_unit_length(units);
ctx.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
crate::executor::SourceRange::default(),
kittycad::types::ModelingCmd::DefaultCameraLookAt {
center: kittycad::types::Point3D {
x: 0.0,
y: 0.0,
z: 0.0,
},
up: kittycad::types::Point3D {
x: 0.0,
y: 0.0,
z: 1.0,
},
vantage: kittycad::types::Point3D {
x: 0.0,
y: -x,
z: y,
},
sequence: None,
kittycad::types::ModelingCmd::ZoomToFit {
object_ids: Default::default(),
padding: 0.1,
},
)
.await

View File

@ -33,28 +33,13 @@ mod test_examples_import {
.await
.unwrap();
ctx.run(program, None).await.unwrap();
let (x, y) = crate::std::utils::get_camera_zoom_magnitude_per_unit_length(units);
ctx.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
crate::executor::SourceRange::default(),
kittycad::types::ModelingCmd::DefaultCameraLookAt {
center: kittycad::types::Point3D {
x: 0.0,
y: 0.0,
z: 0.0,
},
up: kittycad::types::Point3D {
x: 0.0,
y: 0.0,
z: 1.0,
},
vantage: kittycad::types::Point3D {
x: 0.0,
y: -x,
z: y,
},
sequence: None,
kittycad::types::ModelingCmd::ZoomToFit {
object_ids: Default::default(),
padding: 0.1,
},
)
.await

View File

@ -33,28 +33,13 @@ mod test_examples_import {
.await
.unwrap();
ctx.run(program, None).await.unwrap();
let (x, y) = crate::std::utils::get_camera_zoom_magnitude_per_unit_length(units);
ctx.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
crate::executor::SourceRange::default(),
kittycad::types::ModelingCmd::DefaultCameraLookAt {
center: kittycad::types::Point3D {
x: 0.0,
y: 0.0,
z: 0.0,
},
up: kittycad::types::Point3D {
x: 0.0,
y: 0.0,
z: 1.0,
},
vantage: kittycad::types::Point3D {
x: 0.0,
y: -x,
z: y,
},
sequence: None,
kittycad::types::ModelingCmd::ZoomToFit {
object_ids: Default::default(),
padding: 0.1,
},
)
.await

View File

@ -33,28 +33,13 @@ mod test_examples_import {
.await
.unwrap();
ctx.run(program, None).await.unwrap();
let (x, y) = crate::std::utils::get_camera_zoom_magnitude_per_unit_length(units);
ctx.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
crate::executor::SourceRange::default(),
kittycad::types::ModelingCmd::DefaultCameraLookAt {
center: kittycad::types::Point3D {
x: 0.0,
y: 0.0,
z: 0.0,
},
up: kittycad::types::Point3D {
x: 0.0,
y: 0.0,
z: 1.0,
},
vantage: kittycad::types::Point3D {
x: 0.0,
y: -x,
z: y,
},
sequence: None,
kittycad::types::ModelingCmd::ZoomToFit {
object_ids: Default::default(),
padding: 0.1,
},
)
.await

View File

@ -33,28 +33,13 @@ mod test_examples_show {
.await
.unwrap();
ctx.run(program, None).await.unwrap();
let (x, y) = crate::std::utils::get_camera_zoom_magnitude_per_unit_length(units);
ctx.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
crate::executor::SourceRange::default(),
kittycad::types::ModelingCmd::DefaultCameraLookAt {
center: kittycad::types::Point3D {
x: 0.0,
y: 0.0,
z: 0.0,
},
up: kittycad::types::Point3D {
x: 0.0,
y: 0.0,
z: 1.0,
},
vantage: kittycad::types::Point3D {
x: 0.0,
y: -x,
z: y,
},
sequence: None,
kittycad::types::ModelingCmd::ZoomToFit {
object_ids: Default::default(),
padding: 0.1,
},
)
.await

View File

@ -14,7 +14,7 @@ kittycad-execution-plan-traits = { workspace = true }
kittycad-execution-plan-macros = { workspace = true }
kittycad-modeling-cmds = { workspace = true }
kittycad-modeling-session = { workspace = true }
thiserror = "1.0.58"
thiserror = "1.0.59"
tokio = { version = "1.37.0", features = ["macros", "rt"] }
twenty-twenty = "0.7.0"
uuid = "1.8"

View File

@ -1,7 +1,7 @@
[package]
name = "kcl-lib"
description = "KittyCAD Language implementation and tools"
version = "0.1.47"
version = "0.1.50"
edition = "2021"
license = "MIT"
repository = "https://github.com/KittyCAD/modeling-app"
@ -19,7 +19,7 @@ chrono = "0.4.38"
clap = { version = "4.5.4", features = ["cargo", "derive", "env", "unicode"], optional = true }
dashmap = "5.5.3"
databake = { version = "0.1.7", features = ["derive"] }
derive-docs = { version = "0.1.14", path = "../derive-docs" }
derive-docs = { version = "0.1.16", path = "../derive-docs" }
form_urlencoded = "1.2.1"
futures = { version = "0.3.30" }
git_rev = "0.1.0"
@ -36,7 +36,7 @@ schemars = { version = "0.8.16", features = ["impl_json_schema", "url", "uuid1"]
serde = { version = "1.0.198", features = ["derive"] }
serde_json = "1.0.116"
sha2 = "0.10.8"
thiserror = "1.0.58"
thiserror = "1.0.59"
ts-rs = { version = "7.1.1", features = ["uuid-impl", "url-impl"] }
url = { version = "2.5.0", features = ["serde"] }
uuid = { version = "1.8.0", features = ["v4", "js", "serde"] }

View File

@ -1864,7 +1864,13 @@ impl ObjectExpression {
"{{ {} }}",
self.properties
.iter()
.map(|prop| { format!("{}: {}", prop.key.name, prop.value.recast(options, 0, false)) })
.map(|prop| {
format!(
"{}: {}",
prop.key.name,
prop.value.recast(options, indentation_level + 1, is_in_pipe)
)
})
.collect::<Vec<String>>()
.join(", ")
);
@ -1880,7 +1886,13 @@ impl ObjectExpression {
inner_indentation,
self.properties
.iter()
.map(|prop| { format!("{}: {}", prop.key.name, prop.value.recast(options, 0, false)) })
.map(|prop| {
format!(
"{}: {}",
prop.key.name,
prop.value.recast(options, indentation_level + 1, is_in_pipe)
)
})
.collect::<Vec<String>>()
.join(format!(",\n{}", inner_indentation).as_str()),
if is_in_pipe {
@ -2657,7 +2669,12 @@ impl PipeExpression {
let non_code_meta = self.non_code_meta.clone();
if let Some(non_code_meta_value) = non_code_meta.non_code_nodes.get(&index) {
for val in non_code_meta_value {
let formatted = val.format(&indentation).trim_end_matches('\n').to_string();
let formatted = if val.end == self.end {
let indentation = options.get_indentation(indentation_level);
val.format(&indentation).trim_end_matches('\n').to_string()
} else {
val.format(&indentation).trim_end_matches('\n').to_string()
};
if let NonCodeValue::BlockComment { .. } = val.value {
s += "\n";
s += &formatted;
@ -3256,6 +3273,244 @@ fn ghi = (x) => {
assert_eq!(recasted, r#""#);
}
#[test]
fn test_recast_large_file() {
let some_program_string = r#"// define constants
const radius = 6.0
const width = 144.0
const length = 83.0
const depth = 45.0
const thk = 5
const hole_diam = 5
// define a rectangular shape func
fn rectShape = (pos, w, l) => {
const rr = startSketchOn('xy')
|> startProfileAt([pos[0] - (w / 2), pos[1] - (l / 2)], %)
|> lineTo([pos[0] + w / 2, pos[1] - (l / 2)], %, "edge1")
|> lineTo([pos[0] + w / 2, pos[1] + l / 2], %, "edge2")
|> lineTo([pos[0] - (w / 2), pos[1] + l / 2], %, "edge3")
|> close(%, "edge4")
return rr
}
// build the body of the focusrite scarlett solo gen 4
// only used for visualization
const scarlett_body = rectShape([0, 0], width, length)
|> extrude(depth, %)
|> fillet({
radius: radius,
tags: [
getEdge("edge2", %),
getEdge("edge4", %),
getOppositeEdge("edge2", %),
getOppositeEdge("edge4", %)
]
}, %)
// build the bracket sketch around the body
fn bracketSketch = (w, d, t) => {
const s = startSketchOn({
plane: {
origin: { x: 0, y: length / 2 + thk, z: 0 },
x_axis: { x: 1, y: 0, z: 0 },
y_axis: { x: 0, y: 0, z: 1 },
z_axis: { x: 0, y: 1, z: 0 }
}
})
|> startProfileAt([-w / 2 - t, d + t], %)
|> lineTo([-w / 2 - t, -t], %, "edge1")
|> lineTo([w / 2 + t, -t], %, "edge2")
|> lineTo([w / 2 + t, d + t], %, "edge3")
|> lineTo([w / 2, d + t], %, "edge4")
|> lineTo([w / 2, 0], %, "edge5")
|> lineTo([-w / 2, 0], %, "edge6")
|> lineTo([-w / 2, d + t], %, "edge7")
|> close(%, "edge8")
return s
}
// build the body of the bracket
const bracket_body = bracketSketch(width, depth, thk)
|> extrude(length + 10, %)
|> fillet({
radius: radius,
tags: [
getNextAdjacentEdge("edge7", %),
getNextAdjacentEdge("edge2", %),
getNextAdjacentEdge("edge3", %),
getNextAdjacentEdge("edge6", %)
]
}, %)
// build the tabs of the mounting bracket (right side)
const tabs_r = startSketchOn({
plane: {
origin: { x: 0, y: 0, z: depth + thk },
x_axis: { x: 1, y: 0, z: 0 },
y_axis: { x: 0, y: 1, z: 0 },
z_axis: { x: 0, y: 0, z: 1 }
}
})
|> startProfileAt([width / 2 + thk, length / 2 + thk], %)
|> line([10, -5], %)
|> line([0, -10], %)
|> line([-10, -5], %)
|> close(%)
|> hole(circle([
width / 2 + thk + hole_diam,
length / 2 - hole_diam
], hole_diam / 2, %), %)
|> extrude(-thk, %)
|> patternLinear3d({
axis: [0, -1, 0],
repetitions: 1,
distance: length - 10
}, %)
// build the tabs of the mounting bracket (left side)
const tabs_l = startSketchOn({
plane: {
origin: { x: 0, y: 0, z: depth + thk },
x_axis: { x: 1, y: 0, z: 0 },
y_axis: { x: 0, y: 1, z: 0 },
z_axis: { x: 0, y: 0, z: 1 }
}
})
|> startProfileAt([-width / 2 - thk, length / 2 + thk], %)
|> line([-10, -5], %)
|> line([0, -10], %)
|> line([10, -5], %)
|> close(%)
|> hole(circle([
-width / 2 - thk - hole_diam,
length / 2 - hole_diam
], hole_diam / 2, %), %)
|> extrude(-thk, %)
|> patternLinear3d({
axis: [0, -1, 0],
repetitions: 1,
distance: length - 10
}, %)
"#;
let tokens = crate::token::lexer(some_program_string).unwrap();
let parser = crate::parser::Parser::new(tokens);
let program = parser.ast().unwrap();
println!("{:#?}", program);
let recasted = program.recast(&Default::default(), 0);
// Its VERY important this comes back with zero new lines.
assert_eq!(
recasted,
r#"// define constants
const radius = 6.0
const width = 144.0
const length = 83.0
const depth = 45.0
const thk = 5
const hole_diam = 5
// define a rectangular shape func
fn rectShape = (pos, w, l) => {
const rr = startSketchOn('xy')
|> startProfileAt([pos[0] - (w / 2), pos[1] - (l / 2)], %)
|> lineTo([pos[0] + w / 2, pos[1] - (l / 2)], %, "edge1")
|> lineTo([pos[0] + w / 2, pos[1] + l / 2], %, "edge2")
|> lineTo([pos[0] - (w / 2), pos[1] + l / 2], %, "edge3")
|> close(%, "edge4")
return rr
}
// build the body of the focusrite scarlett solo gen 4
// only used for visualization
const scarlett_body = rectShape([0, 0], width, length)
|> extrude(depth, %)
|> fillet({
radius: radius,
tags: [
getEdge("edge2", %),
getEdge("edge4", %),
getOppositeEdge("edge2", %),
getOppositeEdge("edge4", %)
]
}, %)
// build the bracket sketch around the body
fn bracketSketch = (w, d, t) => {
const s = startSketchOn({
plane: {
origin: { x: 0, y: length / 2 + thk, z: 0 },
x_axis: { x: 1, y: 0, z: 0 },
y_axis: { x: 0, y: 0, z: 1 },
z_axis: { x: 0, y: 1, z: 0 }
}
})
|> startProfileAt([-w / 2 - t, d + t], %)
|> lineTo([-w / 2 - t, -t], %, "edge1")
|> lineTo([w / 2 + t, -t], %, "edge2")
|> lineTo([w / 2 + t, d + t], %, "edge3")
|> lineTo([w / 2, d + t], %, "edge4")
|> lineTo([w / 2, 0], %, "edge5")
|> lineTo([-w / 2, 0], %, "edge6")
|> lineTo([-w / 2, d + t], %, "edge7")
|> close(%, "edge8")
return s
}
// build the body of the bracket
const bracket_body = bracketSketch(width, depth, thk)
|> extrude(length + 10, %)
|> fillet({
radius: radius,
tags: [
getNextAdjacentEdge("edge7", %),
getNextAdjacentEdge("edge2", %),
getNextAdjacentEdge("edge3", %),
getNextAdjacentEdge("edge6", %)
]
}, %)
// build the tabs of the mounting bracket (right side)
const tabs_r = startSketchOn({
plane: {
origin: { x: 0, y: 0, z: depth + thk },
x_axis: { x: 1, y: 0, z: 0 },
y_axis: { x: 0, y: 1, z: 0 },
z_axis: { x: 0, y: 0, z: 1 }
}
})
|> startProfileAt([width / 2 + thk, length / 2 + thk], %)
|> line([10, -5], %)
|> line([0, -10], %)
|> line([-10, -5], %)
|> close(%)
|> hole(circle([
width / 2 + thk + hole_diam,
length / 2 - hole_diam
], hole_diam / 2, %), %)
|> extrude(-thk, %)
|> patternLinear3d({
axis: [0, -1, 0],
repetitions: 1,
distance: length - 10
}, %)
// build the tabs of the mounting bracket (left side)
const tabs_l = startSketchOn({
plane: {
origin: { x: 0, y: 0, z: depth + thk },
x_axis: { x: 1, y: 0, z: 0 },
y_axis: { x: 0, y: 1, z: 0 },
z_axis: { x: 0, y: 0, z: 1 }
}
})
|> startProfileAt([-width / 2 - thk, length / 2 + thk], %)
|> line([-10, -5], %)
|> line([0, -10], %)
|> line([10, -5], %)
|> close(%)
|> hole(circle([
-width / 2 - thk - hole_diam,
length / 2 - hole_diam
], hole_diam / 2, %), %)
|> extrude(-thk, %)
|> patternLinear3d({
axis: [0, -1, 0],
repetitions: 1,
distance: length - 10
}, %)
"#
);
}
#[test]
fn test_recast_nested_var_declaration_in_fn_body() {
let some_program_string = r#"fn cube = (pos, scale) => {

View File

@ -62,7 +62,11 @@ impl StdLibFnArg {
}
pub fn get_autocomplete_snippet(&self, index: usize) -> Result<Option<(usize, String)>> {
if self.type_ == "SketchGroup" || self.type_ == "ExtrudeGroup" || self.type_ == "SketchSurface" {
if self.type_ == "SketchGroup"
|| self.type_ == "ExtrudeGroup"
|| self.type_ == "SketchSurface"
|| self.type_ == "SketchGroupSet"
{
return Ok(Some((index, format!("${{{}:{}}}", index, "%"))));
}
get_autocomplete_snippet_from_schema(&self.schema.clone(), index)
@ -319,7 +323,12 @@ pub fn get_type_string_from_schema(schema: &schemars::schema::Schema) -> Result<
if let Some(format) = &o.format {
if format == "uuid" {
return Ok((Primitive::Uuid.to_string(), false));
} else if format == "double" || format == "uint" || format == "int64" || format == "uint32" {
} else if format == "double"
|| format == "uint"
|| format == "int64"
|| format == "uint32"
|| format == "uint64"
{
return Ok((Primitive::Number.to_string(), false));
} else {
anyhow::bail!("unknown format: {}", format);
@ -456,7 +465,12 @@ pub fn get_autocomplete_snippet_from_schema(
if let Some(format) = &o.format {
if format == "uuid" {
return Ok(Some((index, format!(r#"${{{}:"tag_or_edge_fn"}}"#, index))));
} else if format == "double" || format == "uint" || format == "int64" || format == "uint32" {
} else if format == "double"
|| format == "uint"
|| format == "int64"
|| format == "uint32"
|| format == "uint64"
{
return Ok(Some((index, format!(r#"${{{}:3.14}}"#, index))));
} else {
anyhow::bail!("unknown format: {}", format);
@ -610,7 +624,12 @@ pub fn get_autocomplete_string_from_schema(schema: &schemars::schema::Schema) ->
if let Some(format) = &o.format {
if format == "uuid" {
return Ok(Primitive::Uuid.to_string());
} else if format == "double" || format == "uint" || format == "int64" || format == "uint32" {
} else if format == "double"
|| format == "uint"
|| format == "int64"
|| format == "uint32"
|| format == "uint64"
{
return Ok(Primitive::Number.to_string());
} else {
anyhow::bail!("unknown format: {}", format);
@ -736,10 +755,12 @@ pub fn completion_item_from_enum_schema(
anyhow::bail!("expected at least one enum value: {:#?}", o);
}
let label = enum_values[0].to_string();
let serde_json::Value::String(ref enum_value) = enum_values[0] else {
anyhow::bail!("expected string enum value: {:#?}", enum_values[0]);
};
Ok(CompletionItem {
label,
label: enum_value.to_string(),
label_details: None,
kind: Some(kind),
detail: Some(description.to_string()),

View File

@ -124,7 +124,7 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
let batched_requests = WebSocketRequest::ModelingCmdBatchReq {
requests,
batch_id: uuid::Uuid::new_v4(),
responses: Some(false),
responses: false,
};
let final_req = if self.batch().lock().unwrap().len() == 1 {
@ -365,6 +365,7 @@ pub fn is_cmd_with_return_values(cmd: &kittycad::types::ModelingCmd) -> bool {
| kittycad::types::ModelingCmd::EntityGetDistance { .. }
| kittycad::types::ModelingCmd::EntityLinearPattern { .. }
| kittycad::types::ModelingCmd::EntityCircularPattern { .. }
| kittycad::types::ModelingCmd::ZoomToFit { .. }
| kittycad::types::ModelingCmd::Solid3DGetExtrusionFaceInfo { .. }) = cmd
else {
return false;

View File

@ -191,6 +191,15 @@ pub enum SketchGroupSet {
SketchGroups(Vec<Box<SketchGroup>>),
}
/// A extrude group or a group of extrude groups.
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)]
#[serde(tag = "type", rename_all = "camelCase")]
pub enum ExtrudeGroupSet {
ExtrudeGroup(Box<ExtrudeGroup>),
ExtrudeGroups(Vec<Box<ExtrudeGroup>>),
}
/// Data for an imported geometry.
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)]

View File

@ -793,6 +793,56 @@ st"#
}
}
#[tokio::test(flavor = "multi_thread")]
async fn test_kcl_lsp_completions_const_raw() {
let server = kcl_lsp_server(false).await.unwrap();
// Send open file.
server
.did_open(tower_lsp::lsp_types::DidOpenTextDocumentParams {
text_document: tower_lsp::lsp_types::TextDocumentItem {
uri: "file:///test.kcl".try_into().unwrap(),
language_id: "kcl".to_string(),
version: 1,
text: r#"con"#.to_string(),
},
})
.await;
// Send completion request.
let completions = server
.completion(tower_lsp::lsp_types::CompletionParams {
text_document_position: tower_lsp::lsp_types::TextDocumentPositionParams {
text_document: tower_lsp::lsp_types::TextDocumentIdentifier {
uri: "file:///test.kcl".try_into().unwrap(),
},
position: tower_lsp::lsp_types::Position { line: 0, character: 2 },
},
context: None,
partial_result_params: Default::default(),
work_done_progress_params: Default::default(),
})
.await
.unwrap()
.unwrap();
// Check the completions.
if let tower_lsp::lsp_types::CompletionResponse::Array(completions) = completions {
assert!(completions.len() > 10);
// Find the one with label "const".
let const_completion = completions
.iter()
.find(|completion| completion.label == "const")
.unwrap();
assert_eq!(
const_completion.kind,
Some(tower_lsp::lsp_types::CompletionItemKind::KEYWORD)
);
} else {
panic!("Expected array of completions");
}
}
#[tokio::test(flavor = "multi_thread")]
async fn test_kcl_lsp_on_hover() {
let server = kcl_lsp_server(false).await.unwrap();

View File

@ -7,17 +7,23 @@ use uuid::Uuid;
use crate::{
errors::{KclError, KclErrorDetails},
executor::{ExtrudeGroup, ExtrudeSurface, ExtrudeTransform, GeoMeta, MemoryItem, Path, SketchGroup, SketchSurface},
executor::{
ExtrudeGroup, ExtrudeGroupSet, ExtrudeSurface, ExtrudeTransform, GeoMeta, MemoryItem, Path, SketchGroup,
SketchGroupSet, SketchSurface,
},
std::Args,
};
/// Extrudes by a given amount.
pub async fn extrude(args: Args) -> Result<MemoryItem, KclError> {
let (length, sketch_group) = args.get_number_sketch_group()?;
let (length, sketch_group_set) = args.get_number_sketch_group_set()?;
let result = inner_extrude(length, sketch_group, args).await?;
let result = inner_extrude(length, sketch_group_set, args).await?;
Ok(MemoryItem::ExtrudeGroup(result))
match result {
ExtrudeGroupSet::ExtrudeGroup(extrude_group) => Ok(MemoryItem::ExtrudeGroup(extrude_group)),
ExtrudeGroupSet::ExtrudeGroups(extrude_groups) => Ok(MemoryItem::ExtrudeGroups { value: extrude_groups }),
}
}
/// Extrudes by a given amount.
@ -34,10 +40,16 @@ pub async fn extrude(args: Args) -> Result<MemoryItem, KclError> {
#[stdlib {
name = "extrude"
}]
async fn inner_extrude(length: f64, sketch_group: Box<SketchGroup>, args: Args) -> Result<Box<ExtrudeGroup>, KclError> {
async fn inner_extrude(length: f64, sketch_group_set: SketchGroupSet, args: Args) -> Result<ExtrudeGroupSet, KclError> {
let id = uuid::Uuid::new_v4();
// Extrude the element.
// Extrude the element(s).
let sketch_groups = match sketch_group_set {
SketchGroupSet::SketchGroup(sketch_group) => vec![sketch_group],
SketchGroupSet::SketchGroups(sketch_groups) => sketch_groups,
};
let mut extrude_groups = Vec::new();
for sketch_group in sketch_groups.iter() {
args.send_modeling_cmd(
id,
kittycad::types::ModelingCmd::Extrude {
@ -47,8 +59,14 @@ async fn inner_extrude(length: f64, sketch_group: Box<SketchGroup>, args: Args)
},
)
.await?;
extrude_groups.push(do_post_extrude(sketch_group.clone(), length, id, args.clone()).await?);
}
do_post_extrude(sketch_group, length, id, args).await
if extrude_groups.len() == 1 {
Ok(ExtrudeGroupSet::ExtrudeGroup(extrude_groups.pop().unwrap()))
} else {
Ok(ExtrudeGroupSet::ExtrudeGroups(extrude_groups))
}
}
pub(crate) async fn do_post_extrude(

View File

@ -11,6 +11,7 @@ pub mod revolve;
pub mod segment;
pub mod shapes;
pub mod sketch;
pub mod types;
pub mod utils;
use std::collections::HashMap;
@ -628,6 +629,49 @@ impl Args {
Ok((data, sketch_group))
}
fn get_data_and_sketch_group_set<T: serde::de::DeserializeOwned>(&self) -> Result<(T, SketchGroupSet), KclError> {
let first_value = self
.args
.first()
.ok_or_else(|| {
KclError::Type(KclErrorDetails {
message: format!("Expected a struct as the first argument, found `{:?}`", self.args),
source_ranges: vec![self.source_range],
})
})?
.get_json_value()?;
let data: T = serde_json::from_value(first_value).map_err(|e| {
KclError::Type(KclErrorDetails {
message: format!("Failed to deserialize struct from JSON: {}", e),
source_ranges: vec![self.source_range],
})
})?;
let second_value = self.args.get(1).ok_or_else(|| {
KclError::Type(KclErrorDetails {
message: format!("Expected a SketchGroup as the second argument, found `{:?}`", self.args),
source_ranges: vec![self.source_range],
})
})?;
let sketch_set = if let MemoryItem::SketchGroup(sg) = second_value {
SketchGroupSet::SketchGroup(sg.clone())
} else if let MemoryItem::SketchGroups { value } = second_value {
SketchGroupSet::SketchGroups(value.clone())
} else {
return Err(KclError::Type(KclErrorDetails {
message: format!(
"Expected a SketchGroup or Vector of SketchGroups as the second argument, found `{:?}`",
self.args
),
source_ranges: vec![self.source_range],
}));
};
Ok((data, sketch_set))
}
fn get_data_and_sketch_group_and_tag<T: serde::de::DeserializeOwned>(
&self,
) -> Result<(T, Box<SketchGroup>, Option<String>), KclError> {
@ -823,7 +867,7 @@ impl Args {
Ok((segment_name, to_number, sketch_group))
}
fn get_number_sketch_group(&self) -> Result<(f64, Box<SketchGroup>), KclError> {
fn get_number_sketch_group_set(&self) -> Result<(f64, SketchGroupSet), KclError> {
// Iterate over our args, the first argument should be a number.
// The second argument should be a SketchGroup.
let first_value = self
@ -846,16 +890,21 @@ impl Args {
})
})?;
let sketch_group = if let MemoryItem::SketchGroup(sg) = second_value {
sg.clone()
let sketch_set = if let MemoryItem::SketchGroup(sg) = second_value {
SketchGroupSet::SketchGroup(sg.clone())
} else if let MemoryItem::SketchGroups { value } = second_value {
SketchGroupSet::SketchGroups(value.clone())
} else {
return Err(KclError::Type(KclErrorDetails {
message: format!("Expected a SketchGroup as the second argument, found `{:?}`", self.args),
message: format!(
"Expected a SketchGroup or Vector of SketchGroups as the second argument, found `{:?}`",
self.args
),
source_ranges: vec![self.source_range],
}));
};
Ok((number, sketch_group))
Ok((number, sketch_set))
}
fn get_path_name_extrude_group(&self) -> Result<(String, Box<ExtrudeGroup>), KclError> {

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