Compare commits

...

7 Commits

Author SHA1 Message Date
10c51896be Merge branch 'main' into safe-reset-scene 2025-04-02 15:20:24 -07:00
96e12b5aba update transform samples with mesh moving (#6080)
* update transform samples with mesh moving

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

* chjanges

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

* updates

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

* update docs

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

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2025-04-02 15:11:06 -07:00
bec3ba71cd More circular deps fixed (#6121)
* 23

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

* 22

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

* 21

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

* fix known

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

* fixes

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

* cleanup

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

* cleanup

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

* 20

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

* 11

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

* 11

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>
2025-04-02 15:10:57 -07:00
c6766d2a73 bump kcl and friends (#6122)
Signed-off-by: Jess Frazelle <github@jessfraz.com>
2025-04-02 14:28:32 -07:00
34f05b3cf2 updates
Signed-off-by: Jess Frazelle <github@jessfraz.com>
2025-04-02 09:57:06 -07:00
3c89ac8421 Update src/components/CommandBar/CommandBarSelectionInput.tsx
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-04-02 09:57:06 -07:00
d3f788050c safe reset scene w cache
Signed-off-by: Jess Frazelle <github@jessfraz.com>

fmt

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

get the outcome data back out

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

fmt

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

updates

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

updates

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

remove deferrer

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

move the artifact graph to kclmanager, dont defer

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

updates

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

cleanup xstate stuffs

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

updates

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

updates

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

updates

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

updates

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

fmt

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

updates

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

updates

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

fixes

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

fixes

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

fix tsc

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2025-04-02 09:57:04 -07:00
53 changed files with 458 additions and 380 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -266059,7 +266059,7 @@
"// Rotate a pipe with roll, pitch, and yaw.\n\n// Create a path for the sweep.\nsweepPath = startSketchOn(XZ)\n |> startProfileAt([0.05, 0.05], %)\n |> line(end = [0, 7])\n |> tangentialArc({ offset = 90, radius = 5 }, %)\n |> line(end = [-3, 0])\n |> tangentialArc({ offset = -90, radius = 5 }, %)\n |> line(end = [0, 7])\n\n// Create a hole for the pipe.\npipeHole = startSketchOn(XY)\n |> circle(center = [0, 0], radius = 1.5)\n\nsweepSketch = startSketchOn(XY)\n |> circle(center = [0, 0], radius = 2)\n |> hole(pipeHole, %)\n |> sweep(path = sweepPath)\n |> rotate(roll = 10, pitch = 10, yaw = 90)",
"// Rotate a pipe with just roll.\n\n// Create a path for the sweep.\nsweepPath = startSketchOn(XZ)\n |> startProfileAt([0.05, 0.05], %)\n |> line(end = [0, 7])\n |> tangentialArc({ offset = 90, radius = 5 }, %)\n |> line(end = [-3, 0])\n |> tangentialArc({ offset = -90, radius = 5 }, %)\n |> line(end = [0, 7])\n\n// Create a hole for the pipe.\npipeHole = startSketchOn(XY)\n |> circle(center = [0, 0], radius = 1.5)\n\nsweepSketch = startSketchOn(XY)\n |> circle(center = [0, 0], radius = 2)\n |> hole(pipeHole, %)\n |> sweep(path = sweepPath)\n |> rotate(roll = 10)",
"// Rotate a pipe about an axis with an angle.\n\n// Create a path for the sweep.\nsweepPath = startSketchOn(XZ)\n |> startProfileAt([0.05, 0.05], %)\n |> line(end = [0, 7])\n |> tangentialArc({ offset = 90, radius = 5 }, %)\n |> line(end = [-3, 0])\n |> tangentialArc({ offset = -90, radius = 5 }, %)\n |> line(end = [0, 7])\n\n// Create a hole for the pipe.\npipeHole = startSketchOn(XY)\n |> circle(center = [0, 0], radius = 1.5)\n\nsweepSketch = startSketchOn(XY)\n |> circle(center = [0, 0], radius = 2)\n |> hole(pipeHole, %)\n |> sweep(path = sweepPath)\n |> rotate(axis = [0, 0, 1.0], angle = 90)",
"// Rotate an imported model.\n\n\nimport \"tests/inputs/cube.sldprt\" as cube\n\ncube\n |> rotate(axis = [0, 0, 1.0], angle = 90)",
"// Rotate an imported model.\n\n\nimport \"tests/inputs/cube.sldprt\" as cube\n\ncube\n |> rotate(axis = [0, 0, 1.0], angle = 9)",
"// Sweep two sketches along the same path.\n\n\nsketch001 = startSketchOn(XY)\nrectangleSketch = startProfileAt([-200, 23.86], sketch001)\n |> angledLine([0, 73.47], %, $rectangleSegmentA001)\n |> angledLine([\n segAng(rectangleSegmentA001) - 90,\n 50.61\n ], %)\n |> angledLine([\n segAng(rectangleSegmentA001),\n -segLen(rectangleSegmentA001)\n ], %)\n |> line(endAbsolute = [profileStartX(%), profileStartY(%)])\n |> close()\n\ncircleSketch = circle(sketch001, center = [200, -30.29], radius = 32.63)\n\nsketch002 = startSketchOn(YZ)\nsweepPath = startProfileAt([0, 0], sketch002)\n |> yLine(length = 231.81)\n |> tangentialArc({ radius = 80, offset = -90 }, %)\n |> xLine(length = 384.93)\n\nparts = sweep([rectangleSketch, circleSketch], path = sweepPath)\n\n// Rotate the sweeps.\nrotate(parts, axis = [0, 0, 1.0], angle = 90)",
"// Translate and rotate a sketch to create a loft.\nsketch001 = startSketchOn(XY)\n\nfn square() {\n return startProfileAt([-10, 10], sketch001)\n |> xLine(length = 20)\n |> yLine(length = -20)\n |> xLine(length = -20)\n |> line(endAbsolute = [profileStartX(%), profileStartY(%)])\n |> close()\n}\n\nprofile001 = square()\n\nprofile002 = square()\n |> translate(x = 0, y = 0, z = 20)\n |> rotate(axis = [0, 0, 1.0], angle = 45)\n\nloft([profile001, profile002])"
]
@ -275841,7 +275841,7 @@
"deprecated": false,
"examples": [
"// Scale a pipe.\n\n// Create a path for the sweep.\nsweepPath = startSketchOn(XZ)\n |> startProfileAt([0.05, 0.05], %)\n |> line(end = [0, 7])\n |> tangentialArc({ offset = 90, radius = 5 }, %)\n |> line(end = [-3, 0])\n |> tangentialArc({ offset = -90, radius = 5 }, %)\n |> line(end = [0, 7])\n\n// Create a hole for the pipe.\npipeHole = startSketchOn(XY)\n |> circle(center = [0, 0], radius = 1.5)\n\nsweepSketch = startSketchOn(XY)\n |> circle(center = [0, 0], radius = 2)\n |> hole(pipeHole, %)\n |> sweep(path = sweepPath)\n |> scale(z = 2.5)",
"// Scale an imported model.\n\n\nimport \"tests/inputs/cube.sldprt\" as cube\n\ncube\n |> scale(z = 2.5)",
"// Scale an imported model.\n\n\nimport \"tests/inputs/cube.sldprt\" as cube\n\ncube\n |> scale(y = 2.5)",
"// Sweep two sketches along the same path.\n\n\nsketch001 = startSketchOn(XY)\nrectangleSketch = startProfileAt([-200, 23.86], sketch001)\n |> angledLine([0, 73.47], %, $rectangleSegmentA001)\n |> angledLine([\n segAng(rectangleSegmentA001) - 90,\n 50.61\n ], %)\n |> angledLine([\n segAng(rectangleSegmentA001),\n -segLen(rectangleSegmentA001)\n ], %)\n |> line(endAbsolute = [profileStartX(%), profileStartY(%)])\n |> close()\n\ncircleSketch = circle(sketch001, center = [200, -30.29], radius = 32.63)\n\nsketch002 = startSketchOn(YZ)\nsweepPath = startProfileAt([0, 0], sketch002)\n |> yLine(length = 231.81)\n |> tangentialArc({ radius = 80, offset = -90 }, %)\n |> xLine(length = 384.93)\n\nparts = sweep([rectangleSketch, circleSketch], path = sweepPath)\n\n// Scale the sweep.\nscale(parts, z = 0.5)"
]
},
@ -334111,7 +334111,7 @@
"deprecated": false,
"examples": [
"// Move a pipe.\n\n// Create a path for the sweep.\nsweepPath = startSketchOn(XZ)\n |> startProfileAt([0.05, 0.05], %)\n |> line(end = [0, 7])\n |> tangentialArc({ offset = 90, radius = 5 }, %)\n |> line(end = [-3, 0])\n |> tangentialArc({ offset = -90, radius = 5 }, %)\n |> line(end = [0, 7])\n\n// Create a hole for the pipe.\npipeHole = startSketchOn(XY)\n |> circle(center = [0, 0], radius = 1.5)\n\nsweepSketch = startSketchOn(XY)\n |> circle(center = [0, 0], radius = 2)\n |> hole(pipeHole, %)\n |> sweep(path = sweepPath)\n |> translate(x = 1.0, y = 1.0, z = 2.5)",
"// Move an imported model.\n\n\nimport \"tests/inputs/cube.sldprt\" as cube\n\ncube\n |> translate(x = 1.0, y = 1.0, z = 2.5)",
"// Move an imported model.\n\n\nimport \"tests/inputs/cube.sldprt\" as cube\n\n// Circle so you actually see the move.\nstartSketchOn(XY)\n |> circle(center = [-10, -10], radius = 10)\n |> extrude(length = 10)\n\ncube\n |> translate(x = 10.0, y = 10.0, z = 2.5)",
"// Sweep two sketches along the same path.\n\n\nsketch001 = startSketchOn(XY)\nrectangleSketch = startProfileAt([-200, 23.86], sketch001)\n |> angledLine([0, 73.47], %, $rectangleSegmentA001)\n |> angledLine([\n segAng(rectangleSegmentA001) - 90,\n 50.61\n ], %)\n |> angledLine([\n segAng(rectangleSegmentA001),\n -segLen(rectangleSegmentA001)\n ], %)\n |> line(endAbsolute = [profileStartX(%), profileStartY(%)])\n |> close()\n\ncircleSketch = circle(sketch001, center = [200, -30.29], radius = 32.63)\n\nsketch002 = startSketchOn(YZ)\nsweepPath = startProfileAt([0, 0], sketch002)\n |> yLine(length = 231.81)\n |> tangentialArc({ radius = 80, offset = -90 }, %)\n |> xLine(length = 384.93)\n\nparts = sweep([rectangleSketch, circleSketch], path = sweepPath)\n\n// Move the sweeps.\ntranslate(\n parts,\n x = 1.0,\n y = 1.0,\n z = 2.5,\n)",
"// Move a sketch.\n\n\nfn square(length) {\n l = length / 2\n p0 = [-l, -l]\n p1 = [-l, l]\n p2 = [l, l]\n p3 = [l, -l]\n\n return startSketchOn(XY)\n |> startProfileAt(p0, %)\n |> line(endAbsolute = p1)\n |> line(endAbsolute = p2)\n |> line(endAbsolute = p3)\n |> close()\n}\n\nsquare(10)\n |> translate(x = 5, y = 5)\n |> extrude(length = 10)",
"// Translate and rotate a sketch to create a loft.\nsketch001 = startSketchOn(XY)\n\nfn square() {\n return startProfileAt([-10, 10], sketch001)\n |> xLine(length = 20)\n |> yLine(length = -20)\n |> xLine(length = -20)\n |> line(endAbsolute = [profileStartX(%), profileStartY(%)])\n |> close()\n}\n\nprofile001 = square()\n\nprofile002 = square()\n |> translate(z = 20)\n |> rotate(axis = [0, 0, 1.0], angle = 45)\n\nloft([profile001, profile002])"

File diff suppressed because one or more lines are too long

View File

@ -1 +1,13 @@
$ dpdm --no-warning --no-tree -T --skip-dynamic-imports=circular src/index.tsx• Circular Dependencies 01) src/lang/std/sketch.ts -> src/lang/modifyAst.ts -> src/lang/modifyAst/addEdgeTreatment.ts 02) src/lang/std/sketch.ts -> src/lang/modifyAst.ts 03) src/lang/std/sketch.ts -> src/lang/modifyAst.ts -> src/lang/std/sketchcombos.ts 04) src/clientSideScene/CameraControls.ts -> src/clientSideScene/sceneInfra.ts 05) src/lib/singletons.ts -> src/editor/manager.ts -> src/lib/selections.ts 06) src/lib/singletons.ts -> src/editor/manager.ts 07) src/lib/singletons.ts -> src/lang/KclSingleton.ts 08) src/lib/singletons.ts -> src/lang/codeManager.ts 09) src/lib/singletons.ts -> src/clientSideScene/sceneEntities.ts -> src/clientSideScene/segments.ts -> src/components/Toolbar/angleLengthInfo.ts 10) src/lib/singletons.ts -> src/clientSideScene/sceneEntities.ts -> src/clientSideScene/segments.ts -> src/machines/commandBarMachine.ts -> src/lib/commandBarConfigs/authCommandConfig.ts -> src/machines/appMachine.ts -> src/machines/settingsMachine.ts -> src/lib/commandBarConfigs/settingsCommandConfig.ts -> src/lib/createMachineCommand.ts -> src/routes/Settings.tsx -> src/components/Settings/AllSettingsFields.tsx -> src/components/LspProvider.tsx -> src/editor/plugins/lsp/copilot/index.ts 11) src/lib/singletons.ts -> src/clientSideScene/sceneEntities.ts -> src/clientSideScene/segments.ts -> src/machines/commandBarMachine.ts -> src/lib/commandBarConfigs/authCommandConfig.ts -> src/machines/appMachine.ts -> src/machines/settingsMachine.ts -> src/lib/commandBarConfigs/settingsCommandConfig.ts -> src/lib/createMachineCommand.ts -> src/routes/Settings.tsx -> src/components/Settings/AllSettingsFields.tsx -> src/components/LspProvider.tsx -> src/editor/plugins/lsp/kcl/language.ts -> src/editor/plugins/lsp/kcl/index.ts 12) src/lib/singletons.ts -> src/clientSideScene/sceneEntities.ts -> src/clientSideScene/segments.ts -> src/machines/commandBarMachine.ts -> src/lib/commandBarConfigs/authCommandConfig.ts -> src/machines/appMachine.ts -> src/machines/settingsMachine.ts -> src/lib/commandBarConfigs/settingsCommandConfig.ts -> src/lib/createMachineCommand.ts -> src/routes/Settings.tsx -> src/components/Settings/AllSettingsFields.tsx -> src/components/LspProvider.tsx 13) src/machines/appMachine.ts -> src/machines/settingsMachine.ts -> src/lib/commandBarConfigs/settingsCommandConfig.ts -> src/lib/createMachineCommand.ts -> src/routes/Settings.tsx -> src/components/Settings/AllSettingsFields.tsx -> src/components/LspProvider.tsx 14) src/machines/appMachine.ts -> src/machines/settingsMachine.ts -> src/lib/commandBarConfigs/settingsCommandConfig.ts -> src/lib/createMachineCommand.ts -> src/routes/Settings.tsx -> src/components/Settings/AllSettingsFields.tsx -> src/components/Settings/SettingsFieldInput.tsx 15) src/machines/appMachine.ts -> src/machines/settingsMachine.ts -> src/lib/commandBarConfigs/settingsCommandConfig.ts -> src/lib/createMachineCommand.ts -> src/routes/Settings.tsx -> src/components/Settings/AllSettingsFields.tsx 16) src/routes/Settings.tsx -> src/components/Settings/AllSettingsFields.tsx 17) src/machines/appMachine.ts -> src/machines/settingsMachine.ts -> src/lib/commandBarConfigs/settingsCommandConfig.ts -> src/lib/createMachineCommand.ts -> src/routes/Settings.tsx -> src/components/Settings/SettingsSearchBar.tsx 18) src/machines/appMachine.ts -> src/machines/settingsMachine.ts -> src/lib/commandBarConfigs/settingsCommandConfig.ts -> src/lib/createMachineCommand.ts -> src/routes/Settings.tsx -> src/components/Settings/SettingsSectionsList.tsx 19) src/lib/singletons.ts -> src/clientSideScene/sceneEntities.ts -> src/clientSideScene/segments.ts -> src/machines/commandBarMachine.ts -> src/lib/commandBarConfigs/authCommandConfig.ts -> src/machines/appMachine.ts -> src/machines/settingsMachine.ts 20) src/machines/commandBarMachine.ts -> src/lib/commandBarConfigs/authCommandConfig.ts -> src/machines/appMachine.ts -> src/machines/settingsMachine.ts 21) src/hooks/useModelingContext.ts -> src/components/ModelingMachineProvider.tsx -> src/components/Toolbar/Intersect.tsx -> src/components/SetHorVertDistanceModal.tsx -> src/lib/useCalculateKclExpression.ts 22) src/components/ToastTextToCad.tsx -> src/lib/textToCad.ts 23) src/hooks/useModelingContext.ts -> src/components/ModelingMachineProvider.tsx -> src/machines/modelingMachine.ts -> src/clientSideScene/ClientSideSceneComp.tsx 24) src/routes/Onboarding/index.tsx -> src/routes/Onboarding/Camera.tsx -> src/routes/Onboarding/utils.tsx
$ dpdm --no-warning --no-tree -T --skip-dynamic-imports=circular src/index.tsx
• Circular Dependencies
01) src/lang/std/sketch.ts -> src/lang/modifyAst.ts -> src/lang/modifyAst/addEdgeTreatment.ts
02) src/lang/std/sketch.ts -> src/lang/modifyAst.ts
03) src/lang/std/sketch.ts -> src/lang/modifyAst.ts -> src/lang/std/sketchcombos.ts
04) src/lib/singletons.ts -> src/editor/manager.ts -> src/lib/selections.ts
05) src/lib/singletons.ts -> src/lang/KclSingleton.ts
06) src/lib/singletons.ts -> src/lang/codeManager.ts
07) src/lib/singletons.ts -> src/clientSideScene/sceneEntities.ts -> src/clientSideScene/segments.ts -> src/components/Toolbar/angleLengthInfo.ts
08) src/lib/singletons.ts -> src/clientSideScene/sceneEntities.ts -> src/clientSideScene/segments.ts -> src/machines/commandBarMachine.ts -> src/lib/commandBarConfigs/authCommandConfig.ts -> src/machines/appMachine.ts -> src/machines/settingsMachine.ts
09) src/machines/commandBarMachine.ts -> src/lib/commandBarConfigs/authCommandConfig.ts -> src/machines/appMachine.ts -> src/machines/settingsMachine.ts
10) src/hooks/useModelingContext.ts -> src/components/ModelingMachineProvider.tsx -> src/components/Toolbar/Intersect.tsx -> src/components/SetHorVertDistanceModal.tsx -> src/lib/useCalculateKclExpression.ts
11) src/routes/Onboarding/index.tsx -> src/routes/Onboarding/Camera.tsx -> src/routes/Onboarding/utils.tsx

