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_WS_MODELING_URL=wss://api.dev.zoo.dev/ws/modeling/commands
VITE_KC_API_BASE_URL=https://api.dev.zoo.dev VITE_KC_API_BASE_URL=https://api.dev.zoo.dev
VITE_KC_SITE_BASE_URL=https://dev.zoo.dev VITE_KC_SITE_BASE_URL=https://dev.zoo.dev
VITE_KC_WASM_OVERRIDE_URL=""
VITE_KC_SKIP_AUTH=false VITE_KC_SKIP_AUTH=false
VITE_KC_CONNECTION_TIMEOUT_MS=5000 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_WS_MODELING_URL=wss://api.zoo.dev/ws/modeling/commands
VITE_KC_API_BASE_URL=https://api.zoo.dev VITE_KC_API_BASE_URL=https://api.zoo.dev
VITE_KC_SITE_BASE_URL=https://zoo.dev VITE_KC_SITE_BASE_URL=https://zoo.dev
VITE_KC_WASM_OVERRIDE_URL=""
VITE_KC_SKIP_AUTH=false VITE_KC_SKIP_AUTH=false
VITE_KC_CONNECTION_TIMEOUT_MS=15000 VITE_KC_CONNECTION_TIMEOUT_MS=15000

View File

@ -14,9 +14,31 @@ permissions:
pull-requests: write pull-requests: write
jobs: 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: playwright-ubuntu:
timeout-minutes: 60 timeout-minutes: 60
runs-on: ubuntu-latest-8-cores runs-on: ubuntu-latest-8-cores
needs: check-wasm-lib-changes
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: actions/setup-node@v4 - uses: actions/setup-node@v4
@ -28,13 +50,19 @@ jobs:
run: yarn run: yarn
- name: Install Playwright Browsers - name: Install Playwright Browsers
run: yarn playwright install --with-deps 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 - name: Setup Rust
if: ${{ needs.check-wasm-lib-changes.outputs.url }} == ''
uses: dtolnay/rust-toolchain@stable uses: dtolnay/rust-toolchain@stable
- name: Cache wasm - name: Cache wasm
if: ${{ needs.check-wasm-lib-changes.outputs.url }} == ''
uses: Swatinem/rust-cache@v2 uses: Swatinem/rust-cache@v2
with: with:
workspaces: './src/wasm-lib' workspaces: './src/wasm-lib'
- name: build wasm - name: build wasm
if: ${{ needs.check-wasm-lib-changes.outputs.url }} == ''
run: yarn build:wasm run: yarn build:wasm
- name: build web - name: build web
run: yarn build:local run: yarn build:local
@ -44,6 +72,7 @@ jobs:
CI: true CI: true
token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }} token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
snapshottoken: ${{ secrets.KITTYCAD_API_TOKEN }} snapshottoken: ${{ secrets.KITTYCAD_API_TOKEN }}
WASM_OVERRIDE: ${{ steps.check-wasm-lib-changes.outputs.url }}
- uses: actions/upload-artifact@v3 - uses: actions/upload-artifact@v3
if: always() if: always()
with: with:
@ -79,6 +108,7 @@ jobs:
env: env:
CI: true CI: true
token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }} token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
WASM_OVERRIDE: ${{ steps.check-wasm-lib-changes.outputs.url }}
- uses: actions/upload-artifact@v3 - uses: actions/upload-artifact@v3
if: always() if: always()
with: with:
@ -89,6 +119,7 @@ jobs:
playwright-macos: playwright-macos:
timeout-minutes: 60 timeout-minutes: 60
runs-on: macos-14 runs-on: macos-14
needs: check-wasm-lib-changes
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: actions/setup-node@v4 - uses: actions/setup-node@v4
@ -100,12 +131,15 @@ jobs:
- name: Install Playwright Browsers - name: Install Playwright Browsers
run: yarn playwright install --with-deps run: yarn playwright install --with-deps
- name: Setup Rust - name: Setup Rust
if: needs.check-wasm-lib-changes.outputs.url == ''
uses: dtolnay/rust-toolchain@stable uses: dtolnay/rust-toolchain@stable
- name: Cache wasm - name: Cache wasm
if: needs.check-wasm-lib-changes.outputs.url == ''
uses: Swatinem/rust-cache@v2 uses: Swatinem/rust-cache@v2
with: with:
workspaces: './src/wasm-lib' workspaces: './src/wasm-lib'
- name: build wasm - name: build wasm
if: needs.check-wasm-lib-changes.outputs.url == ''
run: yarn build:wasm run: yarn build:wasm
- name: build web - name: build web
run: yarn build:local run: yarn build:local
@ -116,6 +150,7 @@ jobs:
env: env:
CI: true CI: true
token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }} token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
WASM_OVERRIDE: ${{ steps.check-wasm-lib-changes.outputs.url }}
- uses: actions/upload-artifact@v3 - uses: actions/upload-artifact@v3
if: always() if: always()
with: 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.press('Tab')
await page.keyboard.type('12') await page.keyboard.type('12')
await page.waitForTimeout(100)
await page.keyboard.press('Tab') await page.keyboard.press('Tab')
await page.waitForTimeout(100)
await page.keyboard.press('Tab') await page.keyboard.press('Tab')
await page.keyboard.press('Tab') await page.keyboard.press('Tab')
await page.keyboard.press('Enter') await page.keyboard.press('Enter')
@ -1033,6 +1035,7 @@ const part001 = startSketchOn('-XZ')
}) })
test('Can add multiple sketches', async ({ page }) => { test('Can add multiple sketches', async ({ page }) => {
test.skip(process.platform === 'darwin', 'Can add multiple sketches')
const u = getUtils(page) const u = getUtils(page)
await page.setViewportSize({ width: 1200, height: 500 }) await page.setViewportSize({ width: 1200, height: 500 })
const PUR = 400 / 37.5 //pixeltoUnitRatio 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, theme: Themes.Dark,
onboardingStatus: 'dismissed', onboardingStatus: 'dismissed',
projectDirectory: '', projectDirectory: '',
enableSSAO: false,
}, },
modeling: { modeling: {
defaultUnit: 'in', defaultUnit: 'in',

View File

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

View File

@ -18,7 +18,7 @@ export default defineConfig({
/* Retry on CI only */ /* Retry on CI only */
retries: process.env.CI ? 3 : 0, retries: process.env.CI ? 3 : 0,
/* Opt out of parallel tests on CI. */ /* 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 to use. See https://playwright.dev/docs/test-reporters */
reporter: 'html', reporter: 'html',
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ /* 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 */ /* Run your local dev server before starting the tests */
webServer: { webServer: {
command: 'yarn serve', command: 'VITE_KC_WASM_OVERRIDE_URL=$WASM_OVERRIDE yarn serve',
// url: 'http://127.0.0.1:3000', // url: 'http://127.0.0.1:3000',
reuseExistingServer: !process.env.CI, 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" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0bb0228f477c0900c880fd78c8759b95c7636dbd7842707f49e132378aa2acdc" checksum = "0bb0228f477c0900c880fd78c8759b95c7636dbd7842707f49e132378aa2acdc"
dependencies = [ dependencies = [
"heck", "heck 0.4.1",
"proc-macro-crate 2.0.2", "proc-macro-crate 2.0.2",
"proc-macro-error", "proc-macro-error",
"proc-macro2", "proc-macro2",
@ -1735,6 +1735,12 @@ version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
[[package]]
name = "heck"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]] [[package]]
name = "hermit-abi" name = "hermit-abi"
version = "0.2.6" version = "0.2.6"
@ -2199,9 +2205,9 @@ dependencies = [
[[package]] [[package]]
name = "kittycad" name = "kittycad"
version = "0.2.67" version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc460442c165c8e707b1154551cefd08938d10bb80c78940e10cd9869487c325" checksum = "ddc922f0da3abc22661bf49423c9bfcc02ce6ae92dae007ede6990874789545b"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-trait", "async-trait",
@ -4322,7 +4328,7 @@ version = "0.24.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59"
dependencies = [ dependencies = [
"heck", "heck 0.4.1",
"proc-macro2", "proc-macro2",
"quote", "quote",
"rustversion", "rustversion",
@ -4411,7 +4417,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5fa6fb9ee296c0dc2df41a656ca7948546d061958115ddb0bcaae43ad0d17d2" checksum = "e5fa6fb9ee296c0dc2df41a656ca7948546d061958115ddb0bcaae43ad0d17d2"
dependencies = [ dependencies = [
"cfg-expr", "cfg-expr",
"heck", "heck 0.4.1",
"pkg-config", "pkg-config",
"toml 0.7.8", "toml 0.7.8",
"version-compare", "version-compare",
@ -4508,7 +4514,7 @@ dependencies = [
"getrandom 0.2.14", "getrandom 0.2.14",
"glob", "glob",
"gtk", "gtk",
"heck", "heck 0.4.1",
"http 1.1.0", "http 1.1.0",
"jni", "jni",
"libc", "libc",
@ -4543,15 +4549,15 @@ dependencies = [
[[package]] [[package]]
name = "tauri-build" 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" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33de24aabe2b9c340d67005800cb6dd40aac5283126a42896fc8eec0b87cbe45" checksum = "abcf98a9b4527567c3e5ca9723431d121e001c2145651b3fa044d22b5e025a7e"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"cargo_toml", "cargo_toml",
"dirs-next", "dirs-next",
"glob", "glob",
"heck", "heck 0.5.0",
"json-patch", "json-patch",
"schemars", "schemars",
"semver", "semver",
@ -4596,7 +4602,7 @@ version = "2.0.0-beta.12"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b096f63f2724a1280ae0f5a34d0731de18ca18305e2ef6e5e9a39bb2710e8a85" checksum = "b096f63f2724a1280ae0f5a34d0731de18ca18305e2ef6e5e9a39bb2710e8a85"
dependencies = [ dependencies = [
"heck", "heck 0.4.1",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.48", "syn 2.0.48",
@ -4623,9 +4629,9 @@ dependencies = [
[[package]] [[package]]
name = "tauri-plugin-dialog" 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" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db4476c824a1488a52f4672d2b419a71fbf3dc97249013ef3c2c08fae2a23b71" checksum = "87caf6f2b704b0d27b4c64ef1fdd1f6ef97e2f5293216e230ad1efe61de54131"
dependencies = [ dependencies = [
"dunce", "dunce",
"log", "log",
@ -4641,9 +4647,9 @@ dependencies = [
[[package]] [[package]]
name = "tauri-plugin-fs" 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" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c138126392c350aa68554e3461529b02680062c9146ab7b41d3ef97a2deaf93b" checksum = "609f53d90f08808679ecdd81455d9a4d0053291b92780695569f7400fdba27d5"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"glob", "glob",
@ -4660,9 +4666,9 @@ dependencies = [
[[package]] [[package]]
name = "tauri-plugin-http" 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" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f27b2c90ed5473e1c068f523927fa0024212bc3a3f3a47c2a9c0b10b4b2e3ee4" checksum = "b7c32962a2e2141b3bc034e5c04f363635965e59435794b6bdcf97a027f0925a"
dependencies = [ dependencies = [
"data-url", "data-url",
"http 1.1.0", "http 1.1.0",
@ -4800,16 +4806,16 @@ dependencies = [
[[package]] [[package]]
name = "tauri-utils" 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" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "760ac613d7f0de95067bcbcbcea175fe1df88fc4ab59c7f0b2cc2d01dc16a199" checksum = "d4709765385f035338ecc330f3fba753b8ee283c659c235da9768949cdb25469"
dependencies = [ dependencies = [
"brotli", "brotli",
"cargo_metadata", "cargo_metadata",
"ctor", "ctor",
"dunce", "dunce",
"glob", "glob",
"heck", "heck 0.5.0",
"html5ever", "html5ever",
"infer", "infer",
"json-patch", "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 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[build-dependencies] [build-dependencies]
tauri-build = { version = "2.0.0-beta.12", features = [] } tauri-build = { version = "2.0.0-beta.13", features = [] }
[dependencies] [dependencies]
anyhow = "1" anyhow = "1"
kittycad = "0.2.67" kittycad = "0.3.0"
oauth2 = "4.4.2" oauth2 = "4.4.2"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0" serde_json = "1.0"
tauri = { version = "2.0.0-beta.15", features = [ "devtools", "unstable"] } tauri = { version = "2.0.0-beta.15", features = [ "devtools", "unstable"] }
tauri-plugin-dialog = { version = "2.0.0-beta.5" } tauri-plugin-dialog = { version = "2.0.0-beta.6" }
tauri-plugin-fs = { version = "2.0.0-beta.5" } tauri-plugin-fs = { version = "2.0.0-beta.6" }
tauri-plugin-http = { version = "2.0.0-beta.5" } tauri-plugin-http = { version = "2.0.0-beta.6" }
tauri-plugin-os = { version = "2.0.0-beta.2" } tauri-plugin-os = { version = "2.0.0-beta.2" }
tauri-plugin-process = { version = "2.0.0-beta.2" } tauri-plugin-process = { version = "2.0.0-beta.2" }
tauri-plugin-shell = { 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 { useKclContext } from 'lang/KclProvider'
import { CommandArgument } from 'lib/commandTypes' import { CommandArgument } from 'lib/commandTypes'
import { import {
ResolvedSelectionType,
canSubmitSelectionArg, canSubmitSelectionArg,
getSelectionType, getSelectionType,
getSelectionTypeDisplayText, getSelectionTypeDisplayText,
} from 'lib/selections' } from 'lib/selections'
import { modelingMachine } from 'machines/modelingMachine' 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 { useHotkeys } from 'react-hotkeys-hook'
import { StateFrom } from 'xstate' import { StateFrom } from 'xstate'
@ -30,13 +29,13 @@ function CommandBarSelectionInput({
const { commandBarState, commandBarSend } = useCommandsContext() const { commandBarState, commandBarSend } = useCommandsContext()
const [hasSubmitted, setHasSubmitted] = useState(false) const [hasSubmitted, setHasSubmitted] = useState(false)
const selection = useSelector(arg.machineActor, selectionSelector) const selection = useSelector(arg.machineActor, selectionSelector)
const [selectionsByType, setSelectionsByType] = useState< const initSelectionsByType = useCallback(() => {
'none' | ResolvedSelectionType[] const selectionRangeEnd = selection.codeBasedSelections[0]?.range[1]
>( return !selectionRangeEnd || selectionRangeEnd === code.length
selection.codeBasedSelections[0]?.range[1] === code.length
? 'none' ? 'none'
: getSelectionType(selection) : getSelectionType(selection)
) }, [selection, code])
const selectionsByType = initSelectionsByType()
const [canSubmitSelection, setCanSubmitSelection] = useState<boolean>( const [canSubmitSelection, setCanSubmitSelection] = useState<boolean>(
canSubmitSelectionArg(selectionsByType, arg) canSubmitSelectionArg(selectionsByType, arg)
) )
@ -51,17 +50,14 @@ function CommandBarSelectionInput({
inputRef.current?.focus() inputRef.current?.focus()
}, [selection, inputRef]) }, [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 // Fast-forward through this arg if it's marked as skippable
// and we have a valid selection already // and we have a valid selection already
useEffect(() => { useEffect(() => {
console.log('selection input effect', {
selectionsByType,
canSubmitSelection,
arg,
})
setCanSubmitSelection(canSubmitSelectionArg(selectionsByType, arg)) setCanSubmitSelection(canSubmitSelectionArg(selectionsByType, arg))
const argValue = commandBarState.context.argumentsToSubmit[arg.name] const argValue = commandBarState.context.argumentsToSubmit[arg.name]
if (canSubmitSelection && arg.skip && argValue === undefined) { if (canSubmitSelection && arg.skip && argValue === undefined) {

View File

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

View File

@ -16,7 +16,6 @@ import {
EditorView, EditorView,
dropCursor, dropCursor,
drawSelection, drawSelection,
ViewUpdate,
} from '@codemirror/view' } from '@codemirror/view'
import { import {
indentWithTab, indentWithTab,
@ -191,9 +190,6 @@ export const KclEditorPane = () => {
return extensions return extensions
}, [kclLSP, copilotLSP, textWrapping.current, cursorBlinking.current]) }, [kclLSP, copilotLSP, textWrapping.current, cursorBlinking.current])
let debounceTimer: ReturnType<typeof setTimeout> | null = null
const updateDelay = 100
return ( return (
<div <div
id="code-mirror-override" id="code-mirror-override"
@ -206,17 +202,6 @@ export const KclEditorPane = () => {
onCreateEditor={(_editorView) => onCreateEditor={(_editorView) =>
editorManager.setEditorView(_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} indentWithTab={false}
basicSetup={false} basicSetup={false}
/> />

View File

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

View File

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

View File

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

View File

@ -266,9 +266,9 @@ const mySk1 = startSketchAt([0, 0])
|> rx(45, %) |> rx(45, %)
/* /*
one more for good measure one more for good measure
*/ */
` `
const { ast } = code2ast(code) const { ast } = code2ast(code)
const recasted = recast(ast) const recasted = recast(ast)
@ -285,7 +285,7 @@ const mySk1 = startSketchAt([0, 0])
// and another with just white space between others below // and another with just white space between others below
|> ry(45, %) |> ry(45, %)
|> rx(45, %) |> rx(45, %)
/* one more for good measure */ /* one more for good measure */
`) `)
}) })
}) })

View File

@ -4,7 +4,7 @@ import { Models } from '@kittycad/lib'
import { exportSave } from 'lib/exportSave' import { exportSave } from 'lib/exportSave'
import { uuidv4 } from 'lib/utils' import { uuidv4 } from 'lib/utils'
import { getNodePathFromSourceRange } from 'lang/queryAst' 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' import { DefaultPlanes } from 'wasm-lib/kcl/bindings/DefaultPlanes'
let lastMessage = '' let lastMessage = ''
@ -941,6 +941,7 @@ export class EngineCommandManager {
settings = { settings = {
theme: Themes.Dark, theme: Themes.Dark,
highlightEdges: true, highlightEdges: true,
enableSSAO: true,
}, },
}: { }: {
setMediaStream: (stream: MediaStream) => void setMediaStream: (stream: MediaStream) => void
@ -953,6 +954,7 @@ export class EngineCommandManager {
settings?: { settings?: {
theme: Themes theme: Themes
highlightEdges: boolean highlightEdges: boolean
enableSSAO: boolean
} }
}) { }) {
this.makeDefaultPlanes = makeDefaultPlanes this.makeDefaultPlanes = makeDefaultPlanes
@ -969,7 +971,8 @@ export class EngineCommandManager {
return 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({ this.engineConnection = new EngineConnection({
engineCommandManager: this, engineCommandManager: this,
url, url,
@ -989,6 +992,18 @@ export class EngineCommandManager {
color: getThemeColorForEngine(settings.theme), 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 // Set the edge lines visibility
this.sendSceneCommand({ this.sendSceneCommand({
type: 'modeling_cmd_req', type: 'modeling_cmd_req',
@ -1326,6 +1341,17 @@ export class EngineCommandManager {
this.lastArtifactMap = this.artifactMap this.lastArtifactMap = this.artifactMap
this.artifactMap = {} this.artifactMap = {}
await this.initPlanes() 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>({ subscribeTo<T extends ModelTypes>({
event, event,

View File

@ -102,7 +102,7 @@ describe('testing changeSketchArguments', () => {
|> startProfileAt([0, 0], %) |> startProfileAt([0, 0], %)
|> ${line} |> ${line}
|> lineTo([0.46, -5.82], %) |> lineTo([0.46, -5.82], %)
// |> rx(45, %) // |> rx(45, %)
` `
const code = genCode(lineToChange) const code = genCode(lineToChange)
const expectedCode = genCode(lineAfterChange) const expectedCode = genCode(lineAfterChange)

View File

@ -25,7 +25,7 @@ import { AppInfo } from 'wasm-lib/kcl/bindings/AppInfo'
import { CoreDumpManager } from 'lib/coredump' import { CoreDumpManager } from 'lib/coredump'
import openWindow from 'lib/openWindow' import openWindow from 'lib/openWindow'
import { DefaultPlanes } from 'wasm-lib/kcl/bindings/DefaultPlanes' 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 { Program } from '../wasm-lib/kcl/bindings/Program'
export type { Value } from '../wasm-lib/kcl/bindings/Value' export type { Value } from '../wasm-lib/kcl/bindings/Value'
@ -76,18 +76,19 @@ export type { MemoryItem } from '../wasm-lib/kcl/bindings/MemoryItem'
export type { ExtrudeSurface } from '../wasm-lib/kcl/bindings/ExtrudeSurface' export type { ExtrudeSurface } from '../wasm-lib/kcl/bindings/ExtrudeSurface'
export const wasmUrl = () => { export const wasmUrl = () => {
const baseUrl = const baseUrl = VITE_KC_WASM_OVERRIDE_URL
typeof window === 'undefined' ? VITE_KC_WASM_OVERRIDE_URL
? 'http://127.0.0.1:3000' : typeof window === 'undefined'
: window.location.origin.includes('tauri://localhost') ? 'http://127.0.0.1:3000'
? 'tauri://localhost' // custom protocol for macOS : window.location.origin.includes('tauri://localhost')
: window.location.origin.includes('tauri.localhost') ? 'tauri://localhost' // custom protocol for macOS
? 'http://tauri.localhost' // fallback for Windows : window.location.origin.includes('tauri.localhost')
: window.location.origin.includes('localhost') ? 'http://tauri.localhost' // fallback for Windows
? 'http://localhost:3000' : window.location.origin.includes('localhost')
: window.location.origin && window.location.origin !== 'null' ? 'http://localhost:3000'
? window.location.origin : window.location.origin && window.location.origin !== 'null'
: 'http://localhost:3000' ? window.location.origin
: 'http://localhost:3000'
const fullUrl = baseUrl + '/wasm_lib_bg.wasm' const fullUrl = baseUrl + '/wasm_lib_bg.wasm'
console.log(`Full URL for WASM: ${fullUrl}`) console.log(`Full URL for WASM: ${fullUrl}`)

View File

@ -420,7 +420,13 @@ export function getSelectionTypeDisplayText(
const selectionsByType = getSelectionType(selection) const selectionsByType = getSelectionType(selection)
return (selectionsByType as Exclude<typeof selectionsByType, 'none'>) 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(', ') .join(', ')
} }

View File

@ -156,6 +156,13 @@ export function createSettings() {
</div> </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>({ onboardingStatus: new Setting<string>({
defaultValue: '', defaultValue: '',
validate: (v) => typeof v === 'string', 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 * The engine takes RGBA values from 0-1
* So we convert from the conventional 0-255 found in Figma * 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 } * @returns { r: number, g: number, b: number, a: number }
*/ */
export function getThemeColorForEngine(theme: Themes) { export function getThemeColorForEngine(theme: Themes) {
const resolvedTheme = theme === Themes.System ? getSystemTheme() : theme const resolvedTheme = getResolvedTheme(theme)
const dark = 28 / 255 const dark = 28 / 255
const light = 249 / 255 const light = 249 / 255
return resolvedTheme === Themes.Dark return resolvedTheme === Themes.Dark

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -788,17 +788,14 @@ fn generate_code_block_test(
ctx.run(program, None).await.unwrap(); 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 ctx.engine
.send_modeling_cmd( .send_modeling_cmd(
uuid::Uuid::new_v4(), uuid::Uuid::new_v4(),
crate::executor::SourceRange::default(), crate::executor::SourceRange::default(),
kittycad::types::ModelingCmd::DefaultCameraLookAt { kittycad::types::ModelingCmd::ZoomToFit {
center: kittycad::types::Point3D { x: 0.0, y: 0.0, z: 0.0 }, object_ids: Default::default(),
up: kittycad::types::Point3D { x: 0.0, y: 0.0, z: 1.0 }, padding: 0.1,
vantage: kittycad::types::Point3D { x: 0.0, y: -x, z: y },
sequence: None,
}, },
) )
.await.unwrap(); .await.unwrap();

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1864,7 +1864,13 @@ impl ObjectExpression {
"{{ {} }}", "{{ {} }}",
self.properties self.properties
.iter() .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>>() .collect::<Vec<String>>()
.join(", ") .join(", ")
); );
@ -1880,7 +1886,13 @@ impl ObjectExpression {
inner_indentation, inner_indentation,
self.properties self.properties
.iter() .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>>() .collect::<Vec<String>>()
.join(format!(",\n{}", inner_indentation).as_str()), .join(format!(",\n{}", inner_indentation).as_str()),
if is_in_pipe { if is_in_pipe {
@ -2657,7 +2669,12 @@ impl PipeExpression {
let non_code_meta = self.non_code_meta.clone(); let non_code_meta = self.non_code_meta.clone();
if let Some(non_code_meta_value) = non_code_meta.non_code_nodes.get(&index) { if let Some(non_code_meta_value) = non_code_meta.non_code_nodes.get(&index) {
for val in non_code_meta_value { 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 { if let NonCodeValue::BlockComment { .. } = val.value {
s += "\n"; s += "\n";
s += &formatted; s += &formatted;
@ -3256,6 +3273,244 @@ fn ghi = (x) => {
assert_eq!(recasted, r#""#); 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] #[test]
fn test_recast_nested_var_declaration_in_fn_body() { fn test_recast_nested_var_declaration_in_fn_body() {
let some_program_string = r#"fn cube = (pos, scale) => { let some_program_string = r#"fn cube = (pos, scale) => {
@ -3543,7 +3798,7 @@ const mySk1 = startSketchOn('XY')
// and another with just white space between others below // and another with just white space between others below
|> ry(45, %) |> ry(45, %)
|> rx(45, %) |> rx(45, %)
// one more for good measure // one more for good measure
"# "#
); );
} }

View File

@ -62,7 +62,11 @@ impl StdLibFnArg {
} }
pub fn get_autocomplete_snippet(&self, index: usize) -> Result<Option<(usize, String)>> { 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, "%")))); return Ok(Some((index, format!("${{{}:{}}}", index, "%"))));
} }
get_autocomplete_snippet_from_schema(&self.schema.clone(), 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 let Some(format) = &o.format {
if format == "uuid" { if format == "uuid" {
return Ok((Primitive::Uuid.to_string(), false)); 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)); return Ok((Primitive::Number.to_string(), false));
} else { } else {
anyhow::bail!("unknown format: {}", format); anyhow::bail!("unknown format: {}", format);
@ -456,7 +465,12 @@ pub fn get_autocomplete_snippet_from_schema(
if let Some(format) = &o.format { if let Some(format) = &o.format {
if format == "uuid" { if format == "uuid" {
return Ok(Some((index, format!(r#"${{{}:"tag_or_edge_fn"}}"#, index)))); 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)))); return Ok(Some((index, format!(r#"${{{}:3.14}}"#, index))));
} else { } else {
anyhow::bail!("unknown format: {}", format); 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 let Some(format) = &o.format {
if format == "uuid" { if format == "uuid" {
return Ok(Primitive::Uuid.to_string()); 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()); return Ok(Primitive::Number.to_string());
} else { } else {
anyhow::bail!("unknown format: {}", format); 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); 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 { Ok(CompletionItem {
label, label: enum_value.to_string(),
label_details: None, label_details: None,
kind: Some(kind), kind: Some(kind),
detail: Some(description.to_string()), 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 { let batched_requests = WebSocketRequest::ModelingCmdBatchReq {
requests, requests,
batch_id: uuid::Uuid::new_v4(), batch_id: uuid::Uuid::new_v4(),
responses: Some(false), responses: false,
}; };
let final_req = if self.batch().lock().unwrap().len() == 1 { 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::EntityGetDistance { .. }
| kittycad::types::ModelingCmd::EntityLinearPattern { .. } | kittycad::types::ModelingCmd::EntityLinearPattern { .. }
| kittycad::types::ModelingCmd::EntityCircularPattern { .. } | kittycad::types::ModelingCmd::EntityCircularPattern { .. }
| kittycad::types::ModelingCmd::ZoomToFit { .. }
| kittycad::types::ModelingCmd::Solid3DGetExtrusionFaceInfo { .. }) = cmd | kittycad::types::ModelingCmd::Solid3DGetExtrusionFaceInfo { .. }) = cmd
else { else {
return false; return false;

View File

@ -191,6 +191,15 @@ pub enum SketchGroupSet {
SketchGroups(Vec<Box<SketchGroup>>), 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. /// Data for an imported geometry.
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)] #[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")] #[tokio::test(flavor = "multi_thread")]
async fn test_kcl_lsp_on_hover() { async fn test_kcl_lsp_on_hover() {
let server = kcl_lsp_server(false).await.unwrap(); let server = kcl_lsp_server(false).await.unwrap();

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