Compare commits
19 Commits
v0.43.0
...
nightly-v2
Author | SHA1 | Date | |
---|---|---|---|
099c48cd63 | |||
f35cd3ef26 | |||
695c432d1e | |||
2835665a6a | |||
45707d2974 | |||
b2e1d21d45 | |||
b98f5605b6 | |||
c050e03df1 | |||
b6fa4325f0 | |||
0804aecc63 | |||
3dfc2c86e1 | |||
71647ede29 | |||
cd679f4be3 | |||
18d87b99bd | |||
70a2202877 | |||
f5c9f84ae9 | |||
71f701dec7 | |||
bffbed1d42 | |||
9f60ed8e75 |
13
.gitattributes
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
# Set default behavior to automatically normalize line endings.
|
||||
* text=auto
|
||||
|
||||
# Force batch scripts to always use CRLF line endings so that if a repo is accessed
|
||||
# in Windows via a file share from Linux, the scripts will work.
|
||||
*.{cmd,[cC][mM][dD]} text working-tree-encoding=UTF-16LE eol=CRLF
|
||||
*.{bat,[bB][aA][tT]} text working-tree-encoding=UTF-16LE eol=CRLF
|
||||
*.{ics,[iI][cC][sS]} text working-tree-encoding=UTF-16LE eol=CRLF
|
||||
*.{ps1,[iP][sS][1]} text working-tree-encoding=UTF-16LE eol=CRLF
|
||||
|
||||
# Force bash scripts to always use LF line endings so that if a repo is accessed
|
||||
# in Unix via a file share from Windows, the scripts will work.
|
||||
*.sh text eol=lfol=lf
|
40008
docs/kcl/std.json
@ -18,6 +18,7 @@ A base path.
|
||||
|----------|------|-------------|----------|
|
||||
| `from` |`[number, number]`| The from point. | No |
|
||||
| `to` |`[number, number]`| The to point. | No |
|
||||
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A base path. | No |
|
||||
| `tag` |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| The tag of the path. | No |
|
||||
| `__geoMeta` |[`GeoMeta`](/docs/kcl/types/GeoMeta)| Metadata. | No |
|
||||
|
||||
|
@ -33,6 +33,7 @@ layout: manual
|
||||
|
||||
|
||||
----
|
||||
A unit of length.
|
||||
|
||||
**Type:** `object`
|
||||
|
||||
@ -140,6 +141,7 @@ layout: manual
|
||||
|
||||
|
||||
----
|
||||
A unit of angle.
|
||||
|
||||
**Type:** `object`
|
||||
|
||||
|
@ -27,6 +27,7 @@ A path that goes to a point.
|
||||
| `type` |enum: `ToPoint`| | No |
|
||||
| `from` |`[number, number]`| The from point. | No |
|
||||
| `to` |`[number, number]`| The to point. | No |
|
||||
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A path. | No |
|
||||
| `tag` |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| The tag of the path. | No |
|
||||
| `__geoMeta` |[`GeoMeta`](/docs/kcl/types/GeoMeta)| Metadata. | No |
|
||||
|
||||
@ -49,6 +50,7 @@ A arc that is tangential to the last path segment that goes to a point
|
||||
| `ccw` |`boolean`| arc's direction | No |
|
||||
| `from` |`[number, number]`| The from point. | No |
|
||||
| `to` |`[number, number]`| The to point. | No |
|
||||
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A path. | No |
|
||||
| `tag` |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| The tag of the path. | No |
|
||||
| `__geoMeta` |[`GeoMeta`](/docs/kcl/types/GeoMeta)| Metadata. | No |
|
||||
|
||||
@ -71,6 +73,7 @@ A arc that is tangential to the last path segment
|
||||
| `ccw` |`boolean`| arc's direction | No |
|
||||
| `from` |`[number, number]`| The from point. | No |
|
||||
| `to` |`[number, number]`| The to point. | No |
|
||||
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A path. | No |
|
||||
| `tag` |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| The tag of the path. | No |
|
||||
| `__geoMeta` |[`GeoMeta`](/docs/kcl/types/GeoMeta)| Metadata. | No |
|
||||
|
||||
@ -94,6 +97,7 @@ a complete arc
|
||||
| `ccw` |`boolean`| arc's direction This is used to compute the tangential angle. | No |
|
||||
| `from` |`[number, number]`| The from point. | No |
|
||||
| `to` |`[number, number]`| The to point. | No |
|
||||
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A path. | No |
|
||||
| `tag` |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| The tag of the path. | No |
|
||||
| `__geoMeta` |[`GeoMeta`](/docs/kcl/types/GeoMeta)| Metadata. | No |
|
||||
|
||||
@ -117,6 +121,7 @@ A base path.
|
||||
| `p3` |`[number, number]`| Point 3 of the circle | No |
|
||||
| `from` |`[number, number]`| The from point. | No |
|
||||
| `to` |`[number, number]`| The to point. | No |
|
||||
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A path. | No |
|
||||
| `tag` |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| The tag of the path. | No |
|
||||
| `__geoMeta` |[`GeoMeta`](/docs/kcl/types/GeoMeta)| Metadata. | No |
|
||||
|
||||
@ -138,6 +143,7 @@ A path that is horizontal.
|
||||
| `x` |`number`| The x coordinate. | No |
|
||||
| `from` |`[number, number]`| The from point. | No |
|
||||
| `to` |`[number, number]`| The to point. | No |
|
||||
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A path. | No |
|
||||
| `tag` |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| The tag of the path. | No |
|
||||
| `__geoMeta` |[`GeoMeta`](/docs/kcl/types/GeoMeta)| Metadata. | No |
|
||||
|
||||
@ -160,6 +166,7 @@ An angled line to.
|
||||
| `y` |`number`| The y coordinate. | No |
|
||||
| `from` |`[number, number]`| The from point. | No |
|
||||
| `to` |`[number, number]`| The to point. | No |
|
||||
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A path. | No |
|
||||
| `tag` |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| The tag of the path. | No |
|
||||
| `__geoMeta` |[`GeoMeta`](/docs/kcl/types/GeoMeta)| Metadata. | No |
|
||||
|
||||
@ -180,6 +187,7 @@ A base path.
|
||||
| `type` |enum: `Base`| | No |
|
||||
| `from` |`[number, number]`| The from point. | No |
|
||||
| `to` |`[number, number]`| The to point. | No |
|
||||
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A path. | No |
|
||||
| `tag` |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| The tag of the path. | No |
|
||||
| `__geoMeta` |[`GeoMeta`](/docs/kcl/types/GeoMeta)| Metadata. | No |
|
||||
|
||||
@ -203,6 +211,7 @@ A circular arc, not necessarily tangential to the current point.
|
||||
| `ccw` |`boolean`| True if the arc is counterclockwise. | No |
|
||||
| `from` |`[number, number]`| The from point. | No |
|
||||
| `to` |`[number, number]`| The to point. | No |
|
||||
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A path. | No |
|
||||
| `tag` |[`TagDeclarator`](/docs/kcl/types#tag-declaration)| The tag of the path. | No |
|
||||
| `__geoMeta` |[`GeoMeta`](/docs/kcl/types/GeoMeta)| Metadata. | No |
|
||||
|
||||
|
@ -6,6 +6,40 @@ layout: manual
|
||||
|
||||
A sketch is a collection of paths.
|
||||
|
||||
When you define a sketch to a variable like:
|
||||
|
||||
```kcl
|
||||
mySketch = startSketchOn('XY')
|
||||
|> startProfileAt([-12, 12], %)
|
||||
|> line(end = [24, 0])
|
||||
|> line(end = [0, -24])
|
||||
|> line(end = [-24, 0])
|
||||
|> close()
|
||||
```
|
||||
|
||||
The `mySketch` variable will be an executed [`Sketch`](/docs/kcl/types/Sketch) object. Executed being past tense, because the engine has already executed the commands to create the sketch.
|
||||
|
||||
The previous sketch commands will never be executed again, in this case.
|
||||
|
||||
If you would like to encapsulate the commands to create the sketch any time you call it, you can use a function.
|
||||
|
||||
```kcl
|
||||
fn createSketch() {
|
||||
return startSketchOn('XY')
|
||||
|> startProfileAt([-12, 12], %)
|
||||
|> line(end = [24, 0])
|
||||
|> line(end = [0, -24])
|
||||
|> line(end = [-24, 0])
|
||||
|> close()
|
||||
}
|
||||
```
|
||||
|
||||
Now, every time you call `createSketch()`, the commands will be executed and a new sketch will be created.
|
||||
|
||||
When you assign the result of `createSketch()` to a variable (`mySketch = createSketch()`), you are assigning the executed sketch to that variable. Meaning that the sketch `mySketch` will not be executed again.
|
||||
|
||||
You can still execute _new_ commands on the sketch like `extrude`, `revolve`, `loft`, etc. and the sketch will be updated.
|
||||
|
||||
**Type:** `object`
|
||||
|
||||
|
||||
|
@ -14,6 +14,40 @@ A sketch or a group of sketches.
|
||||
|
||||
A sketch is a collection of paths.
|
||||
|
||||
When you define a sketch to a variable like:
|
||||
|
||||
```kcl
|
||||
mySketch = startSketchOn('XY')
|
||||
|> startProfileAt([-12, 12], %)
|
||||
|> line(end = [24, 0])
|
||||
|> line(end = [0, -24])
|
||||
|> line(end = [-24, 0])
|
||||
|> close()
|
||||
```
|
||||
|
||||
The `mySketch` variable will be an executed [`Sketch`](/docs/kcl/types/Sketch) object. Executed being past tense, because the engine has already executed the commands to create the sketch.
|
||||
|
||||
The previous sketch commands will never be executed again, in this case.
|
||||
|
||||
If you would like to encapsulate the commands to create the sketch any time you call it, you can use a function.
|
||||
|
||||
```kcl
|
||||
fn createSketch() {
|
||||
return startSketchOn('XY')
|
||||
|> startProfileAt([-12, 12], %)
|
||||
|> line(end = [24, 0])
|
||||
|> line(end = [0, -24])
|
||||
|> line(end = [-24, 0])
|
||||
|> close()
|
||||
}
|
||||
```
|
||||
|
||||
Now, every time you call `createSketch()`, the commands will be executed and a new sketch will be created.
|
||||
|
||||
When you assign the result of `createSketch()` to a variable (`mySketch = createSketch()`), you are assigning the executed sketch to that variable. Meaning that the sketch `mySketch` will not be executed again.
|
||||
|
||||
You can still execute _new_ commands on the sketch like `extrude`, `revolve`, `loft`, etc. and the sketch will be updated.
|
||||
|
||||
**Type:** `object`
|
||||
|
||||
|
||||
|
@ -1,10 +1,46 @@
|
||||
---
|
||||
title: "Solid"
|
||||
excerpt: "An solid is a collection of extrude surfaces."
|
||||
excerpt: "A solid is a collection of extrude surfaces."
|
||||
layout: manual
|
||||
---
|
||||
|
||||
An solid is a collection of extrude surfaces.
|
||||
A solid is a collection of extrude surfaces.
|
||||
|
||||
When you define a solid to a variable like:
|
||||
|
||||
```kcl
|
||||
myPart = startSketchOn('XY')
|
||||
|> startProfileAt([-12, 12], %)
|
||||
|> line(end = [24, 0])
|
||||
|> line(end = [0, -24])
|
||||
|> line(end = [-24, 0])
|
||||
|> close()
|
||||
|> extrude(length = 6)
|
||||
```
|
||||
|
||||
The `myPart` variable will be an executed [`Solid`](/docs/kcl/types/Solid) object. Executed being past tense, because the engine has already executed the commands to create the solid.
|
||||
|
||||
The previous solid commands will never be executed again, in this case.
|
||||
|
||||
If you would like to encapsulate the commands to create the solid any time you call it, you can use a function.
|
||||
|
||||
```kcl
|
||||
fn createPart() {
|
||||
return startSketchOn('XY')
|
||||
|> startProfileAt([-12, 12], %)
|
||||
|> line(end = [24, 0])
|
||||
|> line(end = [0, -24])
|
||||
|> line(end = [-24, 0])
|
||||
|> close()
|
||||
|> extrude(length = 6)
|
||||
}
|
||||
```
|
||||
|
||||
Now, every time you call `createPart()`, the commands will be executed and a new solid will be created.
|
||||
|
||||
When you assign the result of `createPart()` to a variable (`myPart = createPart()`), you are assigning the executed solid to that variable. Meaning that the solid `myPart` will not be executed again.
|
||||
|
||||
You can still execute _new_ commands on the solid like `shell`, `fillet`, `chamfer`, etc. and the solid will be updated.
|
||||
|
||||
**Type:** `object`
|
||||
|
||||
@ -24,7 +60,7 @@ An solid is a collection of extrude surfaces.
|
||||
| `startCapId` |`string`| The id of the extrusion start cap | No |
|
||||
| `endCapId` |`string`| The id of the extrusion end cap | No |
|
||||
| `edgeCuts` |`[` [`EdgeCut`](/docs/kcl/types/EdgeCut) `]`| Chamfers or fillets on this solid. | No |
|
||||
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| An solid is a collection of extrude surfaces. | No |
|
||||
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A solid is a collection of extrude surfaces. | No |
|
||||
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| Metadata. | No |
|
||||
|
||||
|
||||
|
@ -12,7 +12,43 @@ A solid or a group of solids.
|
||||
|
||||
**This schema accepts exactly one of the following:**
|
||||
|
||||
An solid is a collection of extrude surfaces.
|
||||
A solid is a collection of extrude surfaces.
|
||||
|
||||
When you define a solid to a variable like:
|
||||
|
||||
```kcl
|
||||
myPart = startSketchOn('XY')
|
||||
|> startProfileAt([-12, 12], %)
|
||||
|> line(end = [24, 0])
|
||||
|> line(end = [0, -24])
|
||||
|> line(end = [-24, 0])
|
||||
|> close()
|
||||
|> extrude(length = 6)
|
||||
```
|
||||
|
||||
The `myPart` variable will be an executed [`Solid`](/docs/kcl/types/Solid) object. Executed being past tense, because the engine has already executed the commands to create the solid.
|
||||
|
||||
The previous solid commands will never be executed again, in this case.
|
||||
|
||||
If you would like to encapsulate the commands to create the solid any time you call it, you can use a function.
|
||||
|
||||
```kcl
|
||||
fn createPart() {
|
||||
return startSketchOn('XY')
|
||||
|> startProfileAt([-12, 12], %)
|
||||
|> line(end = [24, 0])
|
||||
|> line(end = [0, -24])
|
||||
|> line(end = [-24, 0])
|
||||
|> close()
|
||||
|> extrude(length = 6)
|
||||
}
|
||||
```
|
||||
|
||||
Now, every time you call `createPart()`, the commands will be executed and a new solid will be created.
|
||||
|
||||
When you assign the result of `createPart()` to a variable (`myPart = createPart()`), you are assigning the executed solid to that variable. Meaning that the solid `myPart` will not be executed again.
|
||||
|
||||
You can still execute _new_ commands on the solid like `shell`, `fillet`, `chamfer`, etc. and the solid will be updated.
|
||||
|
||||
**Type:** `object`
|
||||
|
||||
|
@ -1,9 +1,10 @@
|
||||
---
|
||||
title: "UnitAngle"
|
||||
excerpt: ""
|
||||
excerpt: "A unit of angle."
|
||||
layout: manual
|
||||
---
|
||||
|
||||
A unit of angle.
|
||||
|
||||
|
||||
|
||||
|
@ -1,9 +1,10 @@
|
||||
---
|
||||
title: "UnitLen"
|
||||
excerpt: ""
|
||||
excerpt: "A unit of length."
|
||||
layout: manual
|
||||
---
|
||||
|
||||
A unit of length.
|
||||
|
||||
|
||||
|
||||
|
@ -5,6 +5,7 @@ import { ToolbarFixture } from './fixtures/toolbarFixture'
|
||||
import fs from 'node:fs/promises'
|
||||
import path from 'node:path'
|
||||
import { getUtils } from './test-utils'
|
||||
import { Locator } from '@playwright/test'
|
||||
|
||||
// test file is for testing point an click code gen functionality that's not sketch mode related
|
||||
|
||||
@ -2506,6 +2507,94 @@ extrude002 = extrude(sketch002, length = 50)
|
||||
})
|
||||
})
|
||||
|
||||
const shellPointAndClickDeletionCases = [
|
||||
{ shouldUseKeyboard: true },
|
||||
{ shouldUseKeyboard: false },
|
||||
]
|
||||
shellPointAndClickDeletionCases.forEach(({ shouldUseKeyboard }) => {
|
||||
test(`Shell point-and-click deletion (shouldUseKeyboard: ${shouldUseKeyboard})`, async ({
|
||||
context,
|
||||
page,
|
||||
homePage,
|
||||
scene,
|
||||
editor,
|
||||
toolbar,
|
||||
cmdBar,
|
||||
}) => {
|
||||
const sketchCode = `sketch001 = startSketchOn('XY')
|
||||
profile001 = startProfileAt([-20, 20], sketch001)
|
||||
|> xLine(40, %)
|
||||
|> yLine(-60, %)
|
||||
|> xLine(-40, %)
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||
|> close()
|
||||
`
|
||||
const extrudeCode = `extrude001 = extrude(profile001, length = 40)
|
||||
`
|
||||
const shellCode = `shell001 = shell(extrude001, faces = ['end'], thickness = 5)
|
||||
`
|
||||
const initialCode = sketchCode + extrudeCode + shellCode
|
||||
await context.addInitScript((initialCode) => {
|
||||
localStorage.setItem('persistCode', initialCode)
|
||||
}, initialCode)
|
||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||
await homePage.goToModelingScene()
|
||||
await scene.waitForExecutionDone()
|
||||
await toolbar.openPane('feature-tree')
|
||||
|
||||
// One dumb hardcoded screen pixel value
|
||||
const testPoint = { x: 590, y: 400 }
|
||||
const extrudeColor: [number, number, number] = [100, 100, 100]
|
||||
const sketchColor: [number, number, number] = [140, 140, 140]
|
||||
const defaultPlaneColor: [number, number, number] = [50, 50, 100]
|
||||
|
||||
const deleteOperation = async (operationButton: Locator) => {
|
||||
if (shouldUseKeyboard) {
|
||||
await operationButton.click({ button: 'left' })
|
||||
await page.keyboard.press('Backspace')
|
||||
} else {
|
||||
await operationButton.click({ button: 'right' })
|
||||
const editButton = page.getByTestId('context-menu-delete')
|
||||
await editButton.click()
|
||||
}
|
||||
}
|
||||
|
||||
await test.step(`Look for the grey of the extrude shape`, async () => {
|
||||
await scene.expectPixelColor(extrudeColor, testPoint, 20)
|
||||
})
|
||||
|
||||
await test.step('Delete shell and confirm deletion', async () => {
|
||||
const operationButton = await toolbar.getFeatureTreeOperation(
|
||||
'Shell',
|
||||
0
|
||||
)
|
||||
await deleteOperation(operationButton)
|
||||
await scene.expectPixelColor(extrudeColor, testPoint, 20)
|
||||
await editor.expectEditor.not.toContain(shellCode)
|
||||
})
|
||||
|
||||
await test.step('Delete extrude and confirm deletion', async () => {
|
||||
const operationButton = await toolbar.getFeatureTreeOperation(
|
||||
'Extrude',
|
||||
0
|
||||
)
|
||||
await deleteOperation(operationButton)
|
||||
await editor.expectEditor.not.toContain(extrudeCode)
|
||||
await scene.expectPixelColor(sketchColor, testPoint, 20)
|
||||
})
|
||||
|
||||
await test.step('Delete sketch and confirm empty scene', async () => {
|
||||
const operationButton = await toolbar.getFeatureTreeOperation(
|
||||
'Sketch',
|
||||
0
|
||||
)
|
||||
await deleteOperation(operationButton)
|
||||
await editor.expectEditor.toContain('')
|
||||
await scene.expectPixelColor(defaultPlaneColor, testPoint, 20)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
test(`Shell dry-run validation rejects sweeps`, async ({
|
||||
context,
|
||||
page,
|
||||
|
@ -1353,6 +1353,99 @@ test.describe(`Sketching with offset planes`, () => {
|
||||
})
|
||||
|
||||
test.describe('multi-profile sketching', () => {
|
||||
test(
|
||||
`test it removes half-finished expressions when changing tools in sketch mode`,
|
||||
{ tag: ['@skipWin'] },
|
||||
async ({ context, page, scene, toolbar, editor, homePage }) => {
|
||||
// We seed the scene with a single offset plane
|
||||
await context.addInitScript(() => {
|
||||
localStorage.setItem(
|
||||
'persistCode',
|
||||
`yo = 5
|
||||
sketch001 = startSketchOn('XZ')
|
||||
profile001 = startProfileAt([121.52, 168.25], sketch001)
|
||||
|> line(end = [115.04, 113.61])
|
||||
|> line(end = [130.87, -97.79])
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||
|> close()
|
||||
profile002 = startProfileAt([117.2, 56.08], sketch001)
|
||||
|> line(end = [166.82, 25.89])
|
||||
|> yLine(-107.86, %)
|
||||
|
||||
`
|
||||
)
|
||||
})
|
||||
|
||||
await homePage.goToModelingScene()
|
||||
await expect(
|
||||
page.getByRole('button', { name: 'Start Sketch' })
|
||||
).not.toBeDisabled()
|
||||
|
||||
await (await toolbar.getFeatureTreeOperation('Sketch', 0)).dblclick()
|
||||
await page.waitForTimeout(600)
|
||||
|
||||
const [circlePoint1] = scene.makeMouseHelpers(700, 200)
|
||||
|
||||
await test.step('equip circle tool and click first point', async () => {
|
||||
await toolbar.circleBtn.click()
|
||||
await page.waitForTimeout(100)
|
||||
await circlePoint1()
|
||||
await editor.expectEditor.toContain('profile003 = circle({ center = [')
|
||||
})
|
||||
|
||||
await test.step('equip line tool and verify circle code is removed', async () => {
|
||||
await toolbar.lineBtn.click()
|
||||
await editor.expectEditor.not.toContain('profile003 = circle({')
|
||||
})
|
||||
|
||||
const [circle3Point1] = scene.makeMouseHelpers(650, 200)
|
||||
const [circle3Point2] = scene.makeMouseHelpers(750, 200)
|
||||
|
||||
await test.step('equip three point circle tool and click first two points', async () => {
|
||||
await toolbar.selectCircleThreePoint()
|
||||
await page.waitForTimeout(100)
|
||||
await circle3Point1()
|
||||
await page.waitForTimeout(100)
|
||||
await circle3Point2()
|
||||
await editor.expectEditor.toContain('profile003 = circleThreePoint(')
|
||||
})
|
||||
|
||||
await test.step('equip line tool and verify three point circle code is removed', async () => {
|
||||
await toolbar.lineBtn.click()
|
||||
await editor.expectEditor.not.toContain(
|
||||
'profile003 = circleThreePoint('
|
||||
)
|
||||
})
|
||||
|
||||
const [cornerRectPoint1] = scene.makeMouseHelpers(600, 300)
|
||||
|
||||
await test.step('equip corner rectangle tool and click first point', async () => {
|
||||
await toolbar.rectangleBtn.click()
|
||||
await page.waitForTimeout(100)
|
||||
await cornerRectPoint1()
|
||||
await editor.expectEditor.toContain('profile003 = startProfileAt(')
|
||||
})
|
||||
|
||||
await test.step('equip line tool and verify corner rectangle code is removed', async () => {
|
||||
await toolbar.lineBtn.click()
|
||||
await editor.expectEditor.not.toContain('profile003 = startProfileAt(')
|
||||
})
|
||||
|
||||
const [centerRectPoint1] = scene.makeMouseHelpers(700, 300)
|
||||
|
||||
await test.step('equip center rectangle tool and click first point', async () => {
|
||||
await toolbar.selectCenterRectangle()
|
||||
await page.waitForTimeout(100)
|
||||
await centerRectPoint1()
|
||||
await editor.expectEditor.toContain('profile003 = startProfileAt(')
|
||||
})
|
||||
|
||||
await test.step('equip line tool and verify center rectangle code is removed', async () => {
|
||||
await toolbar.lineBtn.click()
|
||||
await editor.expectEditor.not.toContain('profile003 = startProfileAt(')
|
||||
})
|
||||
}
|
||||
)
|
||||
test(
|
||||
`snapToProfile start only works for current profile`,
|
||||
{ tag: ['@skipWin'] },
|
||||
@ -1885,7 +1978,7 @@ profile004 = circleThreePoint(sketch001, p1 = [13.44, -6.8], p2 = [13.39, -2.07]
|
||||
)
|
||||
test(
|
||||
'Can delete a profile in the editor while is sketch mode, and sketch mode does not break, can ctrl+z to undo after constraint with variable was added',
|
||||
{ tag: ['@skipWin'] },
|
||||
{ tag: ['@skipWin', '@skipLinux'] },
|
||||
async ({ scene, toolbar, editor, cmdBar, page, homePage }) => {
|
||||
await page.addInitScript(async () => {
|
||||
localStorage.setItem(
|
||||
@ -1936,9 +2029,6 @@ profile003 = circle({ center = [6.92, -4.2], radius = 3.16 }, sketch001)
|
||||
await moveToClearToolBarPopover()
|
||||
await pointOnSegment({ shouldDbClick: true })
|
||||
await page.waitForTimeout(600)
|
||||
|
||||
await toolbar.lineBtn.click()
|
||||
await page.waitForTimeout(100)
|
||||
})
|
||||
|
||||
await test.step('select and delete code for a profile', async () => {})
|
||||
@ -1969,7 +2059,7 @@ profile003 = circle({ center = [6.92, -4.2], radius = 3.16 }, sketch001)
|
||||
activeLines: ['|>line(end = [-0.41,6.99])'],
|
||||
highlightedCode: 'line(end = [-0.41,6.99])',
|
||||
})
|
||||
}).toPass({ timeout: 10_000, intervals: [1000] })
|
||||
}).toPass({ timeout: 30_000, intervals: [1500] })
|
||||
|
||||
await toolbar.lengthConstraintBtn.click()
|
||||
await cmdBar.progressCmdBar()
|
||||
|
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 76 KiB |
Before Width: | Height: | Size: 143 KiB After Width: | Height: | Size: 143 KiB |
Before Width: | Height: | Size: 127 KiB After Width: | Height: | Size: 127 KiB |
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 49 KiB |
@ -85,7 +85,7 @@
|
||||
"fmt": "prettier --write ./src *.ts *.json *.js ./e2e ./packages",
|
||||
"fmt-check": "prettier --check ./src *.ts *.json *.js ./e2e ./packages",
|
||||
"fetch:wasm": "./get-latest-wasm-bundle.sh",
|
||||
"fetch:samples": "echo \"Fetching latest KCL samples...\" && curl -o public/kcl-samples-manifest-fallback.json https://raw.githubusercontent.com/KittyCAD/kcl-samples/achalmers/offset-plane-kwargs/manifest.json",
|
||||
"fetch:samples": "echo \"Fetching latest KCL samples...\" && curl -o public/kcl-samples-manifest-fallback.json https://raw.githubusercontent.com/KittyCAD/kcl-samples/next/manifest.json",
|
||||
"isomorphic-copy-wasm": "(copy src/wasm-lib/pkg/wasm_lib_bg.wasm public || cp src/wasm-lib/pkg/wasm_lib_bg.wasm public)",
|
||||
"build:wasm-dev": "yarn wasm-prep && (cd src/wasm-lib && wasm-pack build --dev --target web --out-dir pkg && cargo test -p kcl-lib export_bindings) && yarn isomorphic-copy-wasm && yarn fmt",
|
||||
"build:wasm": "yarn wasm-prep && cd src/wasm-lib && wasm-pack build --release --target web --out-dir pkg && cargo test -p kcl-lib export_bindings && cd ../.. && yarn isomorphic-copy-wasm && yarn fmt",
|
||||
|
@ -20,10 +20,14 @@ export const kclHighlight = styleTags({
|
||||
LineComment: t.lineComment,
|
||||
BlockComment: t.blockComment,
|
||||
Shebang: t.meta,
|
||||
AnnotationName: t.annotation,
|
||||
PipeSubstitution: t.atom,
|
||||
VariableDefinition: t.definition(t.variableName),
|
||||
VariableName: t.variableName,
|
||||
PropertyName: t.propertyName,
|
||||
'AnnotationProperty/PropertyName': t.definition(t.propertyName),
|
||||
'ObjectProperty/PropertyName': t.definition(t.propertyName),
|
||||
'LabeledArgument/ArgumentLabel': t.definition(t.propertyName),
|
||||
TagDeclarator: t.tagName,
|
||||
'( )': t.paren,
|
||||
'{ }': t.brace,
|
||||
|
@ -34,6 +34,13 @@
|
||||
"title": "Car Wheel Assembly",
|
||||
"description": "A car wheel assembly with a rotor, tire, and lug nuts."
|
||||
},
|
||||
{
|
||||
"file": "main.kcl",
|
||||
"pathFromProjectDirectoryToFirstFile": "color-cube/main.kcl",
|
||||
"multipleFiles": false,
|
||||
"title": "Color Cube",
|
||||
"description": "This is a color cube centered about the origin. It is used to help determine orientation in the scene."
|
||||
},
|
||||
{
|
||||
"file": "main.kcl",
|
||||
"pathFromProjectDirectoryToFirstFile": "cycloidal-gear/main.kcl",
|
||||
|
@ -1,7 +1,6 @@
|
||||
import toast from 'react-hot-toast'
|
||||
import { ActionIcon, ActionIconProps } from './ActionIcon'
|
||||
import {
|
||||
MouseEvent,
|
||||
RefObject,
|
||||
useCallback,
|
||||
useEffect,
|
||||
@ -148,24 +147,22 @@ interface ContextMenuItemProps {
|
||||
onClick?: () => void
|
||||
hotkey?: string
|
||||
'data-testid'?: string
|
||||
disabled?: boolean
|
||||
}
|
||||
|
||||
export function ContextMenuItem(props: ContextMenuItemProps) {
|
||||
const { children, icon, onClick, hotkey } = props
|
||||
const { children, icon, onClick, hotkey, disabled } = props
|
||||
|
||||
return (
|
||||
<button
|
||||
disabled={disabled}
|
||||
data-testid={props['data-testid']}
|
||||
className="flex items-center gap-2 py-1 px-2 cursor-pointer hover:bg-chalkboard-20 dark:hover:bg-chalkboard-80 border-none text-left"
|
||||
onClick={onClick}
|
||||
onClick={disabled ? undefined : onClick}
|
||||
>
|
||||
{icon && <ActionIcon icon={icon} bgClassName="!bg-transparent" />}
|
||||
<div className="flex-1">{children}</div>
|
||||
{hotkey && (
|
||||
<kbd className="px-1.5 py-0.5 rounded bg-primary/10 text-primary dark:bg-chalkboard-80 dark:text-chalkboard-40">
|
||||
{hotkey}
|
||||
</kbd>
|
||||
)}
|
||||
{hotkey && <kbd className="hotkey">{hotkey}</kbd>}
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
@ -1574,7 +1574,7 @@ export const ModelingMachineProvider = ({
|
||||
: updatedSketchNodePaths[0]
|
||||
}
|
||||
|
||||
if (doesNeedSplitting) {
|
||||
if (doesNeedSplitting || indexToDelete >= 0) {
|
||||
await kclManager.executeAstMock(moddedAst)
|
||||
await codeManager.updateEditorWithAstAndWriteToFile(moddedAst)
|
||||
}
|
||||
|
@ -324,6 +324,20 @@ const OperationItem = (props: {
|
||||
}
|
||||
}
|
||||
|
||||
function deleteOperation() {
|
||||
if (
|
||||
props.item.type === 'StdLibCall' ||
|
||||
props.item.type === 'UserDefinedFunctionCall'
|
||||
) {
|
||||
props.send({
|
||||
type: 'deleteOperation',
|
||||
data: {
|
||||
targetSourceRange: sourceRangeFromRust(props.item.sourceRange),
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const menuItems = useMemo(
|
||||
() => [
|
||||
<ContextMenuItem
|
||||
@ -364,14 +378,24 @@ const OperationItem = (props: {
|
||||
</ContextMenuItem>,
|
||||
]
|
||||
: []),
|
||||
...(props.item.type === 'StdLibCall' &&
|
||||
stdLibMap[props.item.name]?.prepareToEdit
|
||||
...(props.item.type === 'StdLibCall'
|
||||
? [
|
||||
<ContextMenuItem onClick={enterEditFlow}>
|
||||
Edit {name}
|
||||
<ContextMenuItem
|
||||
disabled={!stdLibMap[props.item.name]?.prepareToEdit}
|
||||
onClick={enterEditFlow}
|
||||
hotkey="Double click"
|
||||
>
|
||||
Edit
|
||||
</ContextMenuItem>,
|
||||
]
|
||||
: []),
|
||||
<ContextMenuItem
|
||||
onClick={deleteOperation}
|
||||
hotkey="Delete"
|
||||
data-testid="context-menu-delete"
|
||||
>
|
||||
Delete
|
||||
</ContextMenuItem>,
|
||||
],
|
||||
[props.item, props.send]
|
||||
)
|
||||
|
@ -54,9 +54,27 @@ describe('processMemory', () => {
|
||||
},
|
||||
],
|
||||
theSketch: [
|
||||
{ type: 'ToPoint', to: [-3.35, 0.17], from: [0, 0], tag: null },
|
||||
{ type: 'ToPoint', to: [0.98, 5.16], from: [-3.35, 0.17], tag: null },
|
||||
{ type: 'ToPoint', to: [2.15, 4.32], from: [0.98, 5.16], tag: null },
|
||||
{
|
||||
type: 'ToPoint',
|
||||
to: [-3.35, 0.17],
|
||||
from: [0, 0],
|
||||
units: { type: 'Mm' },
|
||||
tag: null,
|
||||
},
|
||||
{
|
||||
type: 'ToPoint',
|
||||
to: [0.98, 5.16],
|
||||
from: [-3.35, 0.17],
|
||||
units: { type: 'Mm' },
|
||||
tag: null,
|
||||
},
|
||||
{
|
||||
type: 'ToPoint',
|
||||
to: [2.15, 4.32],
|
||||
from: [0.98, 5.16],
|
||||
units: { type: 'Mm' },
|
||||
tag: null,
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
@ -20,7 +20,7 @@ import {
|
||||
getSettingsFolderPaths,
|
||||
} from 'lib/desktopFS'
|
||||
import { useDotDotSlash } from 'hooks/useDotDotSlash'
|
||||
import { ForwardedRef, forwardRef, useEffect } from 'react'
|
||||
import { ForwardedRef, forwardRef, useEffect, useMemo } from 'react'
|
||||
import { useLspContext } from 'components/LspProvider'
|
||||
import { toSync } from 'lib/utils'
|
||||
import { reportRejection } from 'lib/trap'
|
||||
@ -44,20 +44,22 @@ export const AllSettingsFields = forwardRef(
|
||||
settings: { send, context, state },
|
||||
} = useSettingsAuthContext()
|
||||
|
||||
const projectPath =
|
||||
isFileSettings && isDesktop()
|
||||
? decodeURI(
|
||||
location.pathname
|
||||
.replace(PATHS.FILE + window.electron.sep, '')
|
||||
.replace(PATHS.SETTINGS, '')
|
||||
.slice(
|
||||
0,
|
||||
decodeURI(location.pathname).lastIndexOf(
|
||||
window.electron.path.sep
|
||||
)
|
||||
)
|
||||
)
|
||||
: undefined
|
||||
const projectPath = useMemo(() => {
|
||||
const filteredPathname = location.pathname
|
||||
.replace(PATHS.FILE, '')
|
||||
.replace(PATHS.SETTINGS, '')
|
||||
const lastSlashIndex = filteredPathname.lastIndexOf(
|
||||
// This is slicing off any remaining browser path segments,
|
||||
// so we don't use window.electron.sep here
|
||||
'/'
|
||||
)
|
||||
const projectPath =
|
||||
isFileSettings && isDesktop()
|
||||
? decodeURIComponent(filteredPathname.slice(lastSlashIndex + 1))
|
||||
: undefined
|
||||
|
||||
return projectPath
|
||||
}, [location.pathname])
|
||||
|
||||
function restartOnboarding() {
|
||||
send({
|
||||
@ -197,9 +199,7 @@ export const AllSettingsFields = forwardRef(
|
||||
<ActionButton
|
||||
Element="button"
|
||||
onClick={toSync(async () => {
|
||||
const paths = await getSettingsFolderPaths(
|
||||
projectPath ? decodeURIComponent(projectPath) : undefined
|
||||
)
|
||||
const paths = await getSettingsFolderPaths(projectPath)
|
||||
const finalPath = paths[searchParamTab]
|
||||
if (!finalPath) {
|
||||
return new Error('finalPath undefined')
|
||||
|
@ -24,6 +24,7 @@ const mySketch001 = startSketchOn('XY')
|
||||
start: {
|
||||
to: [0, 0],
|
||||
from: [0, 0],
|
||||
units: { type: 'Mm' },
|
||||
tag: null,
|
||||
__geoMeta: {
|
||||
id: expect.any(String),
|
||||
@ -35,6 +36,7 @@ const mySketch001 = startSketchOn('XY')
|
||||
type: 'ToPoint',
|
||||
tag: null,
|
||||
to: [-1.59, -1.54],
|
||||
units: { type: 'Mm' },
|
||||
from: [0, 0],
|
||||
__geoMeta: {
|
||||
sourceRange: [expect.any(Number), expect.any(Number), 0],
|
||||
@ -45,6 +47,7 @@ const mySketch001 = startSketchOn('XY')
|
||||
type: 'ToPoint',
|
||||
to: [0.46, -5.82],
|
||||
from: [-1.59, -1.54],
|
||||
units: { type: 'Mm' },
|
||||
tag: null,
|
||||
__geoMeta: {
|
||||
sourceRange: [expect.any(Number), expect.any(Number), 0],
|
||||
@ -111,6 +114,7 @@ const mySketch001 = startSketchOn('XY')
|
||||
type: 'ToPoint',
|
||||
from: [0, 0],
|
||||
to: [-1.59, -1.54],
|
||||
units: { type: 'Mm' },
|
||||
tag: null,
|
||||
__geoMeta: {
|
||||
id: expect.any(String),
|
||||
@ -121,6 +125,7 @@ const mySketch001 = startSketchOn('XY')
|
||||
type: 'ToPoint',
|
||||
from: [-1.59, -1.54],
|
||||
to: [0.46, -5.82],
|
||||
units: { type: 'Mm' },
|
||||
tag: null,
|
||||
__geoMeta: {
|
||||
id: expect.any(String),
|
||||
@ -229,6 +234,7 @@ const sk2 = startSketchOn('XY')
|
||||
type: 'ToPoint',
|
||||
from: [0, 0],
|
||||
to: [-2.5, 0],
|
||||
units: { type: 'Mm' },
|
||||
tag: null,
|
||||
__geoMeta: {
|
||||
id: expect.any(String),
|
||||
@ -239,6 +245,7 @@ const sk2 = startSketchOn('XY')
|
||||
type: 'ToPoint',
|
||||
from: [-2.5, 0],
|
||||
to: [0, 10],
|
||||
units: { type: 'Mm' },
|
||||
tag: {
|
||||
end: expect.any(Number),
|
||||
start: expect.any(Number),
|
||||
@ -254,6 +261,7 @@ const sk2 = startSketchOn('XY')
|
||||
type: 'ToPoint',
|
||||
from: [0, 10],
|
||||
to: [2.5, 0],
|
||||
units: { type: 'Mm' },
|
||||
tag: null,
|
||||
__geoMeta: {
|
||||
id: expect.any(String),
|
||||
@ -335,6 +343,7 @@ const sk2 = startSketchOn('XY')
|
||||
type: 'ToPoint',
|
||||
from: [0, 0],
|
||||
to: [-2.5, 0],
|
||||
units: { type: 'Mm' },
|
||||
tag: null,
|
||||
__geoMeta: {
|
||||
id: expect.any(String),
|
||||
@ -345,6 +354,7 @@ const sk2 = startSketchOn('XY')
|
||||
type: 'ToPoint',
|
||||
from: [-2.5, 0],
|
||||
to: [0, 3],
|
||||
units: { type: 'Mm' },
|
||||
tag: {
|
||||
end: expect.any(Number),
|
||||
start: expect.any(Number),
|
||||
@ -360,6 +370,7 @@ const sk2 = startSketchOn('XY')
|
||||
type: 'ToPoint',
|
||||
from: [0, 3],
|
||||
to: [2.5, 0],
|
||||
units: { type: 'Mm' },
|
||||
tag: null,
|
||||
__geoMeta: {
|
||||
id: expect.any(String),
|
||||
|
@ -72,6 +72,7 @@ const newVar = myVar + 1`
|
||||
type: 'ToPoint',
|
||||
to: [0, 2],
|
||||
from: [0, 0],
|
||||
units: { type: 'Mm' },
|
||||
__geoMeta: {
|
||||
sourceRange: [expect.any(Number), expect.any(Number), 0],
|
||||
id: expect.any(String),
|
||||
@ -87,6 +88,7 @@ const newVar = myVar + 1`
|
||||
type: 'ToPoint',
|
||||
to: [2, 3],
|
||||
from: [0, 2],
|
||||
units: { type: 'Mm' },
|
||||
tag: null,
|
||||
__geoMeta: {
|
||||
sourceRange: [expect.any(Number), expect.any(Number), 0],
|
||||
@ -97,6 +99,7 @@ const newVar = myVar + 1`
|
||||
type: 'ToPoint',
|
||||
to: [5, -1],
|
||||
from: [2, 3],
|
||||
units: { type: 'Mm' },
|
||||
__geoMeta: {
|
||||
sourceRange: [expect.any(Number), expect.any(Number), 0],
|
||||
id: expect.any(String),
|
||||
@ -165,6 +168,7 @@ const newVar = myVar + 1`
|
||||
start: {
|
||||
to: [0, 0],
|
||||
from: [0, 0],
|
||||
units: { type: 'Mm' },
|
||||
tag: null,
|
||||
__geoMeta: {
|
||||
id: expect.any(String),
|
||||
@ -188,6 +192,7 @@ const newVar = myVar + 1`
|
||||
type: 'ToPoint',
|
||||
to: [1, 1],
|
||||
from: [0, 0],
|
||||
units: { type: 'Mm' },
|
||||
tag: null,
|
||||
__geoMeta: {
|
||||
sourceRange: [expect.any(Number), expect.any(Number), 0],
|
||||
@ -198,6 +203,7 @@ const newVar = myVar + 1`
|
||||
type: 'ToPoint',
|
||||
to: [0, 1],
|
||||
from: [1, 1],
|
||||
units: { type: 'Mm' },
|
||||
__geoMeta: {
|
||||
sourceRange: [expect.any(Number), expect.any(Number), 0],
|
||||
id: expect.any(String),
|
||||
@ -213,6 +219,7 @@ const newVar = myVar + 1`
|
||||
type: 'ToPoint',
|
||||
to: [1, 1],
|
||||
from: [0, 1],
|
||||
units: { type: 'Mm' },
|
||||
tag: null,
|
||||
__geoMeta: {
|
||||
sourceRange: [expect.any(Number), expect.any(Number), 0],
|
||||
|
@ -32,7 +32,7 @@ child_process.spawnSync('git', [
|
||||
'clone',
|
||||
'--single-branch',
|
||||
'--branch',
|
||||
'achalmers/offset-plane-kwargs',
|
||||
'next',
|
||||
URL_GIT_KCL_SAMPLES,
|
||||
DIR_KCL_SAMPLES,
|
||||
])
|
||||
|
38
src/lang/modifyAst/deleteSelection.ts
Normal file
@ -0,0 +1,38 @@
|
||||
import { Selection } from 'lib/selections'
|
||||
import { getFaceDetails } from 'clientSideScene/sceneEntities'
|
||||
import { deleteFromSelection } from 'lang/modifyAst'
|
||||
import { codeManager, engineCommandManager, kclManager } from 'lib/singletons'
|
||||
import { err } from 'lib/trap'
|
||||
import { executeAst } from 'lang/langHelpers'
|
||||
|
||||
export const deletionErrorMessage =
|
||||
'Unable to delete selection. Please edit manually in code pane.'
|
||||
|
||||
export async function deleteSelectionPromise(
|
||||
selection: Selection
|
||||
): Promise<Error | void> {
|
||||
let ast = kclManager.ast
|
||||
|
||||
const modifiedAst = await deleteFromSelection(
|
||||
ast,
|
||||
selection,
|
||||
kclManager.variables,
|
||||
engineCommandManager.artifactGraph,
|
||||
getFaceDetails
|
||||
)
|
||||
if (err(modifiedAst)) {
|
||||
return new Error(deletionErrorMessage)
|
||||
}
|
||||
|
||||
const testExecute = await executeAst({
|
||||
ast: modifiedAst,
|
||||
engineCommandManager,
|
||||
isMock: true,
|
||||
})
|
||||
if (testExecute.errors.length) {
|
||||
return new Error(deletionErrorMessage)
|
||||
}
|
||||
|
||||
await kclManager.updateAst(modifiedAst, true)
|
||||
await codeManager.updateEditorWithAstAndWriteToFile(modifiedAst)
|
||||
}
|
@ -386,6 +386,7 @@ part001 = startSketchOn('XY')
|
||||
type: 'ToPoint',
|
||||
to: [5.62, 1.79],
|
||||
from: [3.48, 0.44],
|
||||
units: { type: 'Mm' },
|
||||
tag: null,
|
||||
})
|
||||
})
|
||||
@ -401,6 +402,7 @@ part001 = startSketchOn('XY')
|
||||
expect(segment).toEqual({
|
||||
to: [0, 0.04],
|
||||
from: [0, 0.04],
|
||||
units: { type: 'Mm' },
|
||||
tag: null,
|
||||
type: 'Base',
|
||||
})
|
||||
|
@ -106,6 +106,7 @@ export type ModelingCommandSchema = {
|
||||
prompt: string
|
||||
selection: Selections
|
||||
}
|
||||
'Delete selection': {}
|
||||
}
|
||||
|
||||
export const modelingMachineCommandConfig: StateMachineCommandSetConfig<
|
||||
|
@ -375,14 +375,7 @@ export const toolbarConfig: Record<ToolbarModeName, ToolbarMode> = {
|
||||
},
|
||||
icon: 'line',
|
||||
status: 'available',
|
||||
disabled: (state) =>
|
||||
state.matches('Sketch no face') ||
|
||||
state.matches({
|
||||
Sketch: { 'Rectangle tool': 'Awaiting second corner' },
|
||||
}) ||
|
||||
state.matches({
|
||||
Sketch: { 'Circle tool': 'Awaiting Radius' },
|
||||
}),
|
||||
disabled: (state) => state.matches('Sketch no face'),
|
||||
title: 'Line',
|
||||
hotkey: (state) =>
|
||||
state.matches({ Sketch: 'Line tool' }) ? ['Esc', 'L'] : 'L',
|
||||
|
@ -44,7 +44,6 @@ import {
|
||||
addHelix,
|
||||
addOffsetPlane,
|
||||
addSweep,
|
||||
deleteFromSelection,
|
||||
extrudeSketch,
|
||||
loftSketches,
|
||||
} from 'lang/modifyAst'
|
||||
@ -70,12 +69,10 @@ import {
|
||||
} from 'components/Toolbar/SetAbsDistance'
|
||||
import { ModelingCommandSchema } from 'lib/commandBarConfigs/modelingCommandConfig'
|
||||
import { err, reportRejection, trap } from 'lib/trap'
|
||||
import { getFaceDetails } from 'clientSideScene/sceneEntities'
|
||||
import { DefaultPlaneStr } from 'lib/planes'
|
||||
import { uuidv4 } from 'lib/utils'
|
||||
import { Coords2d } from 'lang/std/sketch'
|
||||
import { deleteSegment } from 'clientSideScene/ClientSideSceneComp'
|
||||
import { executeAst } from 'lang/langHelpers'
|
||||
import toast from 'react-hot-toast'
|
||||
import { ToolbarModeName } from 'lib/toolbar'
|
||||
import { quaternionFromUpNForward } from 'clientSideScene/helpers'
|
||||
@ -83,6 +80,11 @@ import { Mesh, Vector3 } from 'three'
|
||||
import { MachineManager } from 'components/MachineManagerProvider'
|
||||
import { addShell } from 'lang/modifyAst/addShell'
|
||||
import { KclCommandValue } from 'lib/commandTypes'
|
||||
import { ModelingMachineContext } from 'components/ModelingMachineProvider'
|
||||
import {
|
||||
deleteSelectionPromise,
|
||||
deletionErrorMessage,
|
||||
} from 'lang/modifyAst/deleteSelection'
|
||||
import { getPathsFromPlaneArtifact } from 'lang/std/artifactGraph'
|
||||
import { createProfileStartHandle } from 'clientSideScene/segments'
|
||||
import { DRAFT_POINT } from 'clientSideScene/sceneInfra'
|
||||
@ -308,6 +310,10 @@ export type ModelingMachineEvent =
|
||||
| { type: 'Helix'; data: ModelingCommandSchema['Helix'] }
|
||||
| { type: 'Text-to-CAD'; data: ModelingCommandSchema['Text-to-CAD'] }
|
||||
| { type: 'Prompt-to-edit'; data: ModelingCommandSchema['Prompt-to-edit'] }
|
||||
| {
|
||||
type: 'Delete selection'
|
||||
data: ModelingCommandSchema['Delete selection']
|
||||
}
|
||||
| {
|
||||
type: 'Add rectangle origin'
|
||||
data: [x: number, y: number]
|
||||
@ -731,38 +737,6 @@ export const modelingMachine = setup({
|
||||
}
|
||||
})().catch(reportRejection)
|
||||
},
|
||||
'AST delete selection': ({ context: { selectionRanges } }) => {
|
||||
;(async () => {
|
||||
const errorMessage =
|
||||
'Unable to delete selection. Please edit manually in code pane.'
|
||||
let ast = kclManager.ast
|
||||
|
||||
const modifiedAst = await deleteFromSelection(
|
||||
ast,
|
||||
selectionRanges.graphSelections[0],
|
||||
kclManager.variables,
|
||||
engineCommandManager.artifactGraph,
|
||||
getFaceDetails
|
||||
)
|
||||
if (err(modifiedAst)) {
|
||||
toast.error(errorMessage)
|
||||
return
|
||||
}
|
||||
|
||||
const testExecute = await executeAst({
|
||||
ast: modifiedAst,
|
||||
engineCommandManager,
|
||||
isMock: true,
|
||||
})
|
||||
if (testExecute.errors.length) {
|
||||
toast.error(errorMessage)
|
||||
return
|
||||
}
|
||||
|
||||
await kclManager.updateAst(modifiedAst, true)
|
||||
await codeManager.updateEditorWithAstAndWriteToFile(modifiedAst)
|
||||
})().catch(reportRejection)
|
||||
},
|
||||
'set selection filter to curves only': () => {
|
||||
;(async () => {
|
||||
await engineCommandManager.sendSceneCommand({
|
||||
@ -2170,6 +2144,34 @@ export const modelingMachine = setup({
|
||||
input: ModelingCommandSchema['Prompt-to-edit']
|
||||
}) => {}
|
||||
),
|
||||
deleteSelectionAstMod: fromPromise(
|
||||
({
|
||||
input: { selectionRanges },
|
||||
}: {
|
||||
input: { selectionRanges: Selections }
|
||||
}) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!selectionRanges) {
|
||||
reject(new Error(deletionErrorMessage))
|
||||
}
|
||||
|
||||
const selection = selectionRanges.graphSelections[0]
|
||||
if (!selectionRanges) {
|
||||
reject(new Error(deletionErrorMessage))
|
||||
}
|
||||
|
||||
deleteSelectionPromise(selection)
|
||||
.then((result) => {
|
||||
if (err(result)) {
|
||||
reject(result)
|
||||
return
|
||||
}
|
||||
resolve(result)
|
||||
})
|
||||
.catch(reject)
|
||||
})
|
||||
}
|
||||
),
|
||||
},
|
||||
// end actors
|
||||
}).createMachine({
|
||||
@ -2243,10 +2245,9 @@ export const modelingMachine = setup({
|
||||
},
|
||||
|
||||
'Delete selection': {
|
||||
target: 'idle',
|
||||
target: 'Applying Delete selection',
|
||||
guard: 'has valid selection for deletion',
|
||||
actions: ['AST delete selection'],
|
||||
reenter: false,
|
||||
reenter: true,
|
||||
},
|
||||
|
||||
'Text-to-CAD': {
|
||||
@ -3366,6 +3367,28 @@ export const modelingMachine = setup({
|
||||
onError: 'idle',
|
||||
},
|
||||
},
|
||||
|
||||
'Applying Delete selection': {
|
||||
invoke: {
|
||||
src: 'deleteSelectionAstMod',
|
||||
id: 'deleteSelectionAstMod',
|
||||
|
||||
input: ({ event, context }) => {
|
||||
return { selectionRanges: context.selectionRanges }
|
||||
},
|
||||
|
||||
onDone: 'idle',
|
||||
onError: {
|
||||
target: 'idle',
|
||||
reenter: true,
|
||||
actions: ({ event }) => {
|
||||
if ('error' in event && err(event.error)) {
|
||||
toast.error(event.error.message)
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
initial: 'idle',
|
||||
|
@ -82,7 +82,7 @@ const createWindow = (pathToOpen?: string, reuse?: boolean): BrowserWindow => {
|
||||
}
|
||||
if (!newWindow) {
|
||||
newWindow = new BrowserWindow({
|
||||
autoHideMenuBar: true,
|
||||
autoHideMenuBar: false,
|
||||
show: false,
|
||||
width: 1800,
|
||||
height: 1200,
|
||||
|
70
src/wasm-lib/Cargo.lock
generated
@ -34,7 +34,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"getrandom",
|
||||
"getrandom 0.2.15",
|
||||
"once_cell",
|
||||
"version_check",
|
||||
"zerocopy",
|
||||
@ -715,9 +715,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "data-encoding"
|
||||
version = "2.7.0"
|
||||
version = "2.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e60eed09d8c01d3cee5b7d30acb059b76614c918fa0f992e0dd6eeb10daad6f"
|
||||
checksum = "575f75dfd25738df5b91b8e43e14d44bda14637a58fae779fd2b064f8bf3e010"
|
||||
|
||||
[[package]]
|
||||
name = "deranged"
|
||||
@ -730,7 +730,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "derive-docs"
|
||||
version = "0.1.36"
|
||||
version = "0.1.38"
|
||||
dependencies = [
|
||||
"Inflector",
|
||||
"anyhow",
|
||||
@ -1080,10 +1080,22 @@ dependencies = [
|
||||
"cfg-if",
|
||||
"js-sys",
|
||||
"libc",
|
||||
"wasi",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi 0.13.3+wasi-0.2.2",
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.31.1"
|
||||
@ -1712,7 +1724,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-lib"
|
||||
version = "0.2.35"
|
||||
version = "0.2.38"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"approx 0.5.1",
|
||||
@ -1779,7 +1791,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kcl-test-server"
|
||||
version = "0.1.21"
|
||||
version = "0.1.38"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"hyper 0.14.32",
|
||||
@ -1846,9 +1858,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kittycad-modeling-cmds"
|
||||
version = "0.2.93"
|
||||
version = "0.2.97"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "67a993046541732e3c3ddd8a0364b55b7b138a9258beff353b6e7a043a41dce3"
|
||||
checksum = "6c37ad10b8a2afdcd1852d027f123cf4e38864ea93e0fda5c7ee1e8a49af49fb"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"chrono",
|
||||
@ -2094,7 +2106,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"wasi",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
@ -2688,7 +2700,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2fe5ef3495d7d2e377ff17b1a8ce2ee2ec2a18cde8b6ad6619d65d0701c135d"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"getrandom",
|
||||
"getrandom 0.2.15",
|
||||
"rand 0.8.5",
|
||||
"ring",
|
||||
"rustc-hash 2.1.0",
|
||||
@ -2785,7 +2797,7 @@ version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"getrandom 0.2.15",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2965,7 +2977,7 @@ dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
"futures",
|
||||
"getrandom",
|
||||
"getrandom 0.2.15",
|
||||
"http 1.2.0",
|
||||
"hyper 1.5.2",
|
||||
"parking_lot 0.11.2",
|
||||
@ -2986,7 +2998,7 @@ checksum = "73e6153390585f6961341b50e5a1931d6be6dee4292283635903c26ef9d980d2"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
"getrandom",
|
||||
"getrandom 0.2.15",
|
||||
"http 1.2.0",
|
||||
"matchit",
|
||||
"opentelemetry",
|
||||
@ -3019,7 +3031,7 @@ checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cfg-if",
|
||||
"getrandom",
|
||||
"getrandom 0.2.15",
|
||||
"libc",
|
||||
"spin",
|
||||
"untrusted",
|
||||
@ -3605,7 +3617,7 @@ checksum = "9a8a559c81686f576e8cd0290cd2a24a2a9ad80c98b3478856500fcbd7acd704"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"fastrand",
|
||||
"getrandom",
|
||||
"getrandom 0.2.15",
|
||||
"once_cell",
|
||||
"rustix",
|
||||
"windows-sys 0.59.0",
|
||||
@ -4196,11 +4208,12 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||
|
||||
[[package]]
|
||||
name = "uuid"
|
||||
version = "1.12.1"
|
||||
version = "1.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b3758f5e68192bb96cc8f9b7e2c2cfdabb435499a28499a42f8f984092adad4b"
|
||||
checksum = "ced87ca4be083373936a67f8de945faa23b6b42384bd5b64434850802c6dccd0"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"getrandom 0.3.1",
|
||||
"js-sys",
|
||||
"serde",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
@ -4272,6 +4285,15 @@ version = "0.11.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.13.3+wasi-0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2"
|
||||
dependencies = [
|
||||
"wit-bindgen-rt",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.100"
|
||||
@ -4353,6 +4375,7 @@ dependencies = [
|
||||
"console_error_panic_hook",
|
||||
"data-encoding",
|
||||
"futures",
|
||||
"getrandom 0.2.15",
|
||||
"gloo-utils",
|
||||
"image",
|
||||
"js-sys",
|
||||
@ -4592,6 +4615,15 @@ dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wit-bindgen-rt"
|
||||
version = "0.33.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c"
|
||||
dependencies = [
|
||||
"bitflags 2.8.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "write16"
|
||||
version = "1.0.0"
|
||||
|
@ -39,6 +39,8 @@ dhat-heap = ["kcl-lib/dhat-heap"]
|
||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||
console_error_panic_hook = "0.1.7"
|
||||
futures = "0.3.31"
|
||||
# Enable the feature in a transitive dependency.
|
||||
getrandom = { version = "0.2", features = ["js"] }
|
||||
js-sys = "0.3.72"
|
||||
tower-lsp = { version = "0.20.0", default-features = false, features = ["runtime-agnostic"] }
|
||||
wasm-bindgen-futures = { version = "0.4.44", features = ["futures-core-03-stream"] }
|
||||
@ -78,7 +80,7 @@ members = [
|
||||
[workspace.dependencies]
|
||||
http = "1"
|
||||
kittycad = { version = "0.3.28", default-features = false, features = ["js", "requests"] }
|
||||
kittycad-modeling-cmds = { version = "0.2.93", features = [
|
||||
kittycad-modeling-cmds = { version = "0.2.97", features = [
|
||||
"ts-rs",
|
||||
"websocket",
|
||||
] }
|
||||
|
@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "derive-docs"
|
||||
description = "A tool for generating documentation from Rust derive macros"
|
||||
version = "0.1.36"
|
||||
version = "0.1.38"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
repository = "https://github.com/KittyCAD/modeling-app"
|
||||
|
@ -328,7 +328,7 @@ fn do_stdlib_inner(
|
||||
let label_required = !(i == 0 && metadata.unlabeled_first);
|
||||
if ty_string != "ExecState" && ty_string != "Args" {
|
||||
let schema = quote! {
|
||||
generator.root_schema_for::<#ty_ident>()
|
||||
#docs_crate::cleanup_number_tuples_root(generator.root_schema_for::<#ty_ident>())
|
||||
};
|
||||
arg_types.push(quote! {
|
||||
#docs_crate::StdLibFnArg {
|
||||
@ -393,7 +393,7 @@ fn do_stdlib_inner(
|
||||
let return_type = if !ret_ty_string.is_empty() || ret_ty_string != "()" {
|
||||
let ret_ty_string = rust_type_to_openapi_type(&ret_ty_string);
|
||||
quote! {
|
||||
let schema = generator.root_schema_for::<#return_type_inner>();
|
||||
let schema = #docs_crate::cleanup_number_tuples_root(generator.root_schema_for::<#return_type_inner>());
|
||||
Some(#docs_crate::StdLibFnArg {
|
||||
name: "".to_string(),
|
||||
type_: #ret_ty_string.to_string(),
|
||||
|
@ -111,7 +111,7 @@ impl crate::docs::StdLibFn for SomeFn {
|
||||
vec![crate::docs::StdLibFnArg {
|
||||
name: "data".to_string(),
|
||||
type_: "Foo".to_string(),
|
||||
schema: generator.root_schema_for::<Foo>(),
|
||||
schema: crate::docs::cleanup_number_tuples_root(generator.root_schema_for::<Foo>()),
|
||||
required: true,
|
||||
label_required: true,
|
||||
description: String::new().to_string(),
|
||||
@ -123,7 +123,7 @@ impl crate::docs::StdLibFn for SomeFn {
|
||||
let mut settings = schemars::gen::SchemaSettings::openapi3();
|
||||
settings.inline_subschemas = inline_subschemas;
|
||||
let mut generator = schemars::gen::SchemaGenerator::new(settings);
|
||||
let schema = generator.root_schema_for::<i32>();
|
||||
let schema = crate::docs::cleanup_number_tuples_root(generator.root_schema_for::<i32>());
|
||||
Some(crate::docs::StdLibFnArg {
|
||||
name: "".to_string(),
|
||||
type_: "i32".to_string(),
|
||||
|
@ -111,7 +111,7 @@ impl crate::docs::StdLibFn for SomeFn {
|
||||
vec![crate::docs::StdLibFnArg {
|
||||
name: "data".to_string(),
|
||||
type_: "string".to_string(),
|
||||
schema: generator.root_schema_for::<str>(),
|
||||
schema: crate::docs::cleanup_number_tuples_root(generator.root_schema_for::<str>()),
|
||||
required: true,
|
||||
label_required: true,
|
||||
description: String::new().to_string(),
|
||||
@ -123,7 +123,7 @@ impl crate::docs::StdLibFn for SomeFn {
|
||||
let mut settings = schemars::gen::SchemaSettings::openapi3();
|
||||
settings.inline_subschemas = inline_subschemas;
|
||||
let mut generator = schemars::gen::SchemaGenerator::new(settings);
|
||||
let schema = generator.root_schema_for::<i32>();
|
||||
let schema = crate::docs::cleanup_number_tuples_root(generator.root_schema_for::<i32>());
|
||||
Some(crate::docs::StdLibFnArg {
|
||||
name: "".to_string(),
|
||||
type_: "i32".to_string(),
|
||||
|
@ -172,7 +172,9 @@ impl crate::docs::StdLibFn for Show {
|
||||
vec![crate::docs::StdLibFnArg {
|
||||
name: "args".to_string(),
|
||||
type_: "[number]".to_string(),
|
||||
schema: generator.root_schema_for::<[f64; 2usize]>(),
|
||||
schema: crate::docs::cleanup_number_tuples_root(
|
||||
generator.root_schema_for::<[f64; 2usize]>(),
|
||||
),
|
||||
required: true,
|
||||
label_required: true,
|
||||
description: String::new().to_string(),
|
||||
@ -184,7 +186,7 @@ impl crate::docs::StdLibFn for Show {
|
||||
let mut settings = schemars::gen::SchemaSettings::openapi3();
|
||||
settings.inline_subschemas = inline_subschemas;
|
||||
let mut generator = schemars::gen::SchemaGenerator::new(settings);
|
||||
let schema = generator.root_schema_for::<f64>();
|
||||
let schema = crate::docs::cleanup_number_tuples_root(generator.root_schema_for::<f64>());
|
||||
Some(crate::docs::StdLibFnArg {
|
||||
name: "".to_string(),
|
||||
type_: "number".to_string(),
|
||||
|
@ -112,7 +112,7 @@ impl crate::docs::StdLibFn for Show {
|
||||
vec![crate::docs::StdLibFnArg {
|
||||
name: "args".to_string(),
|
||||
type_: "number".to_string(),
|
||||
schema: generator.root_schema_for::<f64>(),
|
||||
schema: crate::docs::cleanup_number_tuples_root(generator.root_schema_for::<f64>()),
|
||||
required: true,
|
||||
label_required: true,
|
||||
description: String::new().to_string(),
|
||||
@ -124,7 +124,7 @@ impl crate::docs::StdLibFn for Show {
|
||||
let mut settings = schemars::gen::SchemaSettings::openapi3();
|
||||
settings.inline_subschemas = inline_subschemas;
|
||||
let mut generator = schemars::gen::SchemaGenerator::new(settings);
|
||||
let schema = generator.root_schema_for::<f64>();
|
||||
let schema = crate::docs::cleanup_number_tuples_root(generator.root_schema_for::<f64>());
|
||||
Some(crate::docs::StdLibFnArg {
|
||||
name: "".to_string(),
|
||||
type_: "number".to_string(),
|
||||
|
@ -173,7 +173,9 @@ impl crate::docs::StdLibFn for MyFunc {
|
||||
vec![crate::docs::StdLibFnArg {
|
||||
name: "args".to_string(),
|
||||
type_: "kittycad::types::InputFormat".to_string(),
|
||||
schema: generator.root_schema_for::<Option<kittycad::types::InputFormat>>(),
|
||||
schema: crate::docs::cleanup_number_tuples_root(
|
||||
generator.root_schema_for::<Option<kittycad::types::InputFormat>>(),
|
||||
),
|
||||
required: false,
|
||||
label_required: true,
|
||||
description: String::new().to_string(),
|
||||
@ -185,7 +187,8 @@ impl crate::docs::StdLibFn for MyFunc {
|
||||
let mut settings = schemars::gen::SchemaSettings::openapi3();
|
||||
settings.inline_subschemas = inline_subschemas;
|
||||
let mut generator = schemars::gen::SchemaGenerator::new(settings);
|
||||
let schema = generator.root_schema_for::<Vec<Sketch>>();
|
||||
let schema =
|
||||
crate::docs::cleanup_number_tuples_root(generator.root_schema_for::<Vec<Sketch>>());
|
||||
Some(crate::docs::StdLibFnArg {
|
||||
name: "".to_string(),
|
||||
type_: "[Sketch]".to_string(),
|
||||
|
@ -174,7 +174,9 @@ impl crate::docs::StdLibFn for LineTo {
|
||||
crate::docs::StdLibFnArg {
|
||||
name: "data".to_string(),
|
||||
type_: "LineToData".to_string(),
|
||||
schema: generator.root_schema_for::<LineToData>(),
|
||||
schema: crate::docs::cleanup_number_tuples_root(
|
||||
generator.root_schema_for::<LineToData>(),
|
||||
),
|
||||
required: true,
|
||||
label_required: true,
|
||||
description: String::new().to_string(),
|
||||
@ -183,7 +185,9 @@ impl crate::docs::StdLibFn for LineTo {
|
||||
crate::docs::StdLibFnArg {
|
||||
name: "sketch".to_string(),
|
||||
type_: "Sketch".to_string(),
|
||||
schema: generator.root_schema_for::<Sketch>(),
|
||||
schema: crate::docs::cleanup_number_tuples_root(
|
||||
generator.root_schema_for::<Sketch>(),
|
||||
),
|
||||
required: true,
|
||||
label_required: true,
|
||||
description: "the sketch you're adding the line to".to_string(),
|
||||
@ -196,7 +200,7 @@ impl crate::docs::StdLibFn for LineTo {
|
||||
let mut settings = schemars::gen::SchemaSettings::openapi3();
|
||||
settings.inline_subschemas = inline_subschemas;
|
||||
let mut generator = schemars::gen::SchemaGenerator::new(settings);
|
||||
let schema = generator.root_schema_for::<Sketch>();
|
||||
let schema = crate::docs::cleanup_number_tuples_root(generator.root_schema_for::<Sketch>());
|
||||
Some(crate::docs::StdLibFnArg {
|
||||
name: "".to_string(),
|
||||
type_: "Sketch".to_string(),
|
||||
|
@ -172,7 +172,9 @@ impl crate::docs::StdLibFn for Min {
|
||||
vec![crate::docs::StdLibFnArg {
|
||||
name: "args".to_string(),
|
||||
type_: "[number]".to_string(),
|
||||
schema: generator.root_schema_for::<Vec<f64>>(),
|
||||
schema: crate::docs::cleanup_number_tuples_root(
|
||||
generator.root_schema_for::<Vec<f64>>(),
|
||||
),
|
||||
required: true,
|
||||
label_required: true,
|
||||
description: String::new().to_string(),
|
||||
@ -184,7 +186,7 @@ impl crate::docs::StdLibFn for Min {
|
||||
let mut settings = schemars::gen::SchemaSettings::openapi3();
|
||||
settings.inline_subschemas = inline_subschemas;
|
||||
let mut generator = schemars::gen::SchemaGenerator::new(settings);
|
||||
let schema = generator.root_schema_for::<f64>();
|
||||
let schema = crate::docs::cleanup_number_tuples_root(generator.root_schema_for::<f64>());
|
||||
Some(crate::docs::StdLibFnArg {
|
||||
name: "".to_string(),
|
||||
type_: "number".to_string(),
|
||||
|
@ -112,7 +112,9 @@ impl crate::docs::StdLibFn for Show {
|
||||
vec![crate::docs::StdLibFnArg {
|
||||
name: "args".to_string(),
|
||||
type_: "number".to_string(),
|
||||
schema: generator.root_schema_for::<Option<f64>>(),
|
||||
schema: crate::docs::cleanup_number_tuples_root(
|
||||
generator.root_schema_for::<Option<f64>>(),
|
||||
),
|
||||
required: false,
|
||||
label_required: true,
|
||||
description: String::new().to_string(),
|
||||
@ -124,7 +126,7 @@ impl crate::docs::StdLibFn for Show {
|
||||
let mut settings = schemars::gen::SchemaSettings::openapi3();
|
||||
settings.inline_subschemas = inline_subschemas;
|
||||
let mut generator = schemars::gen::SchemaGenerator::new(settings);
|
||||
let schema = generator.root_schema_for::<f64>();
|
||||
let schema = crate::docs::cleanup_number_tuples_root(generator.root_schema_for::<f64>());
|
||||
Some(crate::docs::StdLibFnArg {
|
||||
name: "".to_string(),
|
||||
type_: "number".to_string(),
|
||||
|
@ -112,7 +112,9 @@ impl crate::docs::StdLibFn for Import {
|
||||
vec![crate::docs::StdLibFnArg {
|
||||
name: "args".to_string(),
|
||||
type_: "kittycad::types::InputFormat".to_string(),
|
||||
schema: generator.root_schema_for::<Option<kittycad::types::InputFormat>>(),
|
||||
schema: crate::docs::cleanup_number_tuples_root(
|
||||
generator.root_schema_for::<Option<kittycad::types::InputFormat>>(),
|
||||
),
|
||||
required: false,
|
||||
label_required: true,
|
||||
description: String::new().to_string(),
|
||||
@ -124,7 +126,7 @@ impl crate::docs::StdLibFn for Import {
|
||||
let mut settings = schemars::gen::SchemaSettings::openapi3();
|
||||
settings.inline_subschemas = inline_subschemas;
|
||||
let mut generator = schemars::gen::SchemaGenerator::new(settings);
|
||||
let schema = generator.root_schema_for::<f64>();
|
||||
let schema = crate::docs::cleanup_number_tuples_root(generator.root_schema_for::<f64>());
|
||||
Some(crate::docs::StdLibFnArg {
|
||||
name: "".to_string(),
|
||||
type_: "number".to_string(),
|
||||
|