View File

@ -103,6 +103,7 @@
"lint-fix": "eslint --fix --ext .ts --ext .tsx src e2e packages/codemirror-lsp-client/src rust/kcl-language-server/client/src",
"lint": "eslint --max-warnings 0 --ext .ts --ext .tsx src e2e packages/codemirror-lsp-client/src rust/kcl-language-server/client/src",
"circular-deps": "dpdm --no-warning --no-tree -T --skip-dynamic-imports=circular src/index.tsx",
"circular-deps:overwrite": "yarn circular-deps | sed '$d' | grep -v '^yarn run' > known-circular.txt",
"circular-deps:diff": "./scripts/diff-circular-deps.sh",
"files:set-version": "echo \"$(jq --arg v \"$VERSION\" '.version=$v' package.json --indent 2)\" > package.json",
"files:set-notes": "./scripts/set-files-notes.sh",

20
rust/Cargo.lock generated
View File

@ -1780,7 +1780,7 @@ dependencies = [
[[package]]
name = "kcl-bumper"
version = "0.1.57"
version = "0.1.58"
dependencies = [
"anyhow",
"clap",
@ -1791,7 +1791,7 @@ dependencies = [
[[package]]
name = "kcl-derive-docs"
version = "0.1.57"
version = "0.1.58"
dependencies = [
"Inflector",
"anyhow",
@ -1810,7 +1810,7 @@ dependencies = [
[[package]]
name = "kcl-directory-test-macro"
version = "0.1.57"
version = "0.1.58"
dependencies = [
"proc-macro2",
"quote",
@ -1819,7 +1819,7 @@ dependencies = [
[[package]]
name = "kcl-language-server"
version = "0.2.57"
version = "0.2.58"
dependencies = [
"anyhow",
"clap",
@ -1840,7 +1840,7 @@ dependencies = [
[[package]]
name = "kcl-language-server-release"
version = "0.1.57"
version = "0.1.58"
dependencies = [
"anyhow",
"clap",
@ -1860,7 +1860,7 @@ dependencies = [
[[package]]
name = "kcl-lib"
version = "0.2.57"
version = "0.2.58"
dependencies = [
"anyhow",
"approx 0.5.1",
@ -1928,7 +1928,7 @@ dependencies = [
[[package]]
name = "kcl-python-bindings"
version = "0.3.57"
version = "0.3.58"
dependencies = [
"anyhow",
"kcl-lib",
@ -1943,7 +1943,7 @@ dependencies = [
[[package]]
name = "kcl-test-server"
version = "0.1.57"
version = "0.1.58"
dependencies = [
"anyhow",
"hyper 0.14.32",
@ -1956,7 +1956,7 @@ dependencies = [
[[package]]
name = "kcl-to-core"
version = "0.1.57"
version = "0.1.58"
dependencies = [
"anyhow",
"async-trait",
@ -1970,7 +1970,7 @@ dependencies = [
[[package]]
name = "kcl-wasm-lib"
version = "0.1.57"
version = "0.1.58"
dependencies = [
"bson",
"console_error_panic_hook",

View File

@ -1,7 +1,7 @@
[package]
name = "kcl-bumper"
version = "0.1.57"
version = "0.1.58"
edition = "2021"
repository = "https://github.com/KittyCAD/modeling-api"
rust-version = "1.76"

View File

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

View File

@ -1,7 +1,7 @@
[package]
name = "kcl-directory-test-macro"
description = "A tool for generating tests from a directory of kcl files"
version = "0.1.57"
version = "0.1.58"
edition = "2021"
license = "MIT"
repository = "https://github.com/KittyCAD/modeling-app"

View File

@ -1,6 +1,6 @@
[package]
name = "kcl-language-server-release"
version = "0.1.57"
version = "0.1.58"
edition = "2021"
authors = ["KittyCAD Inc <kcl@kittycad.io>"]
publish = false

View File

@ -2,7 +2,7 @@
name = "kcl-language-server"
description = "A language server for KCL."
authors = ["KittyCAD Inc <kcl@kittycad.io>"]
version = "0.2.57"
version = "0.2.58"
edition = "2021"
license = "MIT"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

View File

@ -1,7 +1,7 @@
[package]
name = "kcl-lib"
description = "KittyCAD Language implementation and tools"
version = "0.2.57"
version = "0.2.58"
edition = "2021"
license = "MIT"
repository = "https://github.com/KittyCAD/modeling-app"

View File

@ -104,7 +104,7 @@ pub async fn scale(exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
///
/// cube
/// |> scale(
/// z = 2.5,
/// y = 2.5,
/// )
/// ```
///
@ -278,10 +278,20 @@ pub async fn translate(exec_state: &mut ExecState, args: Args) -> Result<KclValu
///
/// import "tests/inputs/cube.sldprt" as cube
///
/// // Circle so you actually see the move.
/// startSketchOn('XY')
/// |> circle(
/// center = [-10, -10],
/// radius = 10,
/// )
/// |> extrude(
/// length = 10,
/// )
///
/// cube
/// |> translate(
/// x = 1.0,
/// y = 1.0,
/// x = 10.0,
/// y = 10.0,
/// z = 2.5,
/// )
/// ```
@ -680,7 +690,7 @@ pub async fn rotate(exec_state: &mut ExecState, args: Args) -> Result<KclValue,
/// cube
/// |> rotate(
/// axis = [0, 0, 1.0],
/// angle = 90,
/// angle = 9,
/// )
/// ```
///

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

After

Width:  |  Height:  |  Size: 74 KiB

View File

@ -1,6 +1,6 @@
[package]
name = "kcl-python-bindings"
version = "0.3.57"
version = "0.3.58"
edition = "2021"
repository = "https://github.com/kittycad/modeling-app"
exclude = ["tests/*", "files/*", "venv/*"]

View File

@ -1,7 +1,7 @@
[package]
name = "kcl-test-server"
description = "A test server for KCL"
version = "0.1.57"
version = "0.1.58"
edition = "2021"
license = "MIT"

View File

@ -1,7 +1,7 @@
[package]
name = "kcl-to-core"
description = "Utility methods to convert kcl to engine core executable tests"
version = "0.1.57"
version = "0.1.58"
edition = "2021"
license = "MIT"
repository = "https://github.com/KittyCAD/modeling-app"

View File

@ -1,6 +1,6 @@
[package]
name = "kcl-wasm-lib"
version = "0.1.57"
version = "0.1.58"
edition = "2021"
repository = "https://github.com/KittyCAD/modeling-app"
rust-version = "1.83"

View File

@ -1,5 +1,5 @@
#!/bin/bash
set -euo pipefail
yarn circular-deps | sed '$d' | grep -v '^yarn run' | tr -d '\n' > /tmp/circular-deps.txt
diff -w /tmp/circular-deps.txt ./known-circular.txt
yarn circular-deps | sed '$d' | grep -v '^yarn run' > /tmp/circular-deps.txt
diff --ignore-blank-lines -w /tmp/circular-deps.txt ./known-circular.txt

View File

@ -20,7 +20,7 @@ import {
INTERSECTION_PLANE_LAYER,
SKETCH_LAYER,
ZOOM_MAGIC_NUMBER,
} from '@src/clientSideScene/sceneInfra'
} from '@src/clientSideScene/sceneUtils'
import type { EngineCommand } from '@src/lang/std/artifactGraph'
import type {
EngineCommandManager,

View File

@ -1,8 +1,6 @@
import { Dialog, Popover, Transition } from '@headlessui/react'
import { Fragment, useEffect, useMemo, useRef, useState } from 'react'
import { Popover } from '@headlessui/react'
import { useEffect, useMemo, useRef, useState } from 'react'
import toast from 'react-hot-toast'
import type { InstanceProps } from 'react-modal-promise'
import { create } from 'react-modal-promise'
import type { Node } from '@rust/kcl-lib/bindings/Node'
@ -15,16 +13,11 @@ import {
import {
ARROWHEAD,
DEBUG_SHOW_BOTH_SCENES,
} from '@src/clientSideScene/sceneInfra'
import { ActionButton } from '@src/components/ActionButton'
} from '@src/clientSideScene/sceneUtils'
import type { CustomIconName } from '@src/components/CustomIcon'
import { CustomIcon } from '@src/components/CustomIcon'
import { useModelingContext } from '@src/hooks/useModelingContext'
import { executeAstMock } from '@src/lang/langHelpers'
import {
deleteSegmentFromPipeExpression,
removeSingleConstraintInfo,
} from '@src/lang/modifyAst'
import { removeSingleConstraintInfo } from '@src/lang/modifyAst'
import { findUsesOfTagInPipe, getNodeFromPath } from '@src/lang/queryAst'
import { getConstraintInfo, getConstraintInfoKw } from '@src/lang/std/sketch'
import type { ConstrainInfo } from '@src/lang/std/stdTypes'
@ -34,7 +27,6 @@ import type {
CallExpressionKw,
Expr,
PathToNode,
Program,
} from '@src/lang/wasm'
import { defaultSourceRange, parse, recast, resultIsOk } from '@src/lang/wasm'
import { cameraMouseDragGuards } from '@src/lib/cameraControls'
@ -43,7 +35,6 @@ import {
editorManager,
engineCommandManager,
kclManager,
rustContext,
sceneEntitiesManager,
sceneInfra,
} from '@src/lib/singletons'
@ -51,10 +42,7 @@ import { err, reportRejection, trap } from '@src/lib/trap'
import { throttle, toSync } from '@src/lib/utils'
import type { useSettings } from '@src/machines/appMachine'
import { commandBarActor } from '@src/machines/commandBarMachine'
import type {
SegmentOverlay,
SketchDetails,
} from '@src/machines/modelingMachine'
import type { SegmentOverlay } from '@src/machines/modelingMachine'
function useShouldHideScene(): { hideClient: boolean; hideServer: boolean } {
const [isCamMoving, setIsCamMoving] = useState(false)
@ -343,130 +331,6 @@ const Overlay = ({
)
}
type ConfirmModalProps = InstanceProps<boolean, boolean> & { text: string }
export const ConfirmModal = ({
isOpen,
onResolve,
onReject,
text,
}: ConfirmModalProps) => {
return (
<Transition appear show={isOpen} as={Fragment}>
<Dialog
as="div"
className="relative z-10"
onClose={() => onResolve(false)}
>
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="ease-in duration-200"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div className="fixed inset-0 bg-black bg-opacity-25" />
</Transition.Child>
<div className="fixed inset-0 overflow-y-auto">
<div className="flex min-h-full items-center justify-center p-4 text-center">
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0 scale-95"
enterTo="opacity-100 scale-100"
leave="ease-in duration-200"
leaveFrom="opacity-100 scale-100"
leaveTo="opacity-0 scale-95"
>
<Dialog.Panel className="rounded relative mx-auto px-4 py-8 bg-chalkboard-10 dark:bg-chalkboard-100 border dark:border-chalkboard-70 max-w-xl w-full shadow-lg">
<div>{text}</div>
<div className="mt-8 flex justify-between">
<ActionButton
Element="button"
onClick={() => onResolve(true)}
>
Continue and unconstrain
</ActionButton>
<ActionButton
Element="button"
onClick={() => onReject(false)}
>
Cancel
</ActionButton>
</div>
</Dialog.Panel>
</Transition.Child>
</div>
</div>
</Dialog>
</Transition>
)
}
export const confirmModal = create<ConfirmModalProps, boolean, boolean>(
ConfirmModal
)
export async function deleteSegment({
pathToNode,
sketchDetails,
}: {
pathToNode: PathToNode
sketchDetails: SketchDetails | null
}) {
let modifiedAst: Node<Program> | Error = kclManager.ast
const dependentRanges = findUsesOfTagInPipe(modifiedAst, pathToNode)
const shouldContinueSegDelete = dependentRanges.length
? await confirmModal({
text: `At least ${dependentRanges.length} segment rely on the segment you're deleting.\nDo you want to continue and unconstrain these segments?`,
isOpen: true,
})
: true
if (!shouldContinueSegDelete) return
modifiedAst = deleteSegmentFromPipeExpression(
dependentRanges,
modifiedAst,
kclManager.variables,
codeManager.code,
pathToNode
)
if (err(modifiedAst)) return Promise.reject(modifiedAst)
const newCode = recast(modifiedAst)
const pResult = parse(newCode)
if (err(pResult) || !resultIsOk(pResult)) return Promise.reject(pResult)
modifiedAst = pResult.program
const testExecute = await executeAstMock({
ast: modifiedAst,
usePrevMemory: false,
rustContext: rustContext,
})
if (testExecute.errors.length) {
toast.error('Segment tag used outside of current Sketch. Could not delete.')
return
}
if (!sketchDetails) return
await sceneEntitiesManager.updateAstAndRejigSketch(
pathToNode,
sketchDetails.sketchNodePaths,
sketchDetails.planeNodePath,
modifiedAst,
sketchDetails.zAxis,
sketchDetails.yAxis,
sketchDetails.origin
)
// Now 'Set sketchDetails' is called with the modified pathToNode
}
const SegmentMenu = ({
verticalPosition,
pathToNode,

View File

@ -0,0 +1,72 @@
import { Fragment } from 'react'
import { create, type InstanceProps } from 'react-modal-promise'
import { Dialog, Transition } from '@headlessui/react'
import { ActionButton } from '@src/components/ActionButton'
type ConfirmModalProps = InstanceProps<boolean, boolean> & { text: string }
export const ConfirmModal = ({
isOpen,
onResolve,
onReject,
text,
}: ConfirmModalProps) => {
return (
<Transition appear show={isOpen} as={Fragment}>
<Dialog
as="div"
className="relative z-10"
onClose={() => onResolve(false)}
>
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="ease-in duration-200"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div className="fixed inset-0 bg-black bg-opacity-25" />
</Transition.Child>
<div className="fixed inset-0 overflow-y-auto">
<div className="flex min-h-full items-center justify-center p-4 text-center">
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0 scale-95"
enterTo="opacity-100 scale-100"
leave="ease-in duration-200"
leaveFrom="opacity-100 scale-100"
leaveTo="opacity-0 scale-95"
>
<Dialog.Panel className="rounded relative mx-auto px-4 py-8 bg-chalkboard-10 dark:bg-chalkboard-100 border dark:border-chalkboard-70 max-w-xl w-full shadow-lg">
<div>{text}</div>
<div className="mt-8 flex justify-between">
<ActionButton
Element="button"
onClick={() => onResolve(true)}
>
Continue and unconstrain
</ActionButton>
<ActionButton
Element="button"
onClick={() => onReject(false)}
>
Cancel
</ActionButton>
</div>
</Dialog.Panel>
</Transition.Child>
</div>
</div>
</Dialog>
</Transition>
)
}
export const confirmModal = create<ConfirmModalProps, boolean, boolean>(
ConfirmModal
)

View File

@ -0,0 +1,75 @@
import toast from 'react-hot-toast'
import type { Node } from '@rust/kcl-lib/bindings/Node'
import { confirmModal } from '@src/clientSideScene/confirmModal'
import { executeAstMock } from '@src/lang/langHelpers'
import { deleteSegmentFromPipeExpression } from '@src/lang/modifyAst'
import { findUsesOfTagInPipe } from '@src/lang/queryAst'
import type { PathToNode, Program } from '@src/lang/wasm'
import { parse, recast, resultIsOk } from '@src/lang/wasm'
import {
codeManager,
kclManager,
rustContext,
sceneEntitiesManager,
} from '@src/lib/singletons'
import { err } from '@src/lib/trap'
import type { SketchDetails } from '@src/machines/modelingMachine'
export async function deleteSegment({
pathToNode,
sketchDetails,
}: {
pathToNode: PathToNode
sketchDetails: SketchDetails | null
}) {
let modifiedAst: Node<Program> | Error = kclManager.ast
const dependentRanges = findUsesOfTagInPipe(modifiedAst, pathToNode)
const shouldContinueSegDelete = dependentRanges.length
? await confirmModal({
text: `At least ${dependentRanges.length} segment rely on the segment you're deleting.\nDo you want to continue and unconstrain these segments?`,
isOpen: true,
})
: true
if (!shouldContinueSegDelete) return
modifiedAst = deleteSegmentFromPipeExpression(
dependentRanges,
modifiedAst,
kclManager.variables,
codeManager.code,
pathToNode
)
if (err(modifiedAst)) return Promise.reject(modifiedAst)
const newCode = recast(modifiedAst)
const pResult = parse(newCode)
if (err(pResult) || !resultIsOk(pResult)) return Promise.reject(pResult)
modifiedAst = pResult.program
const testExecute = await executeAstMock({
ast: modifiedAst,
usePrevMemory: false,
rustContext: rustContext,
})
if (testExecute.errors.length) {
toast.error('Segment tag used outside of current Sketch. Could not delete.')
return
}
if (!sketchDetails) return
await sceneEntitiesManager.updateAstAndRejigSketch(
pathToNode,
sketchDetails.sketchNodePaths,
sketchDetails.planeNodePath,
modifiedAst,
sketchDetails.zAxis,
sketchDetails.yAxis,
sketchDetails.origin
)
// Now 'Set sketchDetails' is called with the modified pathToNode
}

View File

@ -86,7 +86,7 @@ import {
X_AXIS,
Y_AXIS,
getSceneScale,
} from '@src/clientSideScene/sceneInfra'
} from '@src/clientSideScene/sceneUtils'
import type { SegmentUtils } from '@src/clientSideScene/segments'
import {
createProfileStartHandle,

View File

@ -14,7 +14,6 @@ import {
GridHelper,
LineBasicMaterial,
OrthographicCamera,
PerspectiveCamera,
Raycaster,
Scene,
TextureLoader,
@ -26,6 +25,16 @@ import { CSS2DRenderer } from 'three/examples/jsm/renderers/CSS2DRenderer'
import { CameraControls } from '@src/clientSideScene/CameraControls'
import { orthoScale, perspScale } from '@src/clientSideScene/helpers'
import {
AXIS_GROUP,
DEBUG_SHOW_INTERSECTION_PLANE,
INTERSECTION_PLANE_LAYER,
RAYCASTABLE_PLANE,
SKETCH_LAYER,
X_AXIS,
Y_AXIS,
getSceneScale,
} from '@src/clientSideScene/sceneUtils'
import type { useModelingContext } from '@src/hooks/useModelingContext'
import type { EngineCommandManager } from '@src/lang/std/engineConnection'
import type { Coords2d } from '@src/lang/std/sketch'
@ -41,37 +50,6 @@ import type {
type SendType = ReturnType<typeof useModelingContext>['send']
// 63.5 is definitely a bit of a magic number, play with it until it looked right
// if it were 64, that would feel like it's something in the engine where a random
// power of 2 is used, but it's the 0.5 seems to make things look much more correct
export const ZOOM_MAGIC_NUMBER = 63.5
export const INTERSECTION_PLANE_LAYER = 1
export const SKETCH_LAYER = 2
// redundant types so that it can be changed temporarily but CI will catch the wrong type
export const DEBUG_SHOW_INTERSECTION_PLANE = false
export const DEBUG_SHOW_BOTH_SCENES = false
export const RAYCASTABLE_PLANE = 'raycastable-plane'
export const X_AXIS = 'xAxis'
export const Y_AXIS = 'yAxis'
/** If a segment angle is less than this many degrees off a meanginful angle it'll snap to it */
export const ANGLE_SNAP_THRESHOLD_DEGREES = 3
/** the THREEjs representation of the group surrounding a "snapped" point that is not yet placed */
export const DRAFT_POINT_GROUP = 'draft-point-group'
/** the THREEjs representation of a "snapped" point that is not yet placed */
export const DRAFT_POINT = 'draft-point'
export const AXIS_GROUP = 'axisGroup'
export const SKETCH_GROUP_SEGMENTS = 'sketch-group-segments'
export const ARROWHEAD = 'arrowhead'
export const SEGMENT_LENGTH_LABEL = 'segment-length-label'
export const SEGMENT_LENGTH_LABEL_TEXT = 'segment-length-label-text'
export const SEGMENT_LENGTH_LABEL_OFFSET_PX = 30
export const CIRCLE_3_POINT_DRAFT_POINT = 'circle-3-point-draft-point'
export const CIRCLE_3_POINT_DRAFT_CIRCLE = 'circle-3-point-draft-circle'
export interface OnMouseEnterLeaveArgs {
selected: Object3D<Object3DEventMap>
dragSelected?: Object3D<Object3DEventMap>
@ -689,24 +667,6 @@ export class SceneInfra {
}
}
export function getSceneScale(
camera: PerspectiveCamera | OrthographicCamera,
target: Vector3
): number {
const distance =
camera instanceof PerspectiveCamera
? camera.position.distanceTo(target)
: 63.7942123 / camera.zoom
if (distance <= 20) return 0.1
else if (distance > 20 && distance <= 200) return 1
else if (distance > 200 && distance <= 2000) return 10
else if (distance > 2000 && distance <= 20000) return 100
else if (distance > 20000) return 1000
return 1
}
function baseUnitTomm(baseUnit: BaseUnit) {
switch (baseUnit) {
case 'mm':

View File

@ -0,0 +1,52 @@
// 63.5 is definitely a bit of a magic number, play with it until it looked right
// if it were 64, that would feel like it's something in the engine where a random
import type { OrthographicCamera, Vector3 } from 'three'
import { PerspectiveCamera } from 'three'
// power of 2 is used, but it's the 0.5 seems to make things look much more correct
export const ZOOM_MAGIC_NUMBER = 63.5
export const INTERSECTION_PLANE_LAYER = 1
export const SKETCH_LAYER = 2
// redundant types so that it can be changed temporarily but CI will catch the wrong type
export const DEBUG_SHOW_INTERSECTION_PLANE = false
export const DEBUG_SHOW_BOTH_SCENES = false
export const RAYCASTABLE_PLANE = 'raycastable-plane'
export const X_AXIS = 'xAxis'
export const Y_AXIS = 'yAxis'
/** If a segment angle is less than this many degrees off a meanginful angle it'll snap to it */
export const ANGLE_SNAP_THRESHOLD_DEGREES = 3
/** the THREEjs representation of the group surrounding a "snapped" point that is not yet placed */
export const DRAFT_POINT_GROUP = 'draft-point-group'
/** the THREEjs representation of a "snapped" point that is not yet placed */
export const DRAFT_POINT = 'draft-point'
export const AXIS_GROUP = 'axisGroup'
export const SKETCH_GROUP_SEGMENTS = 'sketch-group-segments'
export const ARROWHEAD = 'arrowhead'
export const SEGMENT_LENGTH_LABEL = 'segment-length-label'
export const SEGMENT_LENGTH_LABEL_TEXT = 'segment-length-label-text'
export const SEGMENT_LENGTH_LABEL_OFFSET_PX = 30
export const CIRCLE_3_POINT_DRAFT_POINT = 'circle-3-point-draft-point'
export const CIRCLE_3_POINT_DRAFT_CIRCLE = 'circle-3-point-draft-circle'
export function getSceneScale(
camera: PerspectiveCamera | OrthographicCamera,
target: Vector3
): number {
const distance =
camera instanceof PerspectiveCamera
? camera.position.distanceTo(target)
: 63.7942123 / camera.zoom
if (distance <= 20) return 0.1
else if (distance > 20 && distance <= 200) return 1
else if (distance > 200 && distance <= 2000) return 10
else if (distance > 2000 && distance <= 20000) return 100
else if (distance > 20000) return 1000
return 1
}

View File

@ -71,7 +71,7 @@ import {
SEGMENT_LENGTH_LABEL,
SEGMENT_LENGTH_LABEL_OFFSET_PX,
SEGMENT_LENGTH_LABEL_TEXT,
} from '@src/clientSideScene/sceneInfra'
} from '@src/clientSideScene/sceneUtils'
import { angleLengthInfo } from '@src/components/Toolbar/angleLengthInfo'
import type { Coords2d } from '@src/lang/std/sketch'
import type { SegmentInputs } from '@src/lang/std/stdTypes'

View File

@ -81,9 +81,7 @@ function CommandBarSelectionInput({
return () => {
toSync(() => {
const promises = [
new Promise(() => kclManager.defaultSelectionFilter(selection)),
]
const promises = [kclManager.defaultSelectionFilter(selection)]
if (!kclManager._isAstEmpty(kclManager.ast)) {
promises.push(kclManager.hidePlanes())
}
@ -130,7 +128,10 @@ function CommandBarSelectionInput({
// Set selection filter if needed, and reset it when the component unmounts
useEffect(() => {
arg.selectionFilter && kclManager.setSelectionFilter(arg.selectionFilter)
return () => kclManager.defaultSelectionFilter(selection)
// TODO: We shouldn't use async here.
return toSync(async () => {
await kclManager.defaultSelectionFilter(selection)
}, reportRejection)
}, [arg.selectionFilter])
return (

View File

@ -8,6 +8,8 @@ import {
getSelectionCountByType,
} from '@src/lib/selections'
import { kclManager } from '@src/lib/singletons'
import { reportRejection } from '@src/lib/trap'
import { toSync } from '@src/lib/utils'
import {
commandBarActor,
useCommandBarState,
@ -64,7 +66,10 @@ export default function CommandBarSelectionMixedInput({
// Set selection filter if needed, and reset it when the component unmounts
useEffect(() => {
arg.selectionFilter && kclManager.setSelectionFilter(arg.selectionFilter)
return () => kclManager.defaultSelectionFilter(selection)
// TODO: We shouldn't use async here.
return toSync(async () => {
await kclManager.defaultSelectionFilter(selection)
}, reportRejection)
}, [arg.selectionFilter])
function handleChange() {

View File

@ -13,7 +13,7 @@ import type { CoreDumpManager } from '@src/lib/coredump'
import openWindow, { openExternalBrowserIfDesktop } from '@src/lib/openWindow'
import { PATHS } from '@src/lib/paths'
import { reportRejection } from '@src/lib/trap'
import { APP_VERSION, getReleaseUrl } from '@src/routes/Settings'
import { APP_VERSION, getReleaseUrl } from '@src/routes/utils'
export function LowerRightControls({
children,

View File

@ -211,6 +211,22 @@ export const ModelingMachineProvider = ({
.catch(reportRejection)
})().catch(reportRejection)
},
execute: ({ context: { store } }) => {
// TODO: Remove this async callback. For some reason eslint wouldn't
// let me disable @typescript-eslint/no-misused-promises for the line.
;(async () => {
return kclManager
.executeCode()
.then(() => {
if (engineCommandManager.engineConnection?.idleMode) return
store.videoElement?.play().catch((e) => {
console.warn('Video playing was prevented', e)
})
})
.catch(reportRejection)
})().catch(reportRejection)
},
'Set mouse state': assign(({ context, event }) => {
if (event.type !== 'Set mouse state') return {}
const nextSegmentHoverMap = () => {

View File

@ -30,7 +30,7 @@ import {
import { reportRejection } from '@src/lib/trap'
import { toSync } from '@src/lib/utils'
import { settingsActor, useSettings } from '@src/machines/appMachine'
import { APP_VERSION, IS_NIGHTLY, getReleaseUrl } from '@src/routes/Settings'
import { APP_VERSION, IS_NIGHTLY, getReleaseUrl } from '@src/routes/utils'
interface AllSettingsFieldsProps {
searchParamTab: SettingsLevel

View File

@ -268,13 +268,14 @@ export const Stream = () => {
if (state.matches('Sketch')) return
// Only respect default plane selection if we're on a selection command argument
if (
state.matches({ idle: 'showPlanes' }) &&
!kclManager.defaultPlanesShown &&
!(
commandBarState.matches('Gathering arguments') &&
commandBarState.context.currentArgument?.inputType === 'selection'
)
)
return
// If we're mousing up from a camera drag, don't send a select event
if (sceneInfra.camControls.wasDragging === true) return
@ -295,7 +296,7 @@ export const Stream = () => {
!isNetworkOkay ||
!videoRef.current ||
state.matches('Sketch') ||
state.matches({ idle: 'showPlanes' }) ||
!kclManager.defaultPlanesShown ||
sceneInfra.camControls.wasDragging === true ||
!btnName(e.nativeEvent).left
) {

View File

@ -30,7 +30,7 @@ import { isDesktop } from '@src/lib/isDesktop'
import { openExternalBrowserIfDesktop } from '@src/lib/openWindow'
import { PATHS } from '@src/lib/paths'
import { codeManager, kclManager } from '@src/lib/singletons'
import { sendTelemetry } from '@src/lib/textToCad'
import { sendTelemetry } from '@src/lib/textToCadTelemetry'
import type { Themes } from '@src/lib/theme'
import { reportRejection } from '@src/lib/trap'
import { commandBarActor } from '@src/machines/commandBarMachine'

View File

@ -5,7 +5,7 @@ import toast from 'react-hot-toast'
import { ActionButton } from '@src/components/ActionButton'
import { SafeRenderer } from '@src/lib/markdown'
import { openExternalBrowserIfDesktop } from '@src/lib/openWindow'
import { getReleaseUrl } from '@src/routes/Settings'
import { getReleaseUrl } from '@src/routes/utils'
export function ToastUpdate({
version,

View File

@ -11,10 +11,11 @@ import {
addLineHighlight,
addLineHighlightEvent,
} from '@src/editor/highlightextension'
import type { KclManager } from '@src/lang/KclSingleton'
import type { EngineCommandManager } from '@src/lang/std/engineConnection'
import { markOnce } from '@src/lib/performance'
import type { Selection, Selections } from '@src/lib/selections'
import { processCodeMirrorRanges } from '@src/lib/selections'
import { engineCommandManager, kclManager } from '@src/lib/singletons'
import { kclEditorActor } from '@src/machines/kclEditorMachine'
import type {
ModelingMachineEvent,
@ -44,6 +45,8 @@ export const setDiagnosticsEvent = setDiagnosticsAnnotation.of(true)
export default class EditorManager {
private _copilotEnabled: boolean = true
private engineCommandManager: EngineCommandManager
private kclManager: KclManager
private _isAllTextSelected: boolean = false
private _isShiftDown: boolean = false
@ -64,6 +67,14 @@ export default class EditorManager {
public _editorView: EditorView | null = null
constructor(
engineCommandManager: EngineCommandManager,
kclManager: KclManager
) {
this.engineCommandManager = engineCommandManager
this.kclManager = kclManager
}
setCopilotEnabled(enabled: boolean) {
this._copilotEnabled = enabled
}
@ -379,8 +390,8 @@ export default class EditorManager {
codeMirrorRanges: viewUpdate.state.selection.ranges,
selectionRanges: this._selectionRanges,
isShiftDown: this._isShiftDown,
ast: kclManager.ast,
artifactGraph: kclManager.artifactGraph,
ast: this.kclManager.ast,
artifactGraph: this.kclManager.artifactGraph,
})
if (!eventInfo) {
@ -407,7 +418,7 @@ export default class EditorManager {
this._modelingSend(eventInfo.modelingEvent)
eventInfo.engineEvents.forEach((event) => {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
engineCommandManager.sendSceneCommand(event)
this.engineCommandManager.sendSceneCommand(event)
})
}
}

View File

@ -53,7 +53,7 @@ import {
sceneInfra,
} from '@src/lib/singletons'
import { err, reportRejection } from '@src/lib/trap'
import { deferExecution, isOverlap, uuidv4 } from '@src/lib/utils'
import { isOverlap, uuidv4 } from '@src/lib/utils'
interface ExecuteArgs {
ast?: Node<Program>
@ -317,23 +317,44 @@ export class KclManager {
this.artifactGraph = execStateArtifactGraph
this.artifactIndex = buildArtifactIndex(execStateArtifactGraph)
if (this.artifactGraph.size) {
// TODO: we wanna remove this logic from xstate, it is racey
// This defer is bullshit but playwright wants it
// It was like this in engineConnection.ts already
deferExecution((a?: null) => {
this.engineCommandManager.modelingSend({
type: 'Artifact graph emptied',
})
}, 200)(null)
} else {
deferExecution((a?: null) => {
this.engineCommandManager.modelingSend({
type: 'Artifact graph populated',
})
}, 200)(null)
// Hide the planes.
await Promise.all([this.hidePlanes(), this.defaultSelectionFilter()])
} else if (!this.hasErrors()) {
// Only show the planes if there are no errors.
// Show the planes and reset.
await this.showAndResetPlanes()
}
}
private async showAndResetPlanes(): Promise<void> {
await Promise.all([
this.showPlanes(),
this.resetCameraPosition(),
this.engineCommandManager.sendSceneCommand({
type: 'modeling_cmd_req',
cmd_id: uuidv4(),
cmd: {
type: 'set_selection_filter',
filter: ['curve'],
},
}),
])
}
async resetCameraPosition(): Promise<void> {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
await this.engineCommandManager.sendSceneCommand({
type: 'modeling_cmd_req',
cmd_id: uuidv4(),
cmd: {
type: 'default_camera_look_at',
center: { x: 0, y: 0, z: 0 },
vantage: { x: 0, y: -1250, z: 580 },
up: { x: 0, y: 0, z: 1 },
},
})
}
// Some "objects" have the same source range, such as sketch_mode_start and start_path.
// So when passing a range, we need to also specify the command type
private mapRangeToObjectId(
@ -704,8 +725,9 @@ export class KclManager {
return rustContext.defaultPlanes
}
showPlanes(all = false) {
if (!this.defaultPlanes) return Promise.all([])
async showPlanes(all = false): Promise<void> {
if (!this.defaultPlanes) return
this.defaultPlanesShown = true
const thePromises = [
this.engineCommandManager.setPlaneHidden(this.defaultPlanes.xy, false),
this.engineCommandManager.setPlaneHidden(this.defaultPlanes.yz, false),
@ -731,11 +753,12 @@ export class KclManager {
)
)
}
return Promise.all(thePromises)
await Promise.all(thePromises)
}
hidePlanes(all = false) {
if (!this.defaultPlanes) return Promise.all([])
async hidePlanes(all = false): Promise<void> {
if (!this.defaultPlanes) return
this.defaultPlanesShown = false
const thePromises = [
this.engineCommandManager.setPlaneHidden(this.defaultPlanes.xy, true),
this.engineCommandManager.setPlaneHidden(this.defaultPlanes.yz, true),
@ -752,15 +775,20 @@ export class KclManager {
this.engineCommandManager.setPlaneHidden(this.defaultPlanes.negXz, true)
)
}
return Promise.all(thePromises)
await Promise.all(thePromises)
}
/** TODO: this function is hiding unawaited asynchronous work */
defaultSelectionFilter(selectionsToRestore?: Selections) {
setSelectionFilterToDefault(this.engineCommandManager, selectionsToRestore)
async defaultSelectionFilter(
selectionsToRestore?: Selections
): Promise<void> {
await setSelectionFilterToDefault(
this.engineCommandManager,
selectionsToRestore
)
}
/** TODO: this function is hiding unawaited asynchronous work */
setSelectionFilter(filter: EntityType_type[]) {
setSelectionFilter(filter, this.engineCommandManager)
async setSelectionFilter(filter: EntityType_type[]): Promise<void> {
await setSelectionFilter(filter, this.engineCommandManager)
}
/**
@ -801,33 +829,29 @@ const defaultSelectionFilter: EntityType_type[] = [
'object',
]
/** TODO: This function is not synchronous but is currently treated as such */
function setSelectionFilterToDefault(
async function setSelectionFilterToDefault(
engineCommandManager: EngineCommandManager,
selectionsToRestore?: Selections
) {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
setSelectionFilter(
): Promise<void> {
await setSelectionFilter(
defaultSelectionFilter,
engineCommandManager,
selectionsToRestore
)
}
/** TODO: This function is not synchronous but is currently treated as such */
function setSelectionFilter(
async function setSelectionFilter(
filter: EntityType_type[],
engineCommandManager: EngineCommandManager,
selectionsToRestore?: Selections
) {
): Promise<void> {
const { engineEvents } = selectionsToRestore
? handleSelectionBatch({
selections: selectionsToRestore,
})
: { engineEvents: undefined }
if (!selectionsToRestore || !engineEvents) {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
engineCommandManager.sendSceneCommand({
await engineCommandManager.sendSceneCommand({
type: 'modeling_cmd_req',
cmd_id: uuidv4(),
cmd: {
@ -847,7 +871,7 @@ function setSelectionFilter(
}
})
// batch is needed other wise the selection flickers.
engineCommandManager
await engineCommandManager
.sendSceneCommand({
type: 'modeling_cmd_batch_req',
batch_id: uuidv4(),

View File

@ -28,7 +28,7 @@ import type { Selections } from '@src/lib/selections'
import { codeManager, kclManager } from '@src/lib/singletons'
import { err } from '@src/lib/trap'
import type { SketchTool, modelingMachine } from '@src/machines/modelingMachine'
import { IS_NIGHTLY_OR_DEBUG } from '@src/routes/Settings'
import { IS_NIGHTLY_OR_DEBUG } from '@src/routes/utils'
type OutputFormat = Models['OutputFormat3d_type']
type OutputTypeKey = OutputFormat['type']

View File

@ -12,7 +12,7 @@ import type {
import { isDesktop } from '@src/lib/isDesktop'
import type RustContext from '@src/lib/rustContext'
import screenshot from '@src/lib/screenshot'
import { APP_VERSION } from '@src/routes/Settings'
import { APP_VERSION } from '@src/routes/utils'
/* eslint-disable suggest-no-throw/suggest-no-throw --
* All the throws in CoreDumpManager are intentional and should be caught and handled properly

View File

@ -16,7 +16,7 @@ import type {
StateMachineCommandSetSchema,
} from '@src/lib/commandTypes'
import { isDesktop } from '@src/lib/isDesktop'
import { IS_NIGHTLY_OR_DEBUG } from '@src/routes/Settings'
import { IS_NIGHTLY_OR_DEBUG } from '@src/routes/utils'
interface CreateMachineCommandProps<
T extends AnyStateMachine,

View File

@ -10,7 +10,7 @@ import {
SEGMENT_BODIES_PLUS_PROFILE_START,
getParentGroup,
} from '@src/clientSideScene/sceneConstants'
import { AXIS_GROUP, X_AXIS } from '@src/clientSideScene/sceneInfra'
import { AXIS_GROUP, X_AXIS } from '@src/clientSideScene/sceneUtils'
import { getNodeFromPath, isSingleCursorInPipe } from '@src/lang/queryAst'
import { getNodePathFromSourceRange } from '@src/lang/queryAstNodePathUtils'
import type { Artifact, ArtifactId, CodeRef } from '@src/lang/std/artifactGraph'

View File

@ -34,7 +34,7 @@ kclManager.sceneInfraBaseUnitMultiplierSetter = (unit: BaseUnit) => {
}
// This needs to be after sceneInfra and engineCommandManager are is created.
export const editorManager = new EditorManager()
export const editorManager = new EditorManager(engineCommandManager, kclManager)
export const rustContext = new RustContext(engineCommandManager)

View File

@ -251,19 +251,3 @@ export async function submitAndAwaitTextToKcl({
)
return textToCadOutputCreated
}
export async function sendTelemetry(
id: string,
feedback: Models['MlFeedback_type'],
token?: string
): Promise<void> {
const url =
VITE_KC_API_BASE_URL + '/user/text-to-cad/' + id + '?feedback=' + feedback
await crossPlatformFetch(
url,
{
method: 'POST',
},
token
)
}

View File

@ -0,0 +1,19 @@
import type { Models } from '@kittycad/lib/dist/types/src'
import { VITE_KC_API_BASE_URL } from '@src/env'
import crossPlatformFetch from '@src/lib/crossPlatformFetch'
export async function sendTelemetry(
id: string,
feedback: Models['MlFeedback_type'],
token?: string
): Promise<void> {
const url =
VITE_KC_API_BASE_URL + '/user/text-to-cad/' + id + '?feedback=' + feedback
await crossPlatformFetch(
url,
{
method: 'POST',
},
token
)
}

View File

@ -9,7 +9,7 @@ import {
isEditingExistingSketch,
pipeHasCircle,
} from '@src/machines/modelingMachine'
import { IS_NIGHTLY_OR_DEBUG } from '@src/routes/Settings'
import { IS_NIGHTLY_OR_DEBUG } from '@src/routes/utils'
export type ToolbarModeName = 'modeling' | 'sketching'

File diff suppressed because one or more lines are too long

View File

@ -1,11 +1,8 @@
import { Dialog, Transition } from '@headlessui/react'
import { NODE_ENV } from '@src/env'
import { Fragment, useEffect, useRef } from 'react'
import { useHotkeys } from 'react-hotkeys-hook'
import { useLocation, useNavigate, useSearchParams } from 'react-router-dom'
import { IS_PLAYWRIGHT_KEY } from '@e2e/playwright/storageStates'
import { CustomIcon } from '@src/components/CustomIcon'
import { AllKeybindingsFields } from '@src/components/Settings/AllKeybindingsFields'
import { AllSettingsFields } from '@src/components/Settings/AllSettingsFields'
@ -14,35 +11,9 @@ import { SettingsSearchBar } from '@src/components/Settings/SettingsSearchBar'
import { SettingsSectionsList } from '@src/components/Settings/SettingsSectionsList'
import { SettingsTabs } from '@src/components/Settings/SettingsTabs'
import { useDotDotSlash } from '@src/hooks/useDotDotSlash'
import { isDesktop } from '@src/lib/isDesktop'
import { PATHS } from '@src/lib/paths'
import type { SettingsLevel } from '@src/lib/settings/settingsTypes'
const isTestEnv = window?.localStorage.getItem(IS_PLAYWRIGHT_KEY) === 'true'
export const APP_VERSION =
isTestEnv && NODE_ENV === 'development'
? '11.22.33'
: isDesktop()
? // @ts-ignore
window.electron.packageJson.version
: 'main'
export const PACKAGE_NAME = isDesktop()
? window.electron.packageJson.name
: 'zoo-modeling-app'
export const IS_NIGHTLY = PACKAGE_NAME.indexOf('-nightly') > -1
export const IS_NIGHTLY_OR_DEBUG =
IS_NIGHTLY || APP_VERSION === '0.0.0' || APP_VERSION === '11.22.33'
export function getReleaseUrl(version: string = APP_VERSION) {
return `https://github.com/KittyCAD/modeling-app/releases/tag/${
IS_NIGHTLY ? 'nightly-' : ''
}v${version}`
}
export const Settings = () => {
const navigate = useNavigate()
const [searchParams, setSearchParams] = useSearchParams()

View File

@ -15,7 +15,7 @@ import { Themes, getSystemTheme } from '@src/lib/theme'
import { reportRejection } from '@src/lib/trap'
import { toSync } from '@src/lib/utils'
import { authActor, useSettings } from '@src/machines/appMachine'
import { APP_VERSION } from '@src/routes/Settings'
import { APP_VERSION } from '@src/routes/utils'
const subtleBorder =
'border border-solid border-chalkboard-30 dark:border-chalkboard-80'

29
src/routes/utils.ts Normal file
View File

@ -0,0 +1,29 @@
import { NODE_ENV } from '@src/env'
import { isDesktop } from '@src/lib/isDesktop'
import { IS_PLAYWRIGHT_KEY } from '@e2e/playwright/storageStates'
const isTestEnv = window?.localStorage.getItem(IS_PLAYWRIGHT_KEY) === 'true'
export const APP_VERSION =
isTestEnv && NODE_ENV === 'development'
? '11.22.33'
: isDesktop()
? // @ts-ignore
window.electron.packageJson.version
: 'main'
export const PACKAGE_NAME = isDesktop()
? window.electron.packageJson.name
: 'zoo-modeling-app'
export const IS_NIGHTLY = PACKAGE_NAME.indexOf('-nightly') > -1
export const IS_NIGHTLY_OR_DEBUG =
IS_NIGHTLY || APP_VERSION === '0.0.0' || APP_VERSION === '11.22.33'
export function getReleaseUrl(version: string = APP_VERSION) {
return `https://github.com/KittyCAD/modeling-app/releases/tag/${
IS_NIGHTLY ? 'nightly-' : ''
}v${version}`
}