Merge branch 'franknoirot/adhoc/appearance-tweaks-modeling-view' into franknoirot/adhoc/split-sidebar
This commit is contained in:
File diff suppressed because one or more lines are too long
@ -109,3 +109,98 @@ Coordinate systems:
|
||||
- `zoo` (the default), forward: -Y, up: +Z, handedness: right
|
||||
- `opengl`, forward: +Z, up: +Y, handedness: right
|
||||
- `vulkan`, forward: +Z, up: -Y, handedness: left
|
||||
|
||||
### Performance
|
||||
|
||||
Parallelized foreign-file imports now let you overlap file reads, initialization,
|
||||
and rendering. To maximize throughput, you need to understand the three distinct
|
||||
stages—reading, initializing (background render start), and invocation (blocking)
|
||||
—and structure your code to defer blocking operations until the end.
|
||||
|
||||
#### Foreign Import Execution Stages
|
||||
|
||||
1. **Import (Read) Stage**
|
||||
```norun
|
||||
import "tests/inputs/cube.step" as cube
|
||||
```
|
||||
- Reads the file from disk and makes its API available.
|
||||
- **Does _not_** start Engine rendering or block your script.
|
||||
|
||||
2. **Initialization (Background Render) Stage**
|
||||
```norun
|
||||
import "tests/inputs/cube.step" as cube
|
||||
|
||||
myCube = cube // <- This line starts background rendering
|
||||
```
|
||||
- Invoking the imported symbol (assignment or plain call) triggers Engine rendering _in the background_.
|
||||
- This kick‑starts the render pipeline but doesn’t block—you can continue other work while the Engine processes the model.
|
||||
|
||||
3. **Invocation (Blocking) Stage**
|
||||
```norun
|
||||
import "tests/inputs/cube.step" as cube
|
||||
|
||||
myCube = cube
|
||||
|
||||
myCube
|
||||
|> translate(z=10) // <- This line blocks
|
||||
```
|
||||
- Any method call (e.g., `translate`, `scale`, `rotate`) waits for the background render to finish before applying transformations.
|
||||
- This is the only point where your script will block.
|
||||
|
||||
> **Nuance:** Foreign imports differ from pure KCL modules—calling the same import symbol multiple times (e.g., `screw` twice) starts background rendering twice.
|
||||
|
||||
#### Best Practices
|
||||
|
||||
##### 1. Defer Blocking Calls
|
||||
Initialize early but delay all transformations until after your heavy computation:
|
||||
```norun
|
||||
import "tests/inputs/cube.step" as cube // 1) Read
|
||||
|
||||
myCube = cube // 2) Background render starts
|
||||
|
||||
|
||||
// --- perform other operations and calculations or setup here ---
|
||||
|
||||
|
||||
myCube
|
||||
|> translate(z=10) // 3) Blocks only here
|
||||
```
|
||||
|
||||
##### 2. Encapsulate Imports in Modules
|
||||
Keep `main.kcl` free of reads and initialization; wrap them:
|
||||
|
||||
```norun
|
||||
// imports.kcl
|
||||
import "tests/inputs/cube.step" as cube // Read only
|
||||
|
||||
|
||||
export myCube = cube // Kick off rendering
|
||||
```
|
||||
|
||||
```norun
|
||||
// main.kcl
|
||||
import myCube from "imports.kcl" // Import the initialized object
|
||||
|
||||
|
||||
// ... computations ...
|
||||
|
||||
|
||||
myCube
|
||||
|> translate(z=10) // Blocking call at the end
|
||||
```
|
||||
|
||||
##### 3. Avoid Immediate Method Calls
|
||||
|
||||
```norun
|
||||
import "tests/inputs/cube.step" as cube
|
||||
|
||||
cube
|
||||
|> translate(z=10) // Blocks immediately, negating parallelism
|
||||
```
|
||||
|
||||
Both calling methods right on `cube` immediately or leaving an implicit import without assignment introduce blocking.
|
||||
|
||||
#### Future Improvements
|
||||
|
||||
Upcoming releases will auto‑analyze dependencies and only block when truly necessary. Until then, explicit deferral and modular wrapping give you the best performance.
|
||||
|
||||
|
||||
@ -53,7 +53,7 @@ rotate(
|
||||
|
||||
### Returns
|
||||
|
||||
[`SolidOrSketchOrImportedGeometry`](/docs/kcl/types/SolidOrSketchOrImportedGeometry) - Data for a solid or an imported geometry.
|
||||
[`SolidOrSketchOrImportedGeometry`](/docs/kcl/types/SolidOrSketchOrImportedGeometry) - Data for a solid, sketch, or an imported geometry.
|
||||
|
||||
|
||||
### Examples
|
||||
|
||||
@ -37,7 +37,7 @@ scale(
|
||||
|
||||
### Returns
|
||||
|
||||
[`SolidOrSketchOrImportedGeometry`](/docs/kcl/types/SolidOrSketchOrImportedGeometry) - Data for a solid or an imported geometry.
|
||||
[`SolidOrSketchOrImportedGeometry`](/docs/kcl/types/SolidOrSketchOrImportedGeometry) - Data for a solid, sketch, or an imported geometry.
|
||||
|
||||
|
||||
### Examples
|
||||
|
||||
@ -28101,14 +28101,62 @@
|
||||
"args": [
|
||||
{
|
||||
"name": "solids",
|
||||
"type": "[Solid]",
|
||||
"type": "SolidOrImportedGeometry",
|
||||
"schema": {
|
||||
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
||||
"title": "Array_of_Solid",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/Solid"
|
||||
},
|
||||
"title": "SolidOrImportedGeometry",
|
||||
"description": "Data for a solid or an imported geometry.",
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Data for an imported geometry.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"id",
|
||||
"type",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"importedGeometry"
|
||||
]
|
||||
},
|
||||
"id": {
|
||||
"description": "The ID of the imported geometry.",
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
},
|
||||
"value": {
|
||||
"description": "The original file paths.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": [
|
||||
"object",
|
||||
"array"
|
||||
],
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/Solid"
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"solidSet"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"definitions": {
|
||||
"Solid": {
|
||||
"type": "object",
|
||||
@ -34571,14 +34619,62 @@
|
||||
],
|
||||
"returnValue": {
|
||||
"name": "",
|
||||
"type": "[Solid]",
|
||||
"type": "SolidOrImportedGeometry",
|
||||
"schema": {
|
||||
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
||||
"title": "Array_of_Solid",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/Solid"
|
||||
},
|
||||
"title": "SolidOrImportedGeometry",
|
||||
"description": "Data for a solid or an imported geometry.",
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Data for an imported geometry.",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"id",
|
||||
"type",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"importedGeometry"
|
||||
]
|
||||
},
|
||||
"id": {
|
||||
"description": "The ID of the imported geometry.",
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
},
|
||||
"value": {
|
||||
"description": "The original file paths.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": [
|
||||
"object",
|
||||
"array"
|
||||
],
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/Solid"
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"solidSet"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"definitions": {
|
||||
"Solid": {
|
||||
"type": "object",
|
||||
@ -36198,7 +36294,8 @@
|
||||
"// Setting the appearance of a 3D pattern can be done _before_ or _after_ the pattern.\n// This example shows _before_ the pattern.\nexampleSketch = startSketchOn(XZ)\n |> startProfileAt([0, 0], %)\n |> line(end = [0, 2])\n |> line(end = [3, 1])\n |> line(end = [0, -4])\n |> close()\n\nexample = extrude(exampleSketch, length = 1)\n |> appearance(color = '#ff0000', metalness = 90, roughness = 90)\n |> patternLinear3d(axis = [1, 0, 1], instances = 7, distance = 6)",
|
||||
"// Setting the appearance of a 3D pattern can be done _before_ or _after_ the pattern.\n// This example shows _after_ the pattern.\nexampleSketch = startSketchOn(XZ)\n |> startProfileAt([0, 0], %)\n |> line(end = [0, 2])\n |> line(end = [3, 1])\n |> line(end = [0, -4])\n |> close()\n\nexample = extrude(exampleSketch, length = 1)\n |> patternLinear3d(axis = [1, 0, 1], instances = 7, distance = 6)\n |> appearance(color = '#ff0000', metalness = 90, roughness = 90)",
|
||||
"// Color the result of a 2D pattern that was extruded.\nexampleSketch = startSketchOn(XZ)\n |> startProfileAt([.5, 25], %)\n |> line(end = [0, 5])\n |> line(end = [-1, 0])\n |> line(end = [0, -5])\n |> close()\n |> patternCircular2d(\n center = [0, 0],\n instances = 13,\n arcDegrees = 360,\n rotateDuplicates = true,\n )\n\nexample = extrude(exampleSketch, length = 1)\n |> appearance(color = '#ff0000', metalness = 90, roughness = 90)",
|
||||
"// Color the result of a sweep.\n\n// Create a path for the sweep.\nsweepPath = startSketchOn(XZ)\n |> startProfileAt([0.05, 0.05], %)\n |> line(end = [0, 7])\n |> tangentialArc(angle = 90, radius = 5)\n |> line(end = [-3, 0])\n |> tangentialArc(angle = -90, radius = 5)\n |> line(end = [0, 7])\n\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 |> appearance(color = \"#ff0000\", metalness = 50, roughness = 50)"
|
||||
"// Color the result of a sweep.\n\n// Create a path for the sweep.\nsweepPath = startSketchOn(XZ)\n |> startProfileAt([0.05, 0.05], %)\n |> line(end = [0, 7])\n |> tangentialArc(angle = 90, radius = 5)\n |> line(end = [-3, 0])\n |> tangentialArc(angle = -90, radius = 5)\n |> line(end = [0, 7])\n\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 |> appearance(color = \"#ff0000\", metalness = 50, roughness = 50)",
|
||||
"// Change the appearance of an imported model.\n\n\nimport \"tests/inputs/cube.sldprt\" as cube\n\ncube\n// |> appearance(\n// color = \"#ff0000\",\n// metalness = 50,\n// roughness = 50\n// )"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -249578,7 +249675,7 @@
|
||||
"schema": {
|
||||
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
||||
"title": "SolidOrSketchOrImportedGeometry",
|
||||
"description": "Data for a solid or an imported geometry.",
|
||||
"description": "Data for a solid, sketch, or an imported geometry.",
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Data for an imported geometry.",
|
||||
@ -260975,7 +261072,7 @@
|
||||
"schema": {
|
||||
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
||||
"title": "SolidOrSketchOrImportedGeometry",
|
||||
"description": "Data for a solid or an imported geometry.",
|
||||
"description": "Data for a solid, sketch, or an imported geometry.",
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Data for an imported geometry.",
|
||||
@ -262721,7 +262818,7 @@
|
||||
"schema": {
|
||||
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
||||
"title": "SolidOrSketchOrImportedGeometry",
|
||||
"description": "Data for a solid or an imported geometry.",
|
||||
"description": "Data for a solid, sketch, or an imported geometry.",
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Data for an imported geometry.",
|
||||
@ -270879,7 +270976,7 @@
|
||||
"schema": {
|
||||
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
||||
"title": "SolidOrSketchOrImportedGeometry",
|
||||
"description": "Data for a solid or an imported geometry.",
|
||||
"description": "Data for a solid, sketch, or an imported geometry.",
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Data for an imported geometry.",
|
||||
@ -319774,7 +319871,7 @@
|
||||
"schema": {
|
||||
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
||||
"title": "SolidOrSketchOrImportedGeometry",
|
||||
"description": "Data for a solid or an imported geometry.",
|
||||
"description": "Data for a solid, sketch, or an imported geometry.",
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Data for an imported geometry.",
|
||||
@ -327932,7 +328029,7 @@
|
||||
"schema": {
|
||||
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
|
||||
"title": "SolidOrSketchOrImportedGeometry",
|
||||
"description": "Data for a solid or an imported geometry.",
|
||||
"description": "Data for a solid, sketch, or an imported geometry.",
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Data for an imported geometry.",
|
||||
|
||||
@ -33,7 +33,7 @@ translate(
|
||||
|
||||
### Returns
|
||||
|
||||
[`SolidOrSketchOrImportedGeometry`](/docs/kcl/types/SolidOrSketchOrImportedGeometry) - Data for a solid or an imported geometry.
|
||||
[`SolidOrSketchOrImportedGeometry`](/docs/kcl/types/SolidOrSketchOrImportedGeometry) - Data for a solid, sketch, or an imported geometry.
|
||||
|
||||
|
||||
### Examples
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
---
|
||||
title: "SolidOrSketchOrImportedGeometry"
|
||||
excerpt: "Data for a solid or an imported geometry."
|
||||
excerpt: "Data for a solid, sketch, or an imported geometry."
|
||||
layout: manual
|
||||
---
|
||||
|
||||
Data for a solid or an imported geometry.
|
||||
Data for a solid, sketch, or an imported geometry.
|
||||
|
||||
|
||||
|
||||
|
||||
@ -405,10 +405,6 @@ test.describe('Point-and-click assemblies tests', () => {
|
||||
)
|
||||
await scene.settled(cmdBar)
|
||||
|
||||
// TODO: remove this once #5780 is fixed
|
||||
await page.reload()
|
||||
|
||||
await scene.settled(cmdBar)
|
||||
await expect(page.locator('.cm-lint-marker-error')).not.toBeVisible()
|
||||
await toolbar.closePane('code')
|
||||
await scene.expectPixelColor(partColor, partPoint, tolerance)
|
||||
@ -453,10 +449,6 @@ test.describe('Point-and-click assemblies tests', () => {
|
||||
)
|
||||
await scene.settled(cmdBar)
|
||||
|
||||
// TODO: remove this once #5780 is fixed
|
||||
await page.reload()
|
||||
await scene.settled(cmdBar)
|
||||
|
||||
await expect(page.locator('.cm-lint-marker-error')).not.toBeVisible()
|
||||
await toolbar.closePane('code')
|
||||
await scene.expectPixelColor(partColor, partPoint, tolerance)
|
||||
|
||||
@ -3105,23 +3105,25 @@ test.describe('manual edits during sketch mode', () => {
|
||||
await test.step('Edit sketch by dragging handle', async () => {
|
||||
await page.waitForTimeout(500)
|
||||
await expect
|
||||
.poll(async () => {
|
||||
await editor.expectEditor.toContain('length = 156.54, angle = -28')
|
||||
await page.mouse.move(handle1Location.x, handle1Location.y)
|
||||
await page.mouse.down()
|
||||
await page.mouse.move(
|
||||
handle1Location.x + 50,
|
||||
handle1Location.y + 50,
|
||||
{
|
||||
steps: 5,
|
||||
}
|
||||
)
|
||||
await page.mouse.up()
|
||||
await editor.expectEditor.toContain('length = 231.59, angle = -34')
|
||||
return true
|
||||
})
|
||||
.poll(
|
||||
async () => {
|
||||
await editor.expectEditor.toContain('length = 156.54, angle = -28')
|
||||
await page.mouse.move(handle1Location.x, handle1Location.y)
|
||||
await page.mouse.down()
|
||||
await page.mouse.move(
|
||||
handle1Location.x + 50,
|
||||
handle1Location.y + 50,
|
||||
{
|
||||
steps: 5,
|
||||
}
|
||||
)
|
||||
await page.mouse.up()
|
||||
await editor.expectEditor.toContain('length = 231.59, angle = -34')
|
||||
return true
|
||||
},
|
||||
{ timeout: 10_000 }
|
||||
)
|
||||
.toBeTruthy()
|
||||
// await page.waitForTimeout(1000) // Wait for update
|
||||
})
|
||||
|
||||
await test.step('Delete variables and wait for re-execution', async () => {
|
||||
@ -3137,16 +3139,19 @@ test.describe('manual edits during sketch mode', () => {
|
||||
await editor.expectEditor.toContain('length = 231.59, angle = -34')
|
||||
await page.waitForTimeout(500)
|
||||
await expect
|
||||
.poll(async () => {
|
||||
await page.mouse.move(handle2Location.x, handle2Location.y)
|
||||
await page.mouse.down()
|
||||
await page.mouse.move(handle2Location.x, handle2Location.y - 50, {
|
||||
steps: 5,
|
||||
})
|
||||
await page.mouse.up()
|
||||
await editor.expectEditor.toContain('length = 167.36, angle = -14')
|
||||
return true
|
||||
})
|
||||
.poll(
|
||||
async () => {
|
||||
await page.mouse.move(handle2Location.x, handle2Location.y)
|
||||
await page.mouse.down()
|
||||
await page.mouse.move(handle2Location.x, handle2Location.y - 50, {
|
||||
steps: 5,
|
||||
})
|
||||
await page.mouse.up()
|
||||
await editor.expectEditor.toContain('length = 167.36, angle = -14')
|
||||
return true
|
||||
},
|
||||
{ timeout: 10_000 }
|
||||
)
|
||||
.toBeTruthy()
|
||||
})
|
||||
|
||||
@ -3165,17 +3170,20 @@ test.describe('manual edits during sketch mode', () => {
|
||||
await test.step('edit sketch again', async () => {
|
||||
await page.waitForTimeout(500) // Wait for deferred execution
|
||||
await expect
|
||||
.poll(async () => {
|
||||
await editor.expectEditor.toContain('length = 167.36, angle = -14')
|
||||
await page.mouse.move(handle3Location.x, handle3Location.y)
|
||||
await page.mouse.down()
|
||||
await page.mouse.move(handle3Location.x, handle3Location.y + 110, {
|
||||
steps: 5,
|
||||
})
|
||||
await page.mouse.up()
|
||||
await editor.expectEditor.toContain('length = 219.2, angle = -56')
|
||||
return true
|
||||
})
|
||||
.poll(
|
||||
async () => {
|
||||
await editor.expectEditor.toContain('length = 167.36, angle = -14')
|
||||
await page.mouse.move(handle3Location.x, handle3Location.y)
|
||||
await page.mouse.down()
|
||||
await page.mouse.move(handle3Location.x, handle3Location.y + 110, {
|
||||
steps: 5,
|
||||
})
|
||||
await page.mouse.up()
|
||||
await editor.expectEditor.toContain('length = 219.2, angle = -56')
|
||||
return true
|
||||
},
|
||||
{ timeout: 10_000 }
|
||||
)
|
||||
.toBeTruthy()
|
||||
})
|
||||
|
||||
|
||||
@ -44,7 +44,9 @@
|
||||
packages =
|
||||
(with pkgs; [
|
||||
rustToolchain
|
||||
cargo-criterion
|
||||
cargo-nextest
|
||||
cargo-sort
|
||||
just
|
||||
postgresql.lib
|
||||
openssl
|
||||
|
||||
@ -25,10 +25,14 @@ When you submit a PR to add or modify KCL samples, images and STEP files will be
|
||||
---
|
||||
#### [80-20-rail](80-20-rail/main.kcl) ([screenshot](screenshots/80-20-rail.png))
|
||||
[](80-20-rail/main.kcl)
|
||||
#### [axial-fan](axial-fan/main.kcl) ([screenshot](screenshots/axial-fan.png))
|
||||
[](axial-fan/main.kcl)
|
||||
#### [ball-bearing](ball-bearing/main.kcl) ([screenshot](screenshots/ball-bearing.png))
|
||||
[](ball-bearing/main.kcl)
|
||||
#### [bench](bench/main.kcl) ([screenshot](screenshots/bench.png))
|
||||
[](bench/main.kcl)
|
||||
#### [bottle](bottle/main.kcl) ([screenshot](screenshots/bottle.png))
|
||||
[](bottle/main.kcl)
|
||||
#### [bracket](bracket/main.kcl) ([screenshot](screenshots/bracket.png))
|
||||
[](bracket/main.kcl)
|
||||
#### [car-wheel-assembly](car-wheel-assembly/main.kcl) ([screenshot](screenshots/car-wheel-assembly.png))
|
||||
|
||||
153
public/kcl-samples/axial-fan/fan-housing.kcl
Normal file
153
public/kcl-samples/axial-fan/fan-housing.kcl
Normal file
@ -0,0 +1,153 @@
|
||||
// Fan Housing
|
||||
// The plastic housing that contains the fan and the motor
|
||||
|
||||
// Set units
|
||||
@settings(defaultLengthUnit = mm)
|
||||
|
||||
// Import parameters
|
||||
import * from "parameters.kcl"
|
||||
|
||||
// Model the housing which holds the motor, the fan, and the mounting provisions
|
||||
// Bottom mounting face
|
||||
bottomFaceSketch = startSketchOn(XY)
|
||||
|> startProfileAt([-fanSize / 2, -fanSize / 2], %)
|
||||
|> angledLine(angle = 0, length = fanSize, tag = $rectangleSegmentA001)
|
||||
|> angledLine(angle = segAng(rectangleSegmentA001) + 90, length = fanSize, tag = $rectangleSegmentB001)
|
||||
|> angledLine(angle = segAng(rectangleSegmentA001), length = -segLen(rectangleSegmentA001), tag = $rectangleSegmentC001)
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $rectangleSegmentD001)
|
||||
|> close()
|
||||
|> hole(circle(center = [0, 0], radius = 4), %)
|
||||
|> hole(circle(
|
||||
center = [
|
||||
mountingHoleSpacing / 2,
|
||||
mountingHoleSpacing / 2
|
||||
],
|
||||
radius = mountingHoleSize / 2,
|
||||
), %)
|
||||
|> hole(circle(
|
||||
center = [
|
||||
-mountingHoleSpacing / 2,
|
||||
mountingHoleSpacing / 2
|
||||
],
|
||||
radius = mountingHoleSize / 2,
|
||||
), %)
|
||||
|> hole(circle(
|
||||
center = [
|
||||
mountingHoleSpacing / 2,
|
||||
-mountingHoleSpacing / 2
|
||||
],
|
||||
radius = mountingHoleSize / 2,
|
||||
), %)
|
||||
|> hole(circle(
|
||||
center = [
|
||||
-mountingHoleSpacing / 2,
|
||||
-mountingHoleSpacing / 2
|
||||
],
|
||||
radius = mountingHoleSize / 2,
|
||||
), %)
|
||||
|> extrude(length = 4)
|
||||
|
||||
// Add large openings to the bottom face to allow airflow through the fan
|
||||
airflowPattern = startSketchOn(bottomFaceSketch, face = END)
|
||||
|> startProfileAt([fanSize * 7 / 25, -fanSize * 9 / 25], %)
|
||||
|> angledLine(angle = 140, length = fanSize * 12 / 25, tag = $seg01)
|
||||
|> tangentialArc(radius = fanSize * 1 / 50, angle = 90)
|
||||
|> angledLine(angle = -130, length = fanSize * 8 / 25)
|
||||
|> tangentialArc(radius = fanSize * 1 / 50, angle = 90)
|
||||
|> angledLine(angle = segAng(seg01) + 180, length = fanSize * 2 / 25)
|
||||
|> tangentialArc(radius = fanSize * 8 / 25, angle = 40)
|
||||
|> xLine(length = fanSize * 3 / 25)
|
||||
|> tangentialArc(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||
|> close()
|
||||
|> patternCircular2d(
|
||||
instances = 4,
|
||||
center = [0, 0],
|
||||
arcDegrees = 360,
|
||||
rotateDuplicates = true,
|
||||
)
|
||||
|> extrude(length = -4)
|
||||
|
||||
// Create the middle segment of the fan housing body
|
||||
housingMiddleLength = fanSize / 3
|
||||
housingMiddleRadius = fanSize / 3 - 1
|
||||
bodyMiddle = startSketchOn(bottomFaceSketch, face = END)
|
||||
|> startProfileAt([
|
||||
housingMiddleLength / 2,
|
||||
-housingMiddleLength / 2 - housingMiddleRadius
|
||||
], %)
|
||||
|> tangentialArc(radius = housingMiddleRadius, angle = 90)
|
||||
|> yLine(length = housingMiddleLength)
|
||||
|> tangentialArc(radius = housingMiddleRadius, angle = 90)
|
||||
|> xLine(length = -housingMiddleLength)
|
||||
|> tangentialArc(radius = housingMiddleRadius, angle = 90)
|
||||
|> yLine(length = -housingMiddleLength)
|
||||
|> tangentialArc(radius = housingMiddleRadius, angle = 90)
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||
|> extrude(length = fanHeight - 4 - 4)
|
||||
|
||||
// Cut a hole in the body to accommodate the fan
|
||||
bodyFanHole = startSketchOn(bodyMiddle, face = END)
|
||||
|> circle(center = [0, 0], radius = fanSize * 23 / 50)
|
||||
|> extrude(length = -(fanHeight - 4 - 4))
|
||||
|
||||
// Top mounting face. Cut a hole in the face to accommodate the fan
|
||||
topFaceSketch = startSketchOn(bodyMiddle, face = END)
|
||||
topHoles = startProfileAt([-fanSize / 2, -fanSize / 2], topFaceSketch)
|
||||
|> angledLine(angle = 0, length = fanSize, tag = $rectangleSegmentA002)
|
||||
|> angledLine(angle = segAng(rectangleSegmentA002) + 90, length = fanSize, tag = $rectangleSegmentB002)
|
||||
|> angledLine(angle = segAng(rectangleSegmentA002), length = -segLen(rectangleSegmentA002), tag = $rectangleSegmentC002)
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $rectangleSegmentD002)
|
||||
|> close()
|
||||
|> hole(circle(center = [0, 0], radius = fanSize * 23 / 50), %)
|
||||
|> hole(circle(
|
||||
center = [
|
||||
mountingHoleSpacing / 2,
|
||||
mountingHoleSpacing / 2
|
||||
],
|
||||
radius = mountingHoleSize / 2,
|
||||
), %)
|
||||
|> hole(circle(
|
||||
center = [
|
||||
-mountingHoleSpacing / 2,
|
||||
mountingHoleSpacing / 2
|
||||
],
|
||||
radius = mountingHoleSize / 2,
|
||||
), %)
|
||||
|> hole(circle(
|
||||
center = [
|
||||
mountingHoleSpacing / 2,
|
||||
-mountingHoleSpacing / 2
|
||||
],
|
||||
radius = mountingHoleSize / 2,
|
||||
), %)
|
||||
|> hole(circle(
|
||||
center = [
|
||||
-mountingHoleSpacing / 2,
|
||||
-mountingHoleSpacing / 2
|
||||
],
|
||||
radius = mountingHoleSize / 2,
|
||||
), %)
|
||||
|> extrude(length = 4)
|
||||
|
||||
// Create a housing for the electric motor to sit
|
||||
motorHousing = startSketchOn(bottomFaceSketch, face = END)
|
||||
|> circle(center = [0, 0], radius = 11.2)
|
||||
|> extrude(length = 16)
|
||||
|
||||
startSketchOn(motorHousing, face = END)
|
||||
|> circle(center = [0, 0], radius = 10)
|
||||
|> extrude(length = -16)
|
||||
|> appearance(color = "#a55e2c")
|
||||
|> fillet(
|
||||
radius = abs(fanSize - mountingHoleSpacing) / 2,
|
||||
tags = [
|
||||
getNextAdjacentEdge(rectangleSegmentA001),
|
||||
getNextAdjacentEdge(rectangleSegmentB001),
|
||||
getNextAdjacentEdge(rectangleSegmentC001),
|
||||
getNextAdjacentEdge(rectangleSegmentD001),
|
||||
getNextAdjacentEdge(rectangleSegmentA002),
|
||||
getNextAdjacentEdge(rectangleSegmentB002),
|
||||
getNextAdjacentEdge(rectangleSegmentC002),
|
||||
getNextAdjacentEdge(rectangleSegmentD002)
|
||||
],
|
||||
)
|
||||
92
public/kcl-samples/axial-fan/fan.kcl
Normal file
92
public/kcl-samples/axial-fan/fan.kcl
Normal file
@ -0,0 +1,92 @@
|
||||
// Fan
|
||||
// Spinning axial fan that moves airflow
|
||||
|
||||
// Set units
|
||||
@settings(defaultLengthUnit = mm)
|
||||
|
||||
// Import parameters
|
||||
import * from "parameters.kcl"
|
||||
|
||||
// Model the center of the fan
|
||||
fanCenter = startSketchOn(XZ)
|
||||
|> startProfileAt([-0.0001, fanHeight], %)
|
||||
|> xLine(endAbsolute = -15 + 1.5)
|
||||
|> tangentialArc(radius = 1.5, angle = 90)
|
||||
|> yLine(endAbsolute = 4.5)
|
||||
|> xLine(endAbsolute = -13)
|
||||
|> yLine(endAbsolute = profileStartY(%) - 5)
|
||||
|> tangentialArc(radius = 1, angle = -90)
|
||||
|> xLine(endAbsolute = -1)
|
||||
|> yLine(length = 2)
|
||||
|> xLine(length = -0.15)
|
||||
|> line(endAbsolute = [
|
||||
profileStartX(%) - 1,
|
||||
profileStartY(%) - 1.4
|
||||
])
|
||||
|> xLine(endAbsolute = profileStartX(%))
|
||||
|> yLine(endAbsolute = profileStartY(%))
|
||||
|> close()
|
||||
|> revolve(axis = {
|
||||
direction = [0.0, 1.0],
|
||||
origin = [0.0, 0.0]
|
||||
})
|
||||
|> appearance(color = "#f3e2d8")
|
||||
|
||||
// Create a function for a lofted fan blade cross section that rotates about the center hub of the fan
|
||||
fn fanBlade(offsetHeight, startAngle) {
|
||||
fanBlade = startSketchOn(offsetPlane(XY, offset = offsetHeight))
|
||||
|> startProfileAt([
|
||||
15 * cos(toRadians(startAngle)),
|
||||
15 * sin(toRadians(startAngle))
|
||||
], %)
|
||||
|> arc({
|
||||
angleStart = startAngle,
|
||||
angleEnd = startAngle + 14,
|
||||
radius = 15
|
||||
}, %)
|
||||
|> arcTo({
|
||||
end = [
|
||||
fanSize * 22 / 50 * cos(toRadians(startAngle - 20)),
|
||||
fanSize * 22 / 50 * sin(toRadians(startAngle - 20))
|
||||
],
|
||||
interior = [
|
||||
fanSize * 11 / 50 * cos(toRadians(startAngle + 3)),
|
||||
fanSize * 11 / 50 * sin(toRadians(startAngle + 3))
|
||||
]
|
||||
}, %)
|
||||
|> arcTo({
|
||||
end = [
|
||||
fanSize * 22 / 50 * cos(toRadians(startAngle - 24)),
|
||||
fanSize * 22 / 50 * sin(toRadians(startAngle - 24))
|
||||
],
|
||||
interior = [
|
||||
fanSize * 22 / 50 * cos(toRadians(startAngle - 22)),
|
||||
fanSize * 22 / 50 * sin(toRadians(startAngle - 22))
|
||||
]
|
||||
}, %)
|
||||
|> arcTo({
|
||||
end = [profileStartX(%), profileStartY(%)],
|
||||
interior = [
|
||||
fanSize * 11 / 50 * cos(toRadians(startAngle - 5)),
|
||||
fanSize * 11 / 50 * sin(toRadians(startAngle - 5))
|
||||
]
|
||||
}, %)
|
||||
|> close()
|
||||
return fanBlade
|
||||
}
|
||||
|
||||
// Loft the fan blade cross sections into a single blade, then pattern them about the fan center
|
||||
loft([
|
||||
fanBlade(4.5, 50),
|
||||
fanBlade((fanHeight - 2 - 4) / 2, 30),
|
||||
fanBlade(fanHeight - 2, 0)
|
||||
])
|
||||
|> appearance(color = "#f3e2d8")
|
||||
|> patternCircular3d(
|
||||
%,
|
||||
instances = 9,
|
||||
axis = [0, 0, 1],
|
||||
center = [0, 0, 0],
|
||||
arcDegrees = 360,
|
||||
rotateDuplicates = true,
|
||||
)
|
||||
15
public/kcl-samples/axial-fan/main.kcl
Normal file
15
public/kcl-samples/axial-fan/main.kcl
Normal file
@ -0,0 +1,15 @@
|
||||
// PC Fan
|
||||
// A small axial fan, used to push or draw airflow over components to remove excess heat
|
||||
|
||||
// Set units
|
||||
@settings(defaultLengthUnit = mm)
|
||||
|
||||
// Import all parts into assembly file
|
||||
import "fan-housing.kcl" as fanHousing
|
||||
import "motor.kcl" as motor
|
||||
import "fan.kcl" as fan
|
||||
|
||||
// Produce the model for each imported part
|
||||
fanHousing
|
||||
motor
|
||||
fan
|
||||
22
public/kcl-samples/axial-fan/motor.kcl
Normal file
22
public/kcl-samples/axial-fan/motor.kcl
Normal file
@ -0,0 +1,22 @@
|
||||
// Motor
|
||||
// A small electric motor to power the fan
|
||||
|
||||
// Set Units
|
||||
@settings(defaultLengthUnit = mm)
|
||||
|
||||
// Import Parameters
|
||||
import * from "parameters.kcl"
|
||||
|
||||
// Model the motor body and stem
|
||||
|
||||
|
||||
topFacePlane = offsetPlane(XY, offset = 4)
|
||||
motorBody = startSketchOn(topFacePlane)
|
||||
|> circle(center = [0, 0], radius = 10, tag = $seg04)
|
||||
|> extrude(length = 17)
|
||||
|> appearance(color = "#021b55")
|
||||
|> fillet(radius = 2, tags = [getOppositeEdge(seg04), seg04])
|
||||
startSketchOn(offsetPlane(XY, offset = 21))
|
||||
|> circle(center = [0, 0], radius = 1)
|
||||
|> extrude(length = 3.8)
|
||||
|> appearance(color = "#dbc89e")
|
||||
10
public/kcl-samples/axial-fan/parameters.kcl
Normal file
10
public/kcl-samples/axial-fan/parameters.kcl
Normal file
@ -0,0 +1,10 @@
|
||||
// Global parameters for the axial fan
|
||||
|
||||
// Set units
|
||||
@settings(defaultLengthUnit = mm)
|
||||
|
||||
// Define Parameters
|
||||
export fanSize = 120
|
||||
export fanHeight = 25
|
||||
export mountingHoleSpacing = 105
|
||||
export mountingHoleSize = 4.5
|
||||
35
public/kcl-samples/bottle/main.kcl
Normal file
35
public/kcl-samples/bottle/main.kcl
Normal file
@ -0,0 +1,35 @@
|
||||
// Bottle
|
||||
// A simple bottle with a hollow, watertight interior
|
||||
|
||||
// Set Units
|
||||
@settings(defaultLengthUnit = mm)
|
||||
|
||||
// Input dimensions to define the bottle
|
||||
bottleWidth = 80
|
||||
bottleLength = 125
|
||||
bottleHeight = 220
|
||||
neckDepth = 18
|
||||
neckDiameter = 45
|
||||
wallThickness = 4
|
||||
|
||||
// Create a rounded body for the bottle
|
||||
bottleBody = startSketchOn(XY)
|
||||
|> startProfileAt([-bottleLength / 2, 0], %)
|
||||
|> yLine(length = bottleWidth / 3)
|
||||
|> arcTo({
|
||||
end = [bottleLength / 2, bottleWidth / 3],
|
||||
interior = [0, bottleWidth / 2]
|
||||
}, %)
|
||||
|> yLine(endAbsolute = 0)
|
||||
|> mirror2d(axis = X)
|
||||
|> close()
|
||||
|> extrude(length = bottleHeight - neckDepth)
|
||||
|
||||
// Create a neck centered at the top of the bottle
|
||||
bottleNeck = startSketchOn(bottleBody, face = END)
|
||||
|> circle(center = [0, 0], radius = neckDiameter / 2)
|
||||
|> extrude(length = neckDepth)
|
||||
|
||||
// Define a shell operation so that the entire body and neck are hollow, with only the top face opened
|
||||
bottleShell = shell(bottleNeck, faces = [END], thickness = wallThickness)
|
||||
|> appearance(%, color = "#0078c2")
|
||||
@ -6,6 +6,13 @@
|
||||
"title": "80/20 Rail",
|
||||
"description": "An 80/20 extruded aluminum linear rail. T-slot profile adjustable by profile height, rail length, and origin position"
|
||||
},
|
||||
{
|
||||
"file": "main.kcl",
|
||||
"pathFromProjectDirectoryToFirstFile": "axial-fan/main.kcl",
|
||||
"multipleFiles": true,
|
||||
"title": "PC Fan",
|
||||
"description": "A small axial fan, used to push or draw airflow over components to remove excess heat"
|
||||
},
|
||||
{
|
||||
"file": "main.kcl",
|
||||
"pathFromProjectDirectoryToFirstFile": "ball-bearing/main.kcl",
|
||||
@ -20,6 +27,13 @@
|
||||
"title": "Bench",
|
||||
"description": "This is a slight remix of Depep1's original 3D Boaty (https://www.printables.com/model/1141963-3d-boaty). This is a tool used for benchmarking 3D FDM printers for bed adhesion, overhangs, bridging and top surface quality. The name of this file is a bit of misnomer, the shape of the object is a typical park bench."
|
||||
},
|
||||
{
|
||||
"file": "main.kcl",
|
||||
"pathFromProjectDirectoryToFirstFile": "bottle/main.kcl",
|
||||
"multipleFiles": false,
|
||||
"title": "Bottle",
|
||||
"description": "A simple bottle with a hollow, watertight interior"
|
||||
},
|
||||
{
|
||||
"file": "main.kcl",
|
||||
"pathFromProjectDirectoryToFirstFile": "bracket/main.kcl",
|
||||
|
||||
BIN
public/kcl-samples/screenshots/axial-fan.png
Normal file
BIN
public/kcl-samples/screenshots/axial-fan.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 105 KiB |
BIN
public/kcl-samples/screenshots/bottle.png
Normal file
BIN
public/kcl-samples/screenshots/bottle.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 70 KiB |
89
rust/Cargo.lock
generated
89
rust/Cargo.lock
generated
@ -535,7 +535,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -758,7 +758,7 @@ dependencies = [
|
||||
"hashbrown 0.14.5",
|
||||
"lock_api",
|
||||
"once_cell",
|
||||
"parking_lot_core",
|
||||
"parking_lot_core 0.9.10",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -772,7 +772,7 @@ dependencies = [
|
||||
"hashbrown 0.14.5",
|
||||
"lock_api",
|
||||
"once_cell",
|
||||
"parking_lot_core",
|
||||
"parking_lot_core 0.9.10",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -847,7 +847,7 @@ dependencies = [
|
||||
"backtrace",
|
||||
"lazy_static",
|
||||
"mintex",
|
||||
"parking_lot",
|
||||
"parking_lot 0.12.3",
|
||||
"rustc-hash 1.1.0",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@ -954,7 +954,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1697,6 +1697,18 @@ dependencies = [
|
||||
"similar",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "instant"
|
||||
version = "0.1.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ipnet"
|
||||
version = "2.11.0"
|
||||
@ -1711,7 +1723,7 @@ checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1885,6 +1897,7 @@ dependencies = [
|
||||
"image",
|
||||
"indexmap 2.8.0",
|
||||
"insta",
|
||||
"instant",
|
||||
"itertools 0.13.0",
|
||||
"js-sys",
|
||||
"kcl-derive-docs",
|
||||
@ -1921,6 +1934,7 @@ dependencies = [
|
||||
"validator",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"wasm-timer",
|
||||
"web-sys",
|
||||
"web-time",
|
||||
"winnow 0.6.24",
|
||||
@ -2460,6 +2474,17 @@ dependencies = [
|
||||
"unicode-width 0.2.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
|
||||
dependencies = [
|
||||
"instant",
|
||||
"lock_api",
|
||||
"parking_lot_core 0.8.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.12.3"
|
||||
@ -2467,7 +2492,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
|
||||
dependencies = [
|
||||
"lock_api",
|
||||
"parking_lot_core",
|
||||
"parking_lot_core 0.9.10",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot_core"
|
||||
version = "0.8.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"instant",
|
||||
"libc",
|
||||
"redox_syscall 0.2.16",
|
||||
"smallvec",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2478,7 +2517,7 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"redox_syscall 0.5.10",
|
||||
"smallvec",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
@ -2883,7 +2922,7 @@ dependencies = [
|
||||
"once_cell",
|
||||
"socket2",
|
||||
"tracing",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3018,6 +3057,15 @@ dependencies = [
|
||||
"rand_core 0.3.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.5.10"
|
||||
@ -3211,7 +3259,7 @@ dependencies = [
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3809,7 +3857,7 @@ dependencies = [
|
||||
"getrandom 0.3.1",
|
||||
"once_cell",
|
||||
"rustix",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3984,7 +4032,7 @@ dependencies = [
|
||||
"bytes",
|
||||
"libc",
|
||||
"mio",
|
||||
"parking_lot",
|
||||
"parking_lot 0.12.3",
|
||||
"pin-project-lite",
|
||||
"signal-hook-registry",
|
||||
"socket2",
|
||||
@ -4581,6 +4629,21 @@ dependencies = [
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-timer"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "be0ecb0db480561e9a7642b5d3e4187c128914e58aa84330b9493e3eb68c5e7f"
|
||||
dependencies = [
|
||||
"futures",
|
||||
"js-sys",
|
||||
"parking_lot 0.11.2",
|
||||
"pin-utils",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.77"
|
||||
@ -4632,7 +4695,7 @@ version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
|
||||
dependencies = [
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@ -89,14 +89,17 @@ winnow = "=0.6.24"
|
||||
zip = { workspace = true }
|
||||
|
||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||
instant = { version = "0.1.13", features = ["wasm-bindgen", "inaccurate"] }
|
||||
js-sys = { version = "0.3.72" }
|
||||
tokio = { workspace = true, features = ["sync", "time"] }
|
||||
tower-lsp = { workspace = true, features = ["runtime-agnostic"] }
|
||||
wasm-bindgen = "0.2.99"
|
||||
wasm-bindgen-futures = "0.4.49"
|
||||
wasm-timer = "0.2.5"
|
||||
web-sys = { version = "0.3.76", features = ["console"] }
|
||||
|
||||
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||
instant = "0.1.13"
|
||||
tokio = { workspace = true, features = ["full"] }
|
||||
tokio-tungstenite = { version = "0.24.0", features = [
|
||||
"rustls-tls-native-roots",
|
||||
|
||||
@ -2109,7 +2109,7 @@ async fn kcl_test_better_type_names() {
|
||||
},
|
||||
None => todo!(),
|
||||
};
|
||||
assert_eq!(err, "This function expected the input argument to be one or more Solids but it's actually of type Sketch. You can convert a sketch (2D) into a Solid (3D) by calling a function like `extrude` or `revolve`");
|
||||
assert_eq!(err, "This function expected the input argument to be one or more Solids or imported geometry but it's actually of type Sketch. You can convert a sketch (2D) into a Solid (3D) by calling a function like `extrude` or `revolve`");
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
|
||||
@ -133,6 +133,7 @@ impl StdLibFnArg {
|
||||
|| self.type_ == "[Solid]"
|
||||
|| self.type_ == "SketchSurface"
|
||||
|| self.type_ == "SketchOrSurface"
|
||||
|| self.type_ == "SolidOrImportedGeometry"
|
||||
|| self.type_ == "SolidOrSketchOrImportedGeometry")
|
||||
&& (self.required || self.include_in_snippet)
|
||||
{
|
||||
|
||||
@ -45,6 +45,7 @@ pub struct EngineConnection {
|
||||
batch: Arc<RwLock<Vec<(WebSocketRequest, SourceRange)>>>,
|
||||
batch_end: Arc<RwLock<IndexMap<uuid::Uuid, (WebSocketRequest, SourceRange)>>>,
|
||||
artifact_commands: Arc<RwLock<Vec<ArtifactCommand>>>,
|
||||
ids_of_async_commands: Arc<RwLock<IndexMap<Uuid, SourceRange>>>,
|
||||
|
||||
/// The default planes for the scene.
|
||||
default_planes: Arc<RwLock<Option<DefaultPlanes>>>,
|
||||
@ -115,6 +116,17 @@ impl Drop for TcpReadHandle {
|
||||
}
|
||||
}
|
||||
|
||||
struct ResponsesInformation {
|
||||
/// The responses from the engine.
|
||||
responses: Arc<RwLock<IndexMap<uuid::Uuid, WebSocketResponse>>>,
|
||||
}
|
||||
|
||||
impl ResponsesInformation {
|
||||
pub async fn add(&self, id: Uuid, response: WebSocketResponse) {
|
||||
self.responses.write().await.insert(id, response);
|
||||
}
|
||||
}
|
||||
|
||||
/// Requests to send to the engine, and a way to await a response.
|
||||
struct ToEngineReq {
|
||||
/// The request to send
|
||||
@ -227,10 +239,13 @@ impl EngineConnection {
|
||||
let session_data: Arc<RwLock<Option<ModelingSessionData>>> = Arc::new(RwLock::new(None));
|
||||
let session_data2 = session_data.clone();
|
||||
let responses: Arc<RwLock<IndexMap<uuid::Uuid, WebSocketResponse>>> = Arc::new(RwLock::new(IndexMap::new()));
|
||||
let responses_clone = responses.clone();
|
||||
let ids_of_async_commands: Arc<RwLock<IndexMap<Uuid, SourceRange>>> = Arc::new(RwLock::new(IndexMap::new()));
|
||||
let socket_health = Arc::new(RwLock::new(SocketHealth::Active));
|
||||
let pending_errors = Arc::new(RwLock::new(Vec::new()));
|
||||
let pending_errors_clone = pending_errors.clone();
|
||||
let responses_information = ResponsesInformation {
|
||||
responses: responses.clone(),
|
||||
};
|
||||
|
||||
let socket_health_tcp_read = socket_health.clone();
|
||||
let tcp_read_handle = tokio::spawn(async move {
|
||||
@ -244,8 +259,7 @@ impl EngineConnection {
|
||||
WebSocketResponse::Success(SuccessWebSocketResponse {
|
||||
resp: OkWebSocketResponseData::ModelingBatch { responses },
|
||||
..
|
||||
}) =>
|
||||
{
|
||||
}) => {
|
||||
#[expect(
|
||||
clippy::iter_over_hash_type,
|
||||
reason = "modeling command uses a HashMap and keys are random, so we don't really have a choice"
|
||||
@ -254,26 +268,32 @@ impl EngineConnection {
|
||||
let id: uuid::Uuid = (*resp_id).into();
|
||||
match batch_response {
|
||||
BatchResponse::Success { response } => {
|
||||
responses_clone.write().await.insert(
|
||||
id,
|
||||
WebSocketResponse::Success(SuccessWebSocketResponse {
|
||||
success: true,
|
||||
request_id: Some(id),
|
||||
resp: OkWebSocketResponseData::Modeling {
|
||||
modeling_response: response.clone(),
|
||||
},
|
||||
}),
|
||||
);
|
||||
// If the id is in our ids of async commands, remove
|
||||
// it.
|
||||
responses_information
|
||||
.add(
|
||||
id,
|
||||
WebSocketResponse::Success(SuccessWebSocketResponse {
|
||||
success: true,
|
||||
request_id: Some(id),
|
||||
resp: OkWebSocketResponseData::Modeling {
|
||||
modeling_response: response.clone(),
|
||||
},
|
||||
}),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
BatchResponse::Failure { errors } => {
|
||||
responses_clone.write().await.insert(
|
||||
id,
|
||||
WebSocketResponse::Failure(FailureWebSocketResponse {
|
||||
success: false,
|
||||
request_id: Some(id),
|
||||
errors: errors.clone(),
|
||||
}),
|
||||
);
|
||||
responses_information
|
||||
.add(
|
||||
id,
|
||||
WebSocketResponse::Failure(FailureWebSocketResponse {
|
||||
success: false,
|
||||
request_id: Some(id),
|
||||
errors: errors.clone(),
|
||||
}),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -291,14 +311,16 @@ impl EngineConnection {
|
||||
errors,
|
||||
}) => {
|
||||
if let Some(id) = request_id {
|
||||
responses_clone.write().await.insert(
|
||||
*id,
|
||||
WebSocketResponse::Failure(FailureWebSocketResponse {
|
||||
success: false,
|
||||
request_id: *request_id,
|
||||
errors: errors.clone(),
|
||||
}),
|
||||
);
|
||||
responses_information
|
||||
.add(
|
||||
*id,
|
||||
WebSocketResponse::Failure(FailureWebSocketResponse {
|
||||
success: false,
|
||||
request_id: *request_id,
|
||||
errors: errors.clone(),
|
||||
}),
|
||||
)
|
||||
.await;
|
||||
} else {
|
||||
// Add it to our pending errors.
|
||||
let mut pe = pending_errors_clone.write().await;
|
||||
@ -314,7 +336,7 @@ impl EngineConnection {
|
||||
}
|
||||
|
||||
if let Some(id) = id {
|
||||
responses_clone.write().await.insert(id, ws_resp.clone());
|
||||
responses_information.add(id, ws_resp.clone()).await;
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
@ -341,6 +363,7 @@ impl EngineConnection {
|
||||
batch: Arc::new(RwLock::new(Vec::new())),
|
||||
batch_end: Arc::new(RwLock::new(IndexMap::new())),
|
||||
artifact_commands: Arc::new(RwLock::new(Vec::new())),
|
||||
ids_of_async_commands,
|
||||
default_planes: Default::default(),
|
||||
session_data,
|
||||
stats: Default::default(),
|
||||
@ -366,6 +389,10 @@ impl EngineManager for EngineConnection {
|
||||
self.artifact_commands.clone()
|
||||
}
|
||||
|
||||
fn ids_of_async_commands(&self) -> Arc<RwLock<IndexMap<Uuid, SourceRange>>> {
|
||||
self.ids_of_async_commands.clone()
|
||||
}
|
||||
|
||||
fn stats(&self) -> &EngineStats {
|
||||
&self.stats
|
||||
}
|
||||
@ -386,13 +413,13 @@ impl EngineManager for EngineConnection {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn inner_send_modeling_cmd(
|
||||
async fn inner_fire_modeling_cmd(
|
||||
&self,
|
||||
id: uuid::Uuid,
|
||||
_id: uuid::Uuid,
|
||||
source_range: SourceRange,
|
||||
cmd: WebSocketRequest,
|
||||
_id_to_source_range: HashMap<Uuid, SourceRange>,
|
||||
) -> Result<WebSocketResponse, KclError> {
|
||||
) -> Result<(), KclError> {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
|
||||
// Send the request to the engine, via the actor.
|
||||
@ -424,6 +451,19 @@ impl EngineManager for EngineConnection {
|
||||
})
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn inner_send_modeling_cmd(
|
||||
&self,
|
||||
id: uuid::Uuid,
|
||||
source_range: SourceRange,
|
||||
cmd: WebSocketRequest,
|
||||
id_to_source_range: HashMap<Uuid, SourceRange>,
|
||||
) -> Result<WebSocketResponse, KclError> {
|
||||
self.inner_fire_modeling_cmd(id, source_range, cmd, id_to_source_range)
|
||||
.await?;
|
||||
|
||||
// Wait for the response.
|
||||
let current_time = std::time::Instant::now();
|
||||
while current_time.elapsed().as_secs() < 60 {
|
||||
|
||||
@ -12,7 +12,7 @@ use kcmc::{
|
||||
WebSocketResponse,
|
||||
},
|
||||
};
|
||||
use kittycad_modeling_cmds::{self as kcmc};
|
||||
use kittycad_modeling_cmds::{self as kcmc, websocket::ModelingCmdReq, ImportFiles, ModelingCmd};
|
||||
use tokio::sync::RwLock;
|
||||
use uuid::Uuid;
|
||||
|
||||
@ -29,6 +29,8 @@ pub struct EngineConnection {
|
||||
batch: Arc<RwLock<Vec<(WebSocketRequest, SourceRange)>>>,
|
||||
batch_end: Arc<RwLock<IndexMap<uuid::Uuid, (WebSocketRequest, SourceRange)>>>,
|
||||
artifact_commands: Arc<RwLock<Vec<ArtifactCommand>>>,
|
||||
ids_of_async_commands: Arc<RwLock<IndexMap<Uuid, SourceRange>>>,
|
||||
responses: Arc<RwLock<IndexMap<Uuid, WebSocketResponse>>>,
|
||||
/// The default planes for the scene.
|
||||
default_planes: Arc<RwLock<Option<DefaultPlanes>>>,
|
||||
stats: EngineStats,
|
||||
@ -40,6 +42,8 @@ impl EngineConnection {
|
||||
batch: Arc::new(RwLock::new(Vec::new())),
|
||||
batch_end: Arc::new(RwLock::new(IndexMap::new())),
|
||||
artifact_commands: Arc::new(RwLock::new(Vec::new())),
|
||||
ids_of_async_commands: Arc::new(RwLock::new(IndexMap::new())),
|
||||
responses: Arc::new(RwLock::new(IndexMap::new())),
|
||||
default_planes: Default::default(),
|
||||
stats: Default::default(),
|
||||
})
|
||||
@ -57,7 +61,7 @@ impl crate::engine::EngineManager for EngineConnection {
|
||||
}
|
||||
|
||||
fn responses(&self) -> Arc<RwLock<IndexMap<Uuid, WebSocketResponse>>> {
|
||||
Arc::new(RwLock::new(IndexMap::new()))
|
||||
self.responses.clone()
|
||||
}
|
||||
|
||||
fn stats(&self) -> &EngineStats {
|
||||
@ -68,6 +72,10 @@ impl crate::engine::EngineManager for EngineConnection {
|
||||
self.artifact_commands.clone()
|
||||
}
|
||||
|
||||
fn ids_of_async_commands(&self) -> Arc<RwLock<IndexMap<Uuid, SourceRange>>> {
|
||||
self.ids_of_async_commands.clone()
|
||||
}
|
||||
|
||||
fn get_default_planes(&self) -> Arc<RwLock<Option<DefaultPlanes>>> {
|
||||
self.default_planes.clone()
|
||||
}
|
||||
@ -80,6 +88,25 @@ impl crate::engine::EngineManager for EngineConnection {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn inner_fire_modeling_cmd(
|
||||
&self,
|
||||
id: uuid::Uuid,
|
||||
source_range: SourceRange,
|
||||
cmd: WebSocketRequest,
|
||||
id_to_source_range: HashMap<Uuid, SourceRange>,
|
||||
) -> Result<(), KclError> {
|
||||
// Pop off the id we care about.
|
||||
self.ids_of_async_commands.write().await.swap_remove(&id);
|
||||
|
||||
// Add the response to our responses.
|
||||
let response = self
|
||||
.inner_send_modeling_cmd(id, source_range, cmd, id_to_source_range)
|
||||
.await?;
|
||||
self.responses().write().await.insert(id, response);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn inner_send_modeling_cmd(
|
||||
&self,
|
||||
id: uuid::Uuid,
|
||||
@ -109,6 +136,20 @@ impl crate::engine::EngineManager for EngineConnection {
|
||||
success: true,
|
||||
}))
|
||||
}
|
||||
WebSocketRequest::ModelingCmdReq(ModelingCmdReq {
|
||||
cmd: ModelingCmd::ImportFiles(ImportFiles { .. }),
|
||||
cmd_id,
|
||||
}) => Ok(WebSocketResponse::Success(SuccessWebSocketResponse {
|
||||
request_id: Some(id),
|
||||
resp: OkWebSocketResponseData::Modeling {
|
||||
modeling_response: OkModelingCmdResponse::ImportFiles(
|
||||
kittycad_modeling_cmds::output::ImportFiles {
|
||||
object_id: cmd_id.into(),
|
||||
},
|
||||
),
|
||||
},
|
||||
success: true,
|
||||
})),
|
||||
WebSocketRequest::ModelingCmdReq(_) => Ok(WebSocketResponse::Success(SuccessWebSocketResponse {
|
||||
request_id: Some(id),
|
||||
resp: OkWebSocketResponseData::Modeling {
|
||||
|
||||
@ -22,6 +22,15 @@ extern "C" {
|
||||
#[derive(Debug, Clone)]
|
||||
pub type EngineCommandManager;
|
||||
|
||||
#[wasm_bindgen(method, js_name = fireModelingCommandFromWasm, catch)]
|
||||
fn fire_modeling_cmd_from_wasm(
|
||||
this: &EngineCommandManager,
|
||||
id: String,
|
||||
rangeStr: String,
|
||||
cmdStr: String,
|
||||
idToRangeStr: String,
|
||||
) -> Result<(), js_sys::Error>;
|
||||
|
||||
#[wasm_bindgen(method, js_name = sendModelingCommandFromWasm, catch)]
|
||||
fn send_modeling_cmd_from_wasm(
|
||||
this: &EngineCommandManager,
|
||||
@ -38,33 +47,128 @@ extern "C" {
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct EngineConnection {
|
||||
manager: Arc<EngineCommandManager>,
|
||||
response_context: Arc<ResponseContext>,
|
||||
batch: Arc<RwLock<Vec<(WebSocketRequest, SourceRange)>>>,
|
||||
batch_end: Arc<RwLock<IndexMap<uuid::Uuid, (WebSocketRequest, SourceRange)>>>,
|
||||
responses: Arc<RwLock<IndexMap<Uuid, WebSocketResponse>>>,
|
||||
artifact_commands: Arc<RwLock<Vec<ArtifactCommand>>>,
|
||||
ids_of_async_commands: Arc<RwLock<IndexMap<Uuid, SourceRange>>>,
|
||||
/// The default planes for the scene.
|
||||
default_planes: Arc<RwLock<Option<DefaultPlanes>>>,
|
||||
stats: EngineStats,
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ResponseContext {
|
||||
responses: Arc<RwLock<IndexMap<Uuid, WebSocketResponse>>>,
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
impl ResponseContext {
|
||||
#[wasm_bindgen(constructor)]
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
responses: Arc::new(RwLock::new(IndexMap::new())),
|
||||
}
|
||||
}
|
||||
|
||||
// Add a response to the context.
|
||||
pub async fn send_response(&self, data: js_sys::Uint8Array) -> Result<(), JsValue> {
|
||||
let ws_result: WebSocketResponse = match bson::from_slice(&data.to_vec()) {
|
||||
Ok(res) => res,
|
||||
Err(_) => {
|
||||
// We don't care about the error if we can't parse it.
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
|
||||
let id = match &ws_result {
|
||||
WebSocketResponse::Success(res) => res.request_id,
|
||||
WebSocketResponse::Failure(res) => res.request_id,
|
||||
};
|
||||
|
||||
let Some(id) = id else {
|
||||
// We only care if we have an id.
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
// Add this response to our responses.
|
||||
self.add(id, ws_result.clone()).await;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl ResponseContext {
|
||||
pub async fn add(&self, id: Uuid, response: WebSocketResponse) {
|
||||
self.responses.write().await.insert(id, response);
|
||||
}
|
||||
|
||||
pub fn responses(&self) -> Arc<RwLock<IndexMap<Uuid, WebSocketResponse>>> {
|
||||
self.responses.clone()
|
||||
}
|
||||
}
|
||||
|
||||
// Safety: WebAssembly will only ever run in a single-threaded context.
|
||||
unsafe impl Send for EngineConnection {}
|
||||
unsafe impl Sync for EngineConnection {}
|
||||
|
||||
impl EngineConnection {
|
||||
pub async fn new(manager: EngineCommandManager) -> Result<EngineConnection, JsValue> {
|
||||
pub async fn new(
|
||||
manager: EngineCommandManager,
|
||||
response_context: Arc<ResponseContext>,
|
||||
) -> Result<EngineConnection, JsValue> {
|
||||
#[allow(clippy::arc_with_non_send_sync)]
|
||||
Ok(EngineConnection {
|
||||
manager: Arc::new(manager),
|
||||
batch: Arc::new(RwLock::new(Vec::new())),
|
||||
batch_end: Arc::new(RwLock::new(IndexMap::new())),
|
||||
responses: Arc::new(RwLock::new(IndexMap::new())),
|
||||
response_context,
|
||||
artifact_commands: Arc::new(RwLock::new(Vec::new())),
|
||||
ids_of_async_commands: Arc::new(RwLock::new(IndexMap::new())),
|
||||
default_planes: Default::default(),
|
||||
stats: Default::default(),
|
||||
})
|
||||
}
|
||||
|
||||
async fn do_fire_modeling_cmd(
|
||||
&self,
|
||||
id: uuid::Uuid,
|
||||
source_range: SourceRange,
|
||||
cmd: WebSocketRequest,
|
||||
id_to_source_range: HashMap<uuid::Uuid, SourceRange>,
|
||||
) -> Result<(), KclError> {
|
||||
let source_range_str = serde_json::to_string(&source_range).map_err(|e| {
|
||||
KclError::Engine(KclErrorDetails {
|
||||
message: format!("Failed to serialize source range: {:?}", e),
|
||||
source_ranges: vec![source_range],
|
||||
})
|
||||
})?;
|
||||
let cmd_str = serde_json::to_string(&cmd).map_err(|e| {
|
||||
KclError::Engine(KclErrorDetails {
|
||||
message: format!("Failed to serialize modeling command: {:?}", e),
|
||||
source_ranges: vec![source_range],
|
||||
})
|
||||
})?;
|
||||
let id_to_source_range_str = serde_json::to_string(&id_to_source_range).map_err(|e| {
|
||||
KclError::Engine(KclErrorDetails {
|
||||
message: format!("Failed to serialize id to source range: {:?}", e),
|
||||
source_ranges: vec![source_range],
|
||||
})
|
||||
})?;
|
||||
|
||||
self.manager
|
||||
.fire_modeling_cmd_from_wasm(id.to_string(), source_range_str, cmd_str, id_to_source_range_str)
|
||||
.map_err(|e| {
|
||||
KclError::Engine(KclErrorDetails {
|
||||
message: e.to_string().into(),
|
||||
source_ranges: vec![source_range],
|
||||
})
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn do_send_modeling_cmd(
|
||||
&self,
|
||||
id: uuid::Uuid,
|
||||
@ -151,7 +255,7 @@ impl crate::engine::EngineManager for EngineConnection {
|
||||
}
|
||||
|
||||
fn responses(&self) -> Arc<RwLock<IndexMap<Uuid, WebSocketResponse>>> {
|
||||
self.responses.clone()
|
||||
self.response_context.responses.clone()
|
||||
}
|
||||
|
||||
fn stats(&self) -> &EngineStats {
|
||||
@ -162,6 +266,10 @@ impl crate::engine::EngineManager for EngineConnection {
|
||||
self.artifact_commands.clone()
|
||||
}
|
||||
|
||||
fn ids_of_async_commands(&self) -> Arc<RwLock<IndexMap<Uuid, SourceRange>>> {
|
||||
self.ids_of_async_commands.clone()
|
||||
}
|
||||
|
||||
fn get_default_planes(&self) -> Arc<RwLock<Option<DefaultPlanes>>> {
|
||||
self.default_planes.clone()
|
||||
}
|
||||
@ -193,6 +301,19 @@ impl crate::engine::EngineManager for EngineConnection {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn inner_fire_modeling_cmd(
|
||||
&self,
|
||||
id: uuid::Uuid,
|
||||
source_range: SourceRange,
|
||||
cmd: WebSocketRequest,
|
||||
id_to_source_range: HashMap<Uuid, SourceRange>,
|
||||
) -> Result<(), KclError> {
|
||||
self.do_fire_modeling_cmd(id, source_range, cmd, id_to_source_range)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn inner_send_modeling_cmd(
|
||||
&self,
|
||||
id: uuid::Uuid,
|
||||
@ -204,9 +325,7 @@ impl crate::engine::EngineManager for EngineConnection {
|
||||
.do_send_modeling_cmd(id, source_range, cmd, id_to_source_range)
|
||||
.await?;
|
||||
|
||||
let mut responses = self.responses.write().await;
|
||||
responses.insert(id, ws_result.clone());
|
||||
drop(responses);
|
||||
self.response_context.add(id, ws_result.clone()).await;
|
||||
|
||||
Ok(ws_result)
|
||||
}
|
||||
|
||||
@ -76,6 +76,9 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
||||
/// Get the artifact commands that have accumulated so far.
|
||||
fn artifact_commands(&self) -> Arc<RwLock<Vec<ArtifactCommand>>>;
|
||||
|
||||
/// Get the ids of the async commands we are waiting for.
|
||||
fn ids_of_async_commands(&self) -> Arc<RwLock<IndexMap<Uuid, SourceRange>>>;
|
||||
|
||||
/// Take the batch of commands that have accumulated so far and clear them.
|
||||
async fn take_batch(&self) -> Vec<(WebSocketRequest, SourceRange)> {
|
||||
std::mem::take(&mut *self.batch().write().await)
|
||||
@ -96,6 +99,11 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
||||
std::mem::take(&mut *self.artifact_commands().write().await)
|
||||
}
|
||||
|
||||
/// Take the ids of async commands that have accumulated so far and clear them.
|
||||
async fn take_ids_of_async_commands(&self) -> IndexMap<Uuid, SourceRange> {
|
||||
std::mem::take(&mut *self.ids_of_async_commands().write().await)
|
||||
}
|
||||
|
||||
/// Take the responses that have accumulated so far and clear them.
|
||||
async fn take_responses(&self) -> IndexMap<Uuid, WebSocketResponse> {
|
||||
std::mem::take(&mut *self.responses().write().await)
|
||||
@ -136,8 +144,18 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
||||
async fn clear_queues(&self) {
|
||||
self.batch().write().await.clear();
|
||||
self.batch_end().write().await.clear();
|
||||
self.ids_of_async_commands().write().await.clear();
|
||||
}
|
||||
|
||||
/// Send a modeling command and do not wait for the response message.
|
||||
async fn inner_fire_modeling_cmd(
|
||||
&self,
|
||||
id: uuid::Uuid,
|
||||
source_range: SourceRange,
|
||||
cmd: WebSocketRequest,
|
||||
id_to_source_range: HashMap<Uuid, SourceRange>,
|
||||
) -> Result<(), crate::errors::KclError>;
|
||||
|
||||
/// Send a modeling command and wait for the response message.
|
||||
async fn inner_send_modeling_cmd(
|
||||
&self,
|
||||
@ -180,6 +198,68 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Ensure a specific async command has been completed.
|
||||
async fn ensure_async_command_completed(
|
||||
&self,
|
||||
id: uuid::Uuid,
|
||||
source_range: Option<SourceRange>,
|
||||
) -> Result<OkWebSocketResponseData, KclError> {
|
||||
let source_range = if let Some(source_range) = source_range {
|
||||
source_range
|
||||
} else {
|
||||
// Look it up if we don't have it.
|
||||
self.ids_of_async_commands()
|
||||
.read()
|
||||
.await
|
||||
.get(&id)
|
||||
.cloned()
|
||||
.unwrap_or_default()
|
||||
};
|
||||
|
||||
let current_time = instant::Instant::now();
|
||||
while current_time.elapsed().as_secs() < 60 {
|
||||
let responses = self.responses().read().await.clone();
|
||||
let Some(resp) = responses.get(&id) else {
|
||||
// Sleep for a little so we don't hog the CPU.
|
||||
// No seriously WE DO NOT WANT TO PAUSE THE WHOLE APP ON THE JS SIDE.
|
||||
let duration = instant::Duration::from_millis(100);
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
wasm_timer::Delay::new(duration).await.map_err(|err| {
|
||||
KclError::Internal(KclErrorDetails {
|
||||
message: format!("Failed to sleep: {:?}", err),
|
||||
source_ranges: vec![source_range],
|
||||
})
|
||||
})?;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
tokio::time::sleep(duration).await;
|
||||
continue;
|
||||
};
|
||||
|
||||
// If the response is an error, return it.
|
||||
// Parsing will do that and we can ignore the result, we don't care.
|
||||
let response = self.parse_websocket_response(resp.clone(), source_range)?;
|
||||
return Ok(response);
|
||||
}
|
||||
|
||||
Err(KclError::Engine(KclErrorDetails {
|
||||
message: "async command timed out".to_string(),
|
||||
source_ranges: vec![source_range],
|
||||
}))
|
||||
}
|
||||
|
||||
/// Ensure ALL async commands have been completed.
|
||||
async fn ensure_async_commands_completed(&self) -> Result<(), KclError> {
|
||||
// Check if all async commands have been completed.
|
||||
let ids = self.take_ids_of_async_commands().await;
|
||||
|
||||
// Try to get them from the responses.
|
||||
for (id, source_range) in ids {
|
||||
self.ensure_async_command_completed(id, Some(source_range)).await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Set the visibility of edges.
|
||||
async fn set_edge_visibility(
|
||||
&self,
|
||||
@ -342,6 +422,36 @@ pub trait EngineManager: std::fmt::Debug + Send + Sync + 'static {
|
||||
self.run_batch(requests, source_range).await
|
||||
}
|
||||
|
||||
/// Send the modeling cmd async and don't wait for the response.
|
||||
/// Add it to our list of async commands.
|
||||
async fn async_modeling_cmd(
|
||||
&self,
|
||||
id: uuid::Uuid,
|
||||
source_range: SourceRange,
|
||||
cmd: &ModelingCmd,
|
||||
) -> Result<(), crate::errors::KclError> {
|
||||
// Add the command ID to the list of async commands.
|
||||
self.ids_of_async_commands().write().await.insert(id, source_range);
|
||||
|
||||
// Add to artifact commands.
|
||||
self.handle_artifact_command(cmd, id.into(), &HashMap::from([(id, source_range)]))
|
||||
.await?;
|
||||
|
||||
// Fire off the command now, but don't wait for the response, we don't care about it.
|
||||
self.inner_fire_modeling_cmd(
|
||||
id,
|
||||
source_range,
|
||||
WebSocketRequest::ModelingCmdReq(ModelingCmdReq {
|
||||
cmd: cmd.clone(),
|
||||
cmd_id: id.into(),
|
||||
}),
|
||||
HashMap::from([(id, source_range)]),
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Run the batch for the specific commands.
|
||||
async fn run_batch(
|
||||
&self,
|
||||
|
||||
@ -15,6 +15,8 @@ use crate::{
|
||||
std::{args::TyF64, sketch::PlaneData},
|
||||
};
|
||||
|
||||
use super::ExecutorContext;
|
||||
|
||||
type Point2D = kcmc::shared::Point2d<f64>;
|
||||
type Point3D = kcmc::shared::Point3d<f64>;
|
||||
|
||||
@ -76,9 +78,45 @@ pub struct ImportedGeometry {
|
||||
pub value: Vec<String>,
|
||||
#[serde(skip)]
|
||||
pub meta: Vec<Metadata>,
|
||||
/// If the imported geometry has completed.
|
||||
#[serde(skip)]
|
||||
completed: bool,
|
||||
}
|
||||
|
||||
/// Data for a solid or an imported geometry.
|
||||
impl ImportedGeometry {
|
||||
pub fn new(id: uuid::Uuid, value: Vec<String>, meta: Vec<Metadata>) -> Self {
|
||||
Self {
|
||||
id,
|
||||
value,
|
||||
meta,
|
||||
completed: false,
|
||||
}
|
||||
}
|
||||
|
||||
async fn wait_for_finish(&mut self, ctx: &ExecutorContext) -> Result<(), KclError> {
|
||||
if self.completed {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
ctx.engine
|
||||
.ensure_async_command_completed(self.id, self.meta.first().map(|m| m.source_range))
|
||||
.await?;
|
||||
|
||||
self.completed = true;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn id(&mut self, ctx: &ExecutorContext) -> Result<uuid::Uuid, KclError> {
|
||||
if !self.completed {
|
||||
self.wait_for_finish(ctx).await?;
|
||||
}
|
||||
|
||||
Ok(self.id)
|
||||
}
|
||||
}
|
||||
|
||||
/// Data for a solid, sketch, or an imported geometry.
|
||||
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||
#[ts(export)]
|
||||
#[serde(tag = "type", rename_all = "camelCase")]
|
||||
@ -128,11 +166,61 @@ impl From<SolidOrSketchOrImportedGeometry> for crate::execution::KclValue {
|
||||
}
|
||||
|
||||
impl SolidOrSketchOrImportedGeometry {
|
||||
pub(crate) fn ids(&self) -> Vec<uuid::Uuid> {
|
||||
pub(crate) async fn ids(&mut self, ctx: &ExecutorContext) -> Result<Vec<uuid::Uuid>, KclError> {
|
||||
match self {
|
||||
SolidOrSketchOrImportedGeometry::ImportedGeometry(s) => vec![s.id],
|
||||
SolidOrSketchOrImportedGeometry::SolidSet(s) => s.iter().map(|s| s.id).collect(),
|
||||
SolidOrSketchOrImportedGeometry::SketchSet(s) => s.iter().map(|s| s.id).collect(),
|
||||
SolidOrSketchOrImportedGeometry::ImportedGeometry(s) => {
|
||||
let id = s.id(ctx).await?;
|
||||
|
||||
Ok(vec![id])
|
||||
}
|
||||
SolidOrSketchOrImportedGeometry::SolidSet(s) => Ok(s.iter().map(|s| s.id).collect()),
|
||||
SolidOrSketchOrImportedGeometry::SketchSet(s) => Ok(s.iter().map(|s| s.id).collect()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Data for a solid or an imported geometry.
|
||||
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||
#[ts(export)]
|
||||
#[serde(tag = "type", rename_all = "camelCase")]
|
||||
#[allow(clippy::vec_box)]
|
||||
pub enum SolidOrImportedGeometry {
|
||||
ImportedGeometry(Box<ImportedGeometry>),
|
||||
SolidSet(Vec<Solid>),
|
||||
}
|
||||
|
||||
impl From<SolidOrImportedGeometry> for crate::execution::KclValue {
|
||||
fn from(value: SolidOrImportedGeometry) -> Self {
|
||||
match value {
|
||||
SolidOrImportedGeometry::ImportedGeometry(s) => crate::execution::KclValue::ImportedGeometry(*s),
|
||||
SolidOrImportedGeometry::SolidSet(mut s) => {
|
||||
if s.len() == 1 {
|
||||
crate::execution::KclValue::Solid {
|
||||
value: Box::new(s.pop().unwrap()),
|
||||
}
|
||||
} else {
|
||||
crate::execution::KclValue::HomArray {
|
||||
value: s
|
||||
.into_iter()
|
||||
.map(|s| crate::execution::KclValue::Solid { value: Box::new(s) })
|
||||
.collect(),
|
||||
ty: crate::execution::types::RuntimeType::solid(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SolidOrImportedGeometry {
|
||||
pub(crate) async fn ids(&mut self, ctx: &ExecutorContext) -> Result<Vec<uuid::Uuid>, KclError> {
|
||||
match self {
|
||||
SolidOrImportedGeometry::ImportedGeometry(s) => {
|
||||
let id = s.id(ctx).await?;
|
||||
|
||||
Ok(vec![id])
|
||||
}
|
||||
SolidOrImportedGeometry::SolidSet(s) => Ok(s.iter().map(|s| s.id).collect()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,10 +5,8 @@ use kcmc::{
|
||||
coord::{System, KITTYCAD},
|
||||
each_cmd as mcmd,
|
||||
format::InputFormat3d,
|
||||
ok_response::OkModelingCmdResponse,
|
||||
shared::FileImportFormat,
|
||||
units::UnitLength,
|
||||
websocket::OkWebSocketResponseData,
|
||||
ImportFile, ModelingCmd,
|
||||
};
|
||||
use kittycad_modeling_cmds as kcmc;
|
||||
@ -289,34 +287,17 @@ pub struct PreImportedGeometry {
|
||||
}
|
||||
|
||||
pub async fn send_to_engine(pre: PreImportedGeometry, ctxt: &ExecutorContext) -> Result<ImportedGeometry, KclError> {
|
||||
if ctxt.no_engine_commands().await {
|
||||
return Ok(ImportedGeometry {
|
||||
id: pre.id,
|
||||
value: pre.command.files.iter().map(|f| f.path.to_string()).collect(),
|
||||
meta: vec![pre.source_range.into()],
|
||||
});
|
||||
}
|
||||
let imported_geometry = ImportedGeometry::new(
|
||||
pre.id,
|
||||
pre.command.files.iter().map(|f| f.path.to_string()).collect(),
|
||||
vec![pre.source_range.into()],
|
||||
);
|
||||
|
||||
let resp = ctxt
|
||||
.engine
|
||||
.send_modeling_cmd(pre.id, pre.source_range, &ModelingCmd::from(pre.command.clone()))
|
||||
ctxt.engine
|
||||
.async_modeling_cmd(pre.id, pre.source_range, &ModelingCmd::from(pre.command.clone()))
|
||||
.await?;
|
||||
|
||||
let OkWebSocketResponseData::Modeling {
|
||||
modeling_response: OkModelingCmdResponse::ImportFiles(imported_files),
|
||||
} = &resp
|
||||
else {
|
||||
return Err(KclError::Engine(KclErrorDetails {
|
||||
message: format!("ImportFiles response was not as expected: {:?}", resp),
|
||||
source_ranges: vec![pre.source_range],
|
||||
}));
|
||||
};
|
||||
|
||||
Ok(ImportedGeometry {
|
||||
id: imported_files.object_id,
|
||||
value: pre.command.files.iter().map(|f| f.path.to_string()).collect(),
|
||||
meta: vec![pre.source_range.into()],
|
||||
})
|
||||
Ok(imported_geometry)
|
||||
}
|
||||
|
||||
/// Get the source format from the extension.
|
||||
|
||||
@ -947,7 +947,7 @@ impl ExecutorContext {
|
||||
exec_state.global.artifact_graph.clone(),
|
||||
module_id_to_module_path,
|
||||
exec_state.global.id_to_source.clone(),
|
||||
default_planes,
|
||||
default_planes.clone(),
|
||||
)
|
||||
})?;
|
||||
|
||||
@ -957,6 +957,7 @@ impl ExecutorContext {
|
||||
cache::write_old_memory((mem, exec_state.global.module_infos.clone())).await;
|
||||
}
|
||||
let session_data = self.engine.get_session_data().await;
|
||||
|
||||
Ok((env_ref, session_data))
|
||||
}
|
||||
|
||||
@ -984,6 +985,9 @@ impl ExecutorContext {
|
||||
)
|
||||
.await;
|
||||
|
||||
// Ensure all the async commands completed.
|
||||
self.engine.ensure_async_commands_completed().await?;
|
||||
|
||||
// If we errored out and early-returned, there might be commands which haven't been executed
|
||||
// and should be dropped.
|
||||
self.engine.clear_queues().await;
|
||||
|
||||
@ -1338,11 +1338,11 @@ mod test {
|
||||
value: Box::new(Plane::from_plane_data(crate::std::sketch::PlaneData::XY, exec_state)),
|
||||
},
|
||||
// No easy way to make a Face, Sketch, Solid, or Helix
|
||||
KclValue::ImportedGeometry(crate::execution::ImportedGeometry {
|
||||
id: uuid::Uuid::nil(),
|
||||
value: Vec::new(),
|
||||
meta: Vec::new(),
|
||||
}),
|
||||
KclValue::ImportedGeometry(crate::execution::ImportedGeometry::new(
|
||||
uuid::Uuid::nil(),
|
||||
Vec::new(),
|
||||
Vec::new(),
|
||||
)),
|
||||
// Other values don't have types
|
||||
]
|
||||
}
|
||||
|
||||
@ -109,7 +109,7 @@ pub mod exec {
|
||||
pub mod wasm_engine {
|
||||
pub use crate::{
|
||||
coredump::wasm::{CoreDumpManager, CoreDumper},
|
||||
engine::conn_wasm::{EngineCommandManager, EngineConnection},
|
||||
engine::conn_wasm::{EngineCommandManager, EngineConnection, ResponseContext},
|
||||
fs::wasm::{FileManager, FileSystemManager},
|
||||
};
|
||||
}
|
||||
|
||||
@ -2579,3 +2579,24 @@ mod tangent_to_3_point_arc {
|
||||
super::execute(TEST_NAME, true).await
|
||||
}
|
||||
}
|
||||
mod import_async {
|
||||
const TEST_NAME: &str = "import_async";
|
||||
|
||||
/// Test parsing KCL.
|
||||
#[test]
|
||||
fn parse() {
|
||||
super::parse(TEST_NAME)
|
||||
}
|
||||
|
||||
/// Test that parsing and unparsing KCL produces the original KCL input.
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn unparse() {
|
||||
super::unparse(TEST_NAME).await
|
||||
}
|
||||
|
||||
/// Test that KCL is executed correctly.
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn kcl_test_execute() {
|
||||
super::execute(TEST_NAME, true).await
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,7 +13,7 @@ use crate::{
|
||||
errors::{KclError, KclErrorDetails},
|
||||
execution::{
|
||||
types::{NumericType, PrimitiveType, RuntimeType},
|
||||
ExecState, KclValue, Solid,
|
||||
ExecState, KclValue, SolidOrImportedGeometry,
|
||||
},
|
||||
std::Args,
|
||||
};
|
||||
@ -43,7 +43,11 @@ struct AppearanceData {
|
||||
|
||||
/// Set the appearance of a solid. This only works on solids, not sketches or individual paths.
|
||||
pub async fn appearance(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||
let solids = args.get_unlabeled_kw_arg_typed("solids", &RuntimeType::solids(), exec_state)?;
|
||||
let solids = args.get_unlabeled_kw_arg_typed(
|
||||
"solids",
|
||||
&RuntimeType::Union(vec![RuntimeType::solids(), RuntimeType::imported()]),
|
||||
exec_state,
|
||||
)?;
|
||||
|
||||
let color: String = args.get_kw_arg("color")?;
|
||||
let count_ty = RuntimeType::Primitive(PrimitiveType::Number(NumericType::count()));
|
||||
@ -270,6 +274,19 @@ pub async fn appearance(exec_state: &mut ExecState, args: Args) -> Result<KclVal
|
||||
/// roughness = 50
|
||||
/// )
|
||||
/// ```
|
||||
///
|
||||
/// ```no_run
|
||||
/// // Change the appearance of an imported model.
|
||||
///
|
||||
/// import "tests/inputs/cube.sldprt" as cube
|
||||
///
|
||||
/// cube
|
||||
/// // |> appearance(
|
||||
/// // color = "#ff0000",
|
||||
/// // metalness = 50,
|
||||
/// // roughness = 50
|
||||
/// // )
|
||||
/// ```
|
||||
#[stdlib {
|
||||
name = "appearance",
|
||||
keywords = true,
|
||||
@ -282,14 +299,16 @@ pub async fn appearance(exec_state: &mut ExecState, args: Args) -> Result<KclVal
|
||||
}
|
||||
}]
|
||||
async fn inner_appearance(
|
||||
solids: Vec<Solid>,
|
||||
solids: SolidOrImportedGeometry,
|
||||
color: String,
|
||||
metalness: Option<f64>,
|
||||
roughness: Option<f64>,
|
||||
exec_state: &mut ExecState,
|
||||
args: Args,
|
||||
) -> Result<Vec<Solid>, KclError> {
|
||||
for solid in &solids {
|
||||
) -> Result<SolidOrImportedGeometry, KclError> {
|
||||
let mut solids = solids.clone();
|
||||
|
||||
for solid_id in solids.ids(&args.ctx).await? {
|
||||
// Set the material properties.
|
||||
let rgb = rgba_simple::RGB::<f32>::from_hex(&color).map_err(|err| {
|
||||
KclError::Semantic(KclErrorDetails {
|
||||
@ -308,7 +327,7 @@ async fn inner_appearance(
|
||||
args.batch_modeling_cmd(
|
||||
exec_state.next_uuid(),
|
||||
ModelingCmd::from(mcmd::ObjectSetMaterialParamsPbr {
|
||||
object_id: solid.id,
|
||||
object_id: solid_id,
|
||||
color,
|
||||
metalness: metalness.unwrap_or_default() as f32 / 100.0,
|
||||
roughness: roughness.unwrap_or_default() as f32 / 100.0,
|
||||
|
||||
@ -28,6 +28,9 @@ use crate::{
|
||||
ModuleId,
|
||||
};
|
||||
|
||||
const ERROR_STRING_SKETCH_TO_SOLID_HELPER: &str =
|
||||
"You can convert a sketch (2D) into a Solid (3D) by calling a function like `extrude` or `revolve`";
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Arg {
|
||||
/// The evaluated argument.
|
||||
@ -220,18 +223,19 @@ impl Args {
|
||||
ty.human_friendly_type(),
|
||||
);
|
||||
let suggestion = match (ty, actual_type_name) {
|
||||
(RuntimeType::Primitive(PrimitiveType::Solid), "Sketch") => Some(
|
||||
"You can convert a sketch (2D) into a Solid (3D) by calling a function like `extrude` or `revolve`",
|
||||
),
|
||||
(RuntimeType::Array(t, _), "Sketch") if **t == RuntimeType::Primitive(PrimitiveType::Solid) => Some(
|
||||
"You can convert a sketch (2D) into a Solid (3D) by calling a function like `extrude` or `revolve`",
|
||||
),
|
||||
(RuntimeType::Primitive(PrimitiveType::Solid), "Sketch") => Some(ERROR_STRING_SKETCH_TO_SOLID_HELPER),
|
||||
(RuntimeType::Array(t, _), "Sketch") if **t == RuntimeType::Primitive(PrimitiveType::Solid) => {
|
||||
Some(ERROR_STRING_SKETCH_TO_SOLID_HELPER)
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
let message = match suggestion {
|
||||
let mut message = match suggestion {
|
||||
None => msg_base,
|
||||
Some(sugg) => format!("{msg_base}. {sugg}"),
|
||||
};
|
||||
if message.contains("one or more Solids or imported geometry but it's actually of type Sketch") {
|
||||
message = format!("{message}. {ERROR_STRING_SKETCH_TO_SOLID_HELPER}");
|
||||
}
|
||||
KclError::Semantic(KclErrorDetails {
|
||||
source_ranges: arg.source_ranges(),
|
||||
message,
|
||||
@ -343,18 +347,20 @@ impl Args {
|
||||
ty.human_friendly_type(),
|
||||
);
|
||||
let suggestion = match (ty, actual_type_name) {
|
||||
(RuntimeType::Primitive(PrimitiveType::Solid), "Sketch") => Some(
|
||||
"You can convert a sketch (2D) into a Solid (3D) by calling a function like `extrude` or `revolve`",
|
||||
),
|
||||
(RuntimeType::Array(ty, _), "Sketch") if **ty == RuntimeType::Primitive(PrimitiveType::Solid) => Some(
|
||||
"You can convert a sketch (2D) into a Solid (3D) by calling a function like `extrude` or `revolve`",
|
||||
),
|
||||
(RuntimeType::Primitive(PrimitiveType::Solid), "Sketch") => Some(ERROR_STRING_SKETCH_TO_SOLID_HELPER),
|
||||
(RuntimeType::Array(ty, _), "Sketch") if **ty == RuntimeType::Primitive(PrimitiveType::Solid) => {
|
||||
Some(ERROR_STRING_SKETCH_TO_SOLID_HELPER)
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
let message = match suggestion {
|
||||
let mut message = match suggestion {
|
||||
None => msg_base,
|
||||
Some(sugg) => format!("{msg_base}. {sugg}"),
|
||||
};
|
||||
|
||||
if message.contains("one or more Solids or imported geometry but it's actually of type Sketch") {
|
||||
message = format!("{message}. {ERROR_STRING_SKETCH_TO_SOLID_HELPER}");
|
||||
}
|
||||
KclError::Semantic(KclErrorDetails {
|
||||
source_ranges: arg.source_ranges(),
|
||||
message,
|
||||
@ -1396,6 +1402,26 @@ impl<'a> FromKclValue<'a> for crate::execution::SolidOrSketchOrImportedGeometry
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> FromKclValue<'a> for crate::execution::SolidOrImportedGeometry {
|
||||
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
|
||||
match arg {
|
||||
KclValue::Solid { value } => Some(Self::SolidSet(vec![(**value).clone()])),
|
||||
KclValue::HomArray { value, .. } => {
|
||||
let mut solids = vec![];
|
||||
for item in value {
|
||||
match item {
|
||||
KclValue::Solid { value } => solids.push((**value).clone()),
|
||||
_ => return None,
|
||||
}
|
||||
}
|
||||
Some(Self::SolidSet(solids))
|
||||
}
|
||||
KclValue::ImportedGeometry(value) => Some(Self::ImportedGeometry(Box::new(value.clone()))),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> FromKclValue<'a> for super::sketch::SketchData {
|
||||
fn from_kcl_val(arg: &'a KclValue) -> Option<Self> {
|
||||
// Order is critical since PlaneData is a subset of Plane.
|
||||
|
||||
@ -171,7 +171,8 @@ async fn inner_scale(
|
||||
args.flush_batch_for_solids(exec_state, solids).await?;
|
||||
}
|
||||
|
||||
for object_id in objects.ids() {
|
||||
let mut objects = objects.clone();
|
||||
for object_id in objects.ids(&args.ctx).await? {
|
||||
let id = exec_state.next_uuid();
|
||||
|
||||
args.batch_modeling_cmd(
|
||||
@ -409,7 +410,8 @@ async fn inner_translate(
|
||||
args.flush_batch_for_solids(exec_state, solids).await?;
|
||||
}
|
||||
|
||||
for object_id in objects.ids() {
|
||||
let mut objects = objects.clone();
|
||||
for object_id in objects.ids(&args.ctx).await? {
|
||||
let id = exec_state.next_uuid();
|
||||
|
||||
args.batch_modeling_cmd(
|
||||
@ -774,7 +776,8 @@ async fn inner_rotate(
|
||||
args.flush_batch_for_solids(exec_state, solids).await?;
|
||||
}
|
||||
|
||||
for object_id in objects.ids() {
|
||||
let mut objects = objects.clone();
|
||||
for object_id in objects.ids(&args.ctx).await? {
|
||||
let id = exec_state.next_uuid();
|
||||
|
||||
if let (Some(axis), Some(angle)) = (axis, angle) {
|
||||
|
||||
5575229
rust/kcl-lib/tests/import_async/artifact_commands.snap
Normal file
5575229
rust/kcl-lib/tests/import_async/artifact_commands.snap
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,6 @@
|
||||
---
|
||||
source: kcl-lib/src/simulation_tests.rs
|
||||
description: Artifact graph flowchart import_async.kcl
|
||||
extension: md
|
||||
snapshot_kind: binary
|
||||
---
|
||||
503
rust/kcl-lib/tests/import_async/artifact_graph_flowchart.snap.md
Normal file
503
rust/kcl-lib/tests/import_async/artifact_graph_flowchart.snap.md
Normal file
@ -0,0 +1,503 @@
|
||||
```mermaid
|
||||
flowchart LR
|
||||
subgraph path3 [Path]
|
||||
3["Path<br>[1035, 1085, 0]"]
|
||||
4["Segment<br>[1035, 1085, 0]"]
|
||||
5[Solid2d]
|
||||
end
|
||||
subgraph path13 [Path]
|
||||
13["Path<br>[1562, 1599, 0]"]
|
||||
14["Segment<br>[1250, 1288, 0]"]
|
||||
15["Segment<br>[1250, 1288, 0]"]
|
||||
16["Segment<br>[1250, 1288, 0]"]
|
||||
17["Segment<br>[1250, 1288, 0]"]
|
||||
18["Segment<br>[1250, 1288, 0]"]
|
||||
19["Segment<br>[1250, 1288, 0]"]
|
||||
20["Segment<br>[1250, 1288, 0]"]
|
||||
21["Segment<br>[1250, 1288, 0]"]
|
||||
22["Segment<br>[1250, 1288, 0]"]
|
||||
23["Segment<br>[1250, 1288, 0]"]
|
||||
24["Segment<br>[1250, 1288, 0]"]
|
||||
25["Segment<br>[1250, 1288, 0]"]
|
||||
26["Segment<br>[1250, 1288, 0]"]
|
||||
27["Segment<br>[1250, 1288, 0]"]
|
||||
28["Segment<br>[1250, 1288, 0]"]
|
||||
29["Segment<br>[1250, 1288, 0]"]
|
||||
30["Segment<br>[1250, 1288, 0]"]
|
||||
31["Segment<br>[1250, 1288, 0]"]
|
||||
32["Segment<br>[1250, 1288, 0]"]
|
||||
33["Segment<br>[1250, 1288, 0]"]
|
||||
34["Segment<br>[1250, 1288, 0]"]
|
||||
35["Segment<br>[1250, 1288, 0]"]
|
||||
36["Segment<br>[1250, 1288, 0]"]
|
||||
37["Segment<br>[1250, 1288, 0]"]
|
||||
38["Segment<br>[1250, 1288, 0]"]
|
||||
39["Segment<br>[1250, 1288, 0]"]
|
||||
40["Segment<br>[1250, 1288, 0]"]
|
||||
41["Segment<br>[1250, 1288, 0]"]
|
||||
42["Segment<br>[1250, 1288, 0]"]
|
||||
43["Segment<br>[1250, 1288, 0]"]
|
||||
44["Segment<br>[1250, 1288, 0]"]
|
||||
45["Segment<br>[1250, 1288, 0]"]
|
||||
46["Segment<br>[1250, 1288, 0]"]
|
||||
47["Segment<br>[1250, 1288, 0]"]
|
||||
48["Segment<br>[1250, 1288, 0]"]
|
||||
49["Segment<br>[1250, 1288, 0]"]
|
||||
50["Segment<br>[1250, 1288, 0]"]
|
||||
51["Segment<br>[1250, 1288, 0]"]
|
||||
52["Segment<br>[1250, 1288, 0]"]
|
||||
53["Segment<br>[1250, 1288, 0]"]
|
||||
54["Segment<br>[1250, 1288, 0]"]
|
||||
55["Segment<br>[1250, 1288, 0]"]
|
||||
56["Segment<br>[1250, 1288, 0]"]
|
||||
57["Segment<br>[1250, 1288, 0]"]
|
||||
58["Segment<br>[1250, 1288, 0]"]
|
||||
59["Segment<br>[1250, 1288, 0]"]
|
||||
60["Segment<br>[1250, 1288, 0]"]
|
||||
61["Segment<br>[1250, 1288, 0]"]
|
||||
62["Segment<br>[1250, 1288, 0]"]
|
||||
63["Segment<br>[1250, 1288, 0]"]
|
||||
64["Segment<br>[1250, 1288, 0]"]
|
||||
65["Segment<br>[1250, 1288, 0]"]
|
||||
66["Segment<br>[1250, 1288, 0]"]
|
||||
67["Segment<br>[1250, 1288, 0]"]
|
||||
68["Segment<br>[1250, 1288, 0]"]
|
||||
69["Segment<br>[1250, 1288, 0]"]
|
||||
70["Segment<br>[1250, 1288, 0]"]
|
||||
71["Segment<br>[1250, 1288, 0]"]
|
||||
72["Segment<br>[1250, 1288, 0]"]
|
||||
73["Segment<br>[1250, 1288, 0]"]
|
||||
74["Segment<br>[1250, 1288, 0]"]
|
||||
75["Segment<br>[1250, 1288, 0]"]
|
||||
76["Segment<br>[1250, 1288, 0]"]
|
||||
77["Segment<br>[1250, 1288, 0]"]
|
||||
78["Segment<br>[1250, 1288, 0]"]
|
||||
79["Segment<br>[1250, 1288, 0]"]
|
||||
80["Segment<br>[1250, 1288, 0]"]
|
||||
81["Segment<br>[1250, 1288, 0]"]
|
||||
82["Segment<br>[1250, 1288, 0]"]
|
||||
83["Segment<br>[1250, 1288, 0]"]
|
||||
84["Segment<br>[1250, 1288, 0]"]
|
||||
85["Segment<br>[1250, 1288, 0]"]
|
||||
86["Segment<br>[1250, 1288, 0]"]
|
||||
87["Segment<br>[1250, 1288, 0]"]
|
||||
88["Segment<br>[1250, 1288, 0]"]
|
||||
89["Segment<br>[1250, 1288, 0]"]
|
||||
90["Segment<br>[1250, 1288, 0]"]
|
||||
91["Segment<br>[1250, 1288, 0]"]
|
||||
92["Segment<br>[1250, 1288, 0]"]
|
||||
93["Segment<br>[1250, 1288, 0]"]
|
||||
94["Segment<br>[1250, 1288, 0]"]
|
||||
95["Segment<br>[1250, 1288, 0]"]
|
||||
96["Segment<br>[1250, 1288, 0]"]
|
||||
97["Segment<br>[1250, 1288, 0]"]
|
||||
98["Segment<br>[1250, 1288, 0]"]
|
||||
99["Segment<br>[1250, 1288, 0]"]
|
||||
100["Segment<br>[1250, 1288, 0]"]
|
||||
101["Segment<br>[1250, 1288, 0]"]
|
||||
102["Segment<br>[1250, 1288, 0]"]
|
||||
103["Segment<br>[1250, 1288, 0]"]
|
||||
104["Segment<br>[1250, 1288, 0]"]
|
||||
105["Segment<br>[1250, 1288, 0]"]
|
||||
106["Segment<br>[1250, 1288, 0]"]
|
||||
107["Segment<br>[1250, 1288, 0]"]
|
||||
108["Segment<br>[1250, 1288, 0]"]
|
||||
109["Segment<br>[1250, 1288, 0]"]
|
||||
110["Segment<br>[1250, 1288, 0]"]
|
||||
111["Segment<br>[1250, 1288, 0]"]
|
||||
112["Segment<br>[1250, 1288, 0]"]
|
||||
113["Segment<br>[1250, 1288, 0]"]
|
||||
114["Segment<br>[1250, 1288, 0]"]
|
||||
115["Segment<br>[1651, 1753, 0]"]
|
||||
116["Segment<br>[1478, 1508, 0]"]
|
||||
117["Segment<br>[1478, 1508, 0]"]
|
||||
118["Segment<br>[1478, 1508, 0]"]
|
||||
119["Segment<br>[1478, 1508, 0]"]
|
||||
120["Segment<br>[1478, 1508, 0]"]
|
||||
121["Segment<br>[1478, 1508, 0]"]
|
||||
122["Segment<br>[1478, 1508, 0]"]
|
||||
123["Segment<br>[1478, 1508, 0]"]
|
||||
124["Segment<br>[1478, 1508, 0]"]
|
||||
125["Segment<br>[1478, 1508, 0]"]
|
||||
126["Segment<br>[1478, 1508, 0]"]
|
||||
127["Segment<br>[1478, 1508, 0]"]
|
||||
128["Segment<br>[1478, 1508, 0]"]
|
||||
129["Segment<br>[1478, 1508, 0]"]
|
||||
130["Segment<br>[1478, 1508, 0]"]
|
||||
131["Segment<br>[1478, 1508, 0]"]
|
||||
132["Segment<br>[1478, 1508, 0]"]
|
||||
133["Segment<br>[1478, 1508, 0]"]
|
||||
134["Segment<br>[1478, 1508, 0]"]
|
||||
135["Segment<br>[1478, 1508, 0]"]
|
||||
136["Segment<br>[1478, 1508, 0]"]
|
||||
137["Segment<br>[1478, 1508, 0]"]
|
||||
138["Segment<br>[1478, 1508, 0]"]
|
||||
139["Segment<br>[1478, 1508, 0]"]
|
||||
140["Segment<br>[1478, 1508, 0]"]
|
||||
141["Segment<br>[1478, 1508, 0]"]
|
||||
142["Segment<br>[1478, 1508, 0]"]
|
||||
143["Segment<br>[1478, 1508, 0]"]
|
||||
144["Segment<br>[1478, 1508, 0]"]
|
||||
145["Segment<br>[1478, 1508, 0]"]
|
||||
146["Segment<br>[1478, 1508, 0]"]
|
||||
147["Segment<br>[1478, 1508, 0]"]
|
||||
148["Segment<br>[1478, 1508, 0]"]
|
||||
149["Segment<br>[1478, 1508, 0]"]
|
||||
150["Segment<br>[1478, 1508, 0]"]
|
||||
151["Segment<br>[1478, 1508, 0]"]
|
||||
152["Segment<br>[1478, 1508, 0]"]
|
||||
153["Segment<br>[1478, 1508, 0]"]
|
||||
154["Segment<br>[1478, 1508, 0]"]
|
||||
155["Segment<br>[1478, 1508, 0]"]
|
||||
156["Segment<br>[1478, 1508, 0]"]
|
||||
157["Segment<br>[1478, 1508, 0]"]
|
||||
158["Segment<br>[1478, 1508, 0]"]
|
||||
159["Segment<br>[1478, 1508, 0]"]
|
||||
160["Segment<br>[1478, 1508, 0]"]
|
||||
161["Segment<br>[1478, 1508, 0]"]
|
||||
162["Segment<br>[1478, 1508, 0]"]
|
||||
163["Segment<br>[1478, 1508, 0]"]
|
||||
164["Segment<br>[1478, 1508, 0]"]
|
||||
165["Segment<br>[1478, 1508, 0]"]
|
||||
166["Segment<br>[1478, 1508, 0]"]
|
||||
167["Segment<br>[1478, 1508, 0]"]
|
||||
168["Segment<br>[1478, 1508, 0]"]
|
||||
169["Segment<br>[1478, 1508, 0]"]
|
||||
170["Segment<br>[1478, 1508, 0]"]
|
||||
171["Segment<br>[1478, 1508, 0]"]
|
||||
172["Segment<br>[1478, 1508, 0]"]
|
||||
173["Segment<br>[1478, 1508, 0]"]
|
||||
174["Segment<br>[1478, 1508, 0]"]
|
||||
175["Segment<br>[1478, 1508, 0]"]
|
||||
176["Segment<br>[1478, 1508, 0]"]
|
||||
177["Segment<br>[1478, 1508, 0]"]
|
||||
178["Segment<br>[1478, 1508, 0]"]
|
||||
179["Segment<br>[1478, 1508, 0]"]
|
||||
180["Segment<br>[1478, 1508, 0]"]
|
||||
181["Segment<br>[1478, 1508, 0]"]
|
||||
182["Segment<br>[1478, 1508, 0]"]
|
||||
183["Segment<br>[1478, 1508, 0]"]
|
||||
184["Segment<br>[1478, 1508, 0]"]
|
||||
185["Segment<br>[1478, 1508, 0]"]
|
||||
186["Segment<br>[1478, 1508, 0]"]
|
||||
187["Segment<br>[1478, 1508, 0]"]
|
||||
188["Segment<br>[1478, 1508, 0]"]
|
||||
189["Segment<br>[1478, 1508, 0]"]
|
||||
190["Segment<br>[1478, 1508, 0]"]
|
||||
191["Segment<br>[1478, 1508, 0]"]
|
||||
192["Segment<br>[1478, 1508, 0]"]
|
||||
193["Segment<br>[1478, 1508, 0]"]
|
||||
194["Segment<br>[1478, 1508, 0]"]
|
||||
195["Segment<br>[1478, 1508, 0]"]
|
||||
196["Segment<br>[1478, 1508, 0]"]
|
||||
197["Segment<br>[1478, 1508, 0]"]
|
||||
198["Segment<br>[1478, 1508, 0]"]
|
||||
199["Segment<br>[1478, 1508, 0]"]
|
||||
200["Segment<br>[1478, 1508, 0]"]
|
||||
201["Segment<br>[1478, 1508, 0]"]
|
||||
202["Segment<br>[1478, 1508, 0]"]
|
||||
203["Segment<br>[1478, 1508, 0]"]
|
||||
204["Segment<br>[1478, 1508, 0]"]
|
||||
205["Segment<br>[1478, 1508, 0]"]
|
||||
206["Segment<br>[1478, 1508, 0]"]
|
||||
207["Segment<br>[1478, 1508, 0]"]
|
||||
208["Segment<br>[1478, 1508, 0]"]
|
||||
209["Segment<br>[1478, 1508, 0]"]
|
||||
210["Segment<br>[1478, 1508, 0]"]
|
||||
211["Segment<br>[1478, 1508, 0]"]
|
||||
212["Segment<br>[1478, 1508, 0]"]
|
||||
213["Segment<br>[1478, 1508, 0]"]
|
||||
214["Segment<br>[1478, 1508, 0]"]
|
||||
215["Segment<br>[1478, 1508, 0]"]
|
||||
216["Segment<br>[1478, 1508, 0]"]
|
||||
217["Segment<br>[1799, 1806, 0]"]
|
||||
218[Solid2d]
|
||||
end
|
||||
subgraph path220 [Path]
|
||||
220["Path<br>[2287, 2387, 0]"]
|
||||
221["Segment<br>[2393, 2420, 0]"]
|
||||
222["Segment<br>[2426, 2454, 0]"]
|
||||
223["Segment<br>[2460, 2488, 0]"]
|
||||
224["Segment<br>[2494, 2614, 0]"]
|
||||
225["Segment<br>[2620, 2729, 0]"]
|
||||
226["Segment<br>[2735, 2742, 0]"]
|
||||
227[Solid2d]
|
||||
end
|
||||
1["Plane<br>[168, 185, 0]"]
|
||||
2["Plane<br>[1012, 1029, 0]"]
|
||||
6["Sweep Extrusion<br>[1091, 1119, 0]"]
|
||||
7[Wall]
|
||||
8["Cap Start"]
|
||||
9["Cap End"]
|
||||
10["SweepEdge Opposite"]
|
||||
11["SweepEdge Adjacent"]
|
||||
12["Plane<br>[1539, 1556, 0]"]
|
||||
219["Sweep Extrusion<br>[1812, 1840, 0]"]
|
||||
228["Sweep Extrusion<br>[2748, 2777, 0]"]
|
||||
229[Wall]
|
||||
230[Wall]
|
||||
231[Wall]
|
||||
232[Wall]
|
||||
233["SweepEdge Opposite"]
|
||||
234["SweepEdge Adjacent"]
|
||||
235["SweepEdge Opposite"]
|
||||
236["SweepEdge Adjacent"]
|
||||
237["SweepEdge Opposite"]
|
||||
238["SweepEdge Adjacent"]
|
||||
239["SweepEdge Opposite"]
|
||||
240["SweepEdge Adjacent"]
|
||||
241["StartSketchOnFace<br>[2250, 2281, 0]"]
|
||||
2 --- 3
|
||||
3 --- 4
|
||||
3 ---- 6
|
||||
3 --- 5
|
||||
4 --- 7
|
||||
4 --- 10
|
||||
4 --- 11
|
||||
6 --- 7
|
||||
6 --- 8
|
||||
6 --- 9
|
||||
6 --- 10
|
||||
6 --- 11
|
||||
9 --- 220
|
||||
12 --- 13
|
||||
13 --- 14
|
||||
13 --- 15
|
||||
13 --- 16
|
||||
13 --- 17
|
||||
13 --- 18
|
||||
13 --- 19
|
||||
13 --- 20
|
||||
13 --- 21
|
||||
13 --- 22
|
||||
13 --- 23
|
||||
13 --- 24
|
||||
13 --- 25
|
||||
13 --- 26
|
||||
13 --- 27
|
||||
13 --- 28
|
||||
13 --- 29
|
||||
13 --- 30
|
||||
13 --- 31
|
||||
13 --- 32
|
||||
13 --- 33
|
||||
13 --- 34
|
||||
13 --- 35
|
||||
13 --- 36
|
||||
13 --- 37
|
||||
13 --- 38
|
||||
13 --- 39
|
||||
13 --- 40
|
||||
13 --- 41
|
||||
13 --- 42
|
||||
13 --- 43
|
||||
13 --- 44
|
||||
13 --- 45
|
||||
13 --- 46
|
||||
13 --- 47
|
||||
13 --- 48
|
||||
13 --- 49
|
||||
13 --- 50
|
||||
13 --- 51
|
||||
13 --- 52
|
||||
13 --- 53
|
||||
13 --- 54
|
||||
13 --- 55
|
||||
13 --- 56
|
||||
13 --- 57
|
||||
13 --- 58
|
||||
13 --- 59
|
||||
13 --- 60
|
||||
13 --- 61
|
||||
13 --- 62
|
||||
13 --- 63
|
||||
13 --- 64
|
||||
13 --- 65
|
||||
13 --- 66
|
||||
13 --- 67
|
||||
13 --- 68
|
||||
13 --- 69
|
||||
13 --- 70
|
||||
13 --- 71
|
||||
13 --- 72
|
||||
13 --- 73
|
||||
13 --- 74
|
||||
13 --- 75
|
||||
13 --- 76
|
||||
13 --- 77
|
||||
13 --- 78
|
||||
13 --- 79
|
||||
13 --- 80
|
||||
13 --- 81
|
||||
13 --- 82
|
||||
13 --- 83
|
||||
13 --- 84
|
||||
13 --- 85
|
||||
13 --- 86
|
||||
13 --- 87
|
||||
13 --- 88
|
||||
13 --- 89
|
||||
13 --- 90
|
||||
13 --- 91
|
||||
13 --- 92
|
||||
13 --- 93
|
||||
13 --- 94
|
||||
13 --- 95
|
||||
13 --- 96
|
||||
13 --- 97
|
||||
13 --- 98
|
||||
13 --- 99
|
||||
13 --- 100
|
||||
13 --- 101
|
||||
13 --- 102
|
||||
13 --- 103
|
||||
13 --- 104
|
||||
13 --- 105
|
||||
13 --- 106
|
||||
13 --- 107
|
||||
13 --- 108
|
||||
13 --- 109
|
||||
13 --- 110
|
||||
13 --- 111
|
||||
13 --- 112
|
||||
13 --- 113
|
||||
13 --- 114
|
||||
13 --- 115
|
||||
13 --- 116
|
||||
13 --- 117
|
||||
13 --- 118
|
||||
13 --- 119
|
||||
13 --- 120
|
||||
13 --- 121
|
||||
13 --- 122
|
||||
13 --- 123
|
||||
13 --- 124
|
||||
13 --- 125
|
||||
13 --- 126
|
||||
13 --- 127
|
||||
13 --- 128
|
||||
13 --- 129
|
||||
13 --- 130
|
||||
13 --- 131
|
||||
13 --- 132
|
||||
13 --- 133
|
||||
13 --- 134
|
||||
13 --- 135
|
||||
13 --- 136
|
||||
13 --- 137
|
||||
13 --- 138
|
||||
13 --- 139
|
||||
13 --- 140
|
||||
13 --- 141
|
||||
13 --- 142
|
||||
13 --- 143
|
||||
13 --- 144
|
||||
13 --- 145
|
||||
13 --- 146
|
||||
13 --- 147
|
||||
13 --- 148
|
||||
13 --- 149
|
||||
13 --- 150
|
||||
13 --- 151
|
||||
13 --- 152
|
||||
13 --- 153
|
||||
13 --- 154
|
||||
13 --- 155
|
||||
13 --- 156
|
||||
13 --- 157
|
||||
13 --- 158
|
||||
13 --- 159
|
||||
13 --- 160
|
||||
13 --- 161
|
||||
13 --- 162
|
||||
13 --- 163
|
||||
13 --- 164
|
||||
13 --- 165
|
||||
13 --- 166
|
||||
13 --- 167
|
||||
13 --- 168
|
||||
13 --- 169
|
||||
13 --- 170
|
||||
13 --- 171
|
||||
13 --- 172
|
||||
13 --- 173
|
||||
13 --- 174
|
||||
13 --- 175
|
||||
13 --- 176
|
||||
13 --- 177
|
||||
13 --- 178
|
||||
13 --- 179
|
||||
13 --- 180
|
||||
13 --- 181
|
||||
13 --- 182
|
||||
13 --- 183
|
||||
13 --- 184
|
||||
13 --- 185
|
||||
13 --- 186
|
||||
13 --- 187
|
||||
13 --- 188
|
||||
13 --- 189
|
||||
13 --- 190
|
||||
13 --- 191
|
||||
13 --- 192
|
||||
13 --- 193
|
||||
13 --- 194
|
||||
13 --- 195
|
||||
13 --- 196
|
||||
13 --- 197
|
||||
13 --- 198
|
||||
13 --- 199
|
||||
13 --- 200
|
||||
13 --- 201
|
||||
13 --- 202
|
||||
13 --- 203
|
||||
13 --- 204
|
||||
13 --- 205
|
||||
13 --- 206
|
||||
13 --- 207
|
||||
13 --- 208
|
||||
13 --- 209
|
||||
13 --- 210
|
||||
13 --- 211
|
||||
13 --- 212
|
||||
13 --- 213
|
||||
13 --- 214
|
||||
13 --- 215
|
||||
13 --- 216
|
||||
13 --- 217
|
||||
13 ---- 219
|
||||
13 --- 218
|
||||
220 --- 221
|
||||
220 --- 222
|
||||
220 --- 223
|
||||
220 --- 224
|
||||
220 --- 225
|
||||
220 --- 226
|
||||
220 ---- 228
|
||||
220 --- 227
|
||||
221 --- 232
|
||||
221 --- 239
|
||||
221 --- 240
|
||||
222 --- 231
|
||||
222 --- 237
|
||||
222 --- 238
|
||||
223 --- 230
|
||||
223 --- 235
|
||||
223 --- 236
|
||||
225 --- 229
|
||||
225 --- 233
|
||||
225 --- 234
|
||||
228 --- 229
|
||||
228 --- 230
|
||||
228 --- 231
|
||||
228 --- 232
|
||||
228 --- 233
|
||||
228 --- 234
|
||||
228 --- 235
|
||||
228 --- 236
|
||||
228 --- 237
|
||||
228 --- 238
|
||||
228 --- 239
|
||||
228 --- 240
|
||||
9 <--x 241
|
||||
```
|
||||
5103
rust/kcl-lib/tests/import_async/ast.snap
Normal file
5103
rust/kcl-lib/tests/import_async/ast.snap
Normal file
File diff suppressed because it is too large
Load Diff
117
rust/kcl-lib/tests/import_async/input.kcl
Normal file
117
rust/kcl-lib/tests/import_async/input.kcl
Normal file
@ -0,0 +1,117 @@
|
||||
@(lengthUnit = m)
|
||||
import "../../e2e/executor/inputs/2-5-long-m8-chc-screw.stl" as screw
|
||||
|
||||
// Set units
|
||||
@settings(defaultLengthUnit = mm)
|
||||
|
||||
myScrew = screw
|
||||
|
||||
|
||||
surface001 = startSketchOn(XY)
|
||||
|
||||
// Define parameters
|
||||
nTeeth = 21
|
||||
module = 0.5
|
||||
pitchDiameter = module * nTeeth
|
||||
pressureAngle = 20
|
||||
addendum = module
|
||||
deddendum = 1.25 * module
|
||||
baseDiameter = pitchDiameter * cos(toRadians(pressureAngle))
|
||||
tipDiameter = pitchDiameter + 2 * module
|
||||
gearHeight = 3
|
||||
|
||||
// Interpolate points along the involute curve
|
||||
cmo = 101
|
||||
rs = map([0..cmo], fn(i) {
|
||||
return baseDiameter / 2 + i / cmo * (tipDiameter - baseDiameter) / 2
|
||||
})
|
||||
|
||||
// Calculate operating pressure angle
|
||||
angles = map(rs, fn(r) {
|
||||
return toDegrees( acos(baseDiameter / 2 / r))
|
||||
})
|
||||
|
||||
// Calculate the involute function
|
||||
invas = map(angles, fn(a) {
|
||||
return tan(toRadians(a)) - toRadians(a)
|
||||
})
|
||||
|
||||
// Map the involute curve
|
||||
xs = map([0..cmo], fn(i) {
|
||||
return rs[i] * cos(invas[i])
|
||||
})
|
||||
|
||||
ys = map([0..cmo], fn(i) {
|
||||
return rs[i] * sin(invas[i])
|
||||
})
|
||||
|
||||
// Extrude the gear body
|
||||
body = startSketchOn(XY)
|
||||
|> circle(center = [0, 0], radius = baseDiameter / 2)
|
||||
|> extrude(length = gearHeight)
|
||||
|
||||
toothAngle = 360 / nTeeth / 1.5
|
||||
|
||||
// Plot the involute curve
|
||||
fn leftInvolute(i, sg) {
|
||||
j = 100 - i // iterate backwards
|
||||
return line(sg, endAbsolute = [xs[j], ys[j]])
|
||||
}
|
||||
|
||||
fn rightInvolute(i, sg) {
|
||||
x = rs[i] * cos(toRadians(-toothAngle + toDegrees(atan(ys[i] / xs[i]))))
|
||||
y = -rs[i] * sin(toRadians(-toothAngle + toDegrees(atan(ys[i] / xs[i]))))
|
||||
return line(sg, endAbsolute = [x, y])
|
||||
}
|
||||
|
||||
// Draw gear teeth
|
||||
start = startSketchOn(XY)
|
||||
|> startProfileAt([xs[101], ys[101]], %)
|
||||
teeth = reduce([0..100], start, leftInvolute)
|
||||
|> arc({
|
||||
angleStart = 0,
|
||||
angleEnd = toothAngle,
|
||||
radius = baseDiameter / 2
|
||||
}, %)
|
||||
|> reduce([1..101], %, rightInvolute)
|
||||
|> close()
|
||||
|> extrude(length = gearHeight)
|
||||
|> patternCircular3d(
|
||||
axis = [0, 0, 1],
|
||||
center = [0, 0, 0],
|
||||
instances = nTeeth,
|
||||
arcDegrees = 360,
|
||||
rotateDuplicates = true,
|
||||
)
|
||||
|
||||
// Define the constants of the keyway and the bore hole
|
||||
keywayWidth = 0.250
|
||||
keywayDepth = keywayWidth / 2
|
||||
holeDiam = 2
|
||||
holeRadius = 1
|
||||
startAngle = asin(keywayWidth / 2 / holeRadius)
|
||||
|
||||
// Sketch the keyway and center hole and extrude
|
||||
keyWay = startSketchOn(body, face = END)
|
||||
|> startProfileAt([
|
||||
holeRadius * cos(startAngle),
|
||||
holeRadius * sin(startAngle)
|
||||
], %)
|
||||
|> xLine(length = keywayDepth)
|
||||
|> yLine(length = -keywayWidth)
|
||||
|> xLine(length = -keywayDepth)
|
||||
|> arc({
|
||||
angleEnd = 180,
|
||||
angleStart = -1 * toDegrees(startAngle) + 360,
|
||||
radius = holeRadius
|
||||
}, %)
|
||||
|> arc({
|
||||
angleEnd = toDegrees(startAngle),
|
||||
angleStart = 180,
|
||||
radius = holeRadius
|
||||
}, %)
|
||||
|> close()
|
||||
|> extrude(length = -gearHeight)
|
||||
|
||||
myScrew
|
||||
|> translate(y=10)
|
||||
9529
rust/kcl-lib/tests/import_async/ops.snap
Normal file
9529
rust/kcl-lib/tests/import_async/ops.snap
Normal file
File diff suppressed because it is too large
Load Diff
89754
rust/kcl-lib/tests/import_async/program_memory.snap
Normal file
89754
rust/kcl-lib/tests/import_async/program_memory.snap
Normal file
File diff suppressed because it is too large
Load Diff
BIN
rust/kcl-lib/tests/import_async/rendered_model.png
Normal file
BIN
rust/kcl-lib/tests/import_async/rendered_model.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 55 KiB |
120
rust/kcl-lib/tests/import_async/unparsed.snap
Normal file
120
rust/kcl-lib/tests/import_async/unparsed.snap
Normal file
@ -0,0 +1,120 @@
|
||||
---
|
||||
source: kcl-lib/src/simulation_tests.rs
|
||||
description: Result of unparsing import_async.kcl
|
||||
---
|
||||
// Set units
|
||||
@settings(defaultLengthUnit = mm)
|
||||
|
||||
@(lengthUnit = m)
|
||||
import "../../e2e/executor/inputs/2-5-long-m8-chc-screw.stl" as screw
|
||||
|
||||
myScrew = screw
|
||||
|
||||
surface001 = startSketchOn(XY)
|
||||
|
||||
// Define parameters
|
||||
nTeeth = 21
|
||||
module = 0.5
|
||||
pitchDiameter = module * nTeeth
|
||||
pressureAngle = 20
|
||||
addendum = module
|
||||
deddendum = 1.25 * module
|
||||
baseDiameter = pitchDiameter * cos(toRadians(pressureAngle))
|
||||
tipDiameter = pitchDiameter + 2 * module
|
||||
gearHeight = 3
|
||||
|
||||
// Interpolate points along the involute curve
|
||||
cmo = 101
|
||||
rs = map([0..cmo], fn(i) {
|
||||
return baseDiameter / 2 + i / cmo * (tipDiameter - baseDiameter) / 2
|
||||
})
|
||||
|
||||
// Calculate operating pressure angle
|
||||
angles = map(rs, fn(r) {
|
||||
return toDegrees( acos(baseDiameter / 2 / r))
|
||||
})
|
||||
|
||||
// Calculate the involute function
|
||||
invas = map(angles, fn(a) {
|
||||
return tan(toRadians(a)) - toRadians(a)
|
||||
})
|
||||
|
||||
// Map the involute curve
|
||||
xs = map([0..cmo], fn(i) {
|
||||
return rs[i] * cos(invas[i])
|
||||
})
|
||||
|
||||
ys = map([0..cmo], fn(i) {
|
||||
return rs[i] * sin(invas[i])
|
||||
})
|
||||
|
||||
// Extrude the gear body
|
||||
body = startSketchOn(XY)
|
||||
|> circle(center = [0, 0], radius = baseDiameter / 2)
|
||||
|> extrude(length = gearHeight)
|
||||
|
||||
toothAngle = 360 / nTeeth / 1.5
|
||||
|
||||
// Plot the involute curve
|
||||
fn leftInvolute(i, sg) {
|
||||
j = 100 - i // iterate backwards
|
||||
return line(sg, endAbsolute = [xs[j], ys[j]])
|
||||
}
|
||||
|
||||
fn rightInvolute(i, sg) {
|
||||
x = rs[i] * cos(toRadians(-toothAngle + toDegrees(atan(ys[i] / xs[i]))))
|
||||
y = -rs[i] * sin(toRadians(-toothAngle + toDegrees(atan(ys[i] / xs[i]))))
|
||||
return line(sg, endAbsolute = [x, y])
|
||||
}
|
||||
|
||||
// Draw gear teeth
|
||||
start = startSketchOn(XY)
|
||||
|> startProfileAt([xs[101], ys[101]], %)
|
||||
teeth = reduce([0..100], start, leftInvolute)
|
||||
|> arc({
|
||||
angleStart = 0,
|
||||
angleEnd = toothAngle,
|
||||
radius = baseDiameter / 2
|
||||
}, %)
|
||||
|> reduce([1..101], %, rightInvolute)
|
||||
|> close()
|
||||
|> extrude(length = gearHeight)
|
||||
|> patternCircular3d(
|
||||
axis = [0, 0, 1],
|
||||
center = [0, 0, 0],
|
||||
instances = nTeeth,
|
||||
arcDegrees = 360,
|
||||
rotateDuplicates = true,
|
||||
)
|
||||
|
||||
// Define the constants of the keyway and the bore hole
|
||||
keywayWidth = 0.250
|
||||
keywayDepth = keywayWidth / 2
|
||||
holeDiam = 2
|
||||
holeRadius = 1
|
||||
startAngle = asin(keywayWidth / 2 / holeRadius)
|
||||
|
||||
// Sketch the keyway and center hole and extrude
|
||||
keyWay = startSketchOn(body, face = END)
|
||||
|> startProfileAt([
|
||||
holeRadius * cos(startAngle),
|
||||
holeRadius * sin(startAngle)
|
||||
], %)
|
||||
|> xLine(length = keywayDepth)
|
||||
|> yLine(length = -keywayWidth)
|
||||
|> xLine(length = -keywayDepth)
|
||||
|> arc({
|
||||
angleEnd = 180,
|
||||
angleStart = -1 * toDegrees(startAngle) + 360,
|
||||
radius = holeRadius
|
||||
}, %)
|
||||
|> arc({
|
||||
angleEnd = toDegrees(startAngle),
|
||||
angleStart = 180,
|
||||
radius = holeRadius
|
||||
}, %)
|
||||
|> close()
|
||||
|> extrude(length = -gearHeight)
|
||||
|
||||
myScrew
|
||||
|> translate(y = 10)
|
||||
5506
rust/kcl-lib/tests/kcl_samples/axial-fan/artifact_commands.snap
Normal file
5506
rust/kcl-lib/tests/kcl_samples/axial-fan/artifact_commands.snap
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,6 @@
|
||||
---
|
||||
source: kcl-lib/src/simulation_tests.rs
|
||||
description: Artifact graph flowchart axial-fan.kcl
|
||||
extension: md
|
||||
snapshot_kind: binary
|
||||
---
|
||||
@ -0,0 +1,754 @@
|
||||
```mermaid
|
||||
flowchart LR
|
||||
subgraph path2 [Path]
|
||||
2["Path<br>[323, 370, 5]"]
|
||||
3["Segment<br>[376, 444, 5]"]
|
||||
4["Segment<br>[450, 550, 5]"]
|
||||
5["Segment<br>[556, 673, 5]"]
|
||||
6["Segment<br>[679, 764, 5]"]
|
||||
7["Segment<br>[770, 777, 5]"]
|
||||
8[Solid2d]
|
||||
end
|
||||
subgraph path9 [Path]
|
||||
9["Path<br>[788, 823, 5]"]
|
||||
10["Segment<br>[788, 823, 5]"]
|
||||
11[Solid2d]
|
||||
end
|
||||
subgraph path12 [Path]
|
||||
12["Path<br>[838, 985, 5]"]
|
||||
13["Segment<br>[838, 985, 5]"]
|
||||
14[Solid2d]
|
||||
end
|
||||
subgraph path15 [Path]
|
||||
15["Path<br>[1000, 1148, 5]"]
|
||||
16["Segment<br>[1000, 1148, 5]"]
|
||||
17[Solid2d]
|
||||
end
|
||||
subgraph path18 [Path]
|
||||
18["Path<br>[1163, 1311, 5]"]
|
||||
19["Segment<br>[1163, 1311, 5]"]
|
||||
20[Solid2d]
|
||||
end
|
||||
subgraph path21 [Path]
|
||||
21["Path<br>[1326, 1475, 5]"]
|
||||
22["Segment<br>[1326, 1475, 5]"]
|
||||
23[Solid2d]
|
||||
end
|
||||
subgraph path39 [Path]
|
||||
39["Path<br>[1646, 1702, 5]"]
|
||||
40["Segment<br>[1708, 1773, 5]"]
|
||||
41["Segment<br>[1779, 1831, 5]"]
|
||||
42["Segment<br>[1837, 1888, 5]"]
|
||||
43["Segment<br>[1894, 1946, 5]"]
|
||||
44["Segment<br>[1952, 2018, 5]"]
|
||||
45["Segment<br>[2024, 2076, 5]"]
|
||||
46["Segment<br>[2082, 2114, 5]"]
|
||||
47["Segment<br>[2120, 2185, 5]"]
|
||||
48["Segment<br>[2191, 2198, 5]"]
|
||||
49[Solid2d]
|
||||
end
|
||||
subgraph path78 [Path]
|
||||
78["Path<br>[2547, 2660, 5]"]
|
||||
79["Segment<br>[2666, 2721, 5]"]
|
||||
80["Segment<br>[2727, 2762, 5]"]
|
||||
81["Segment<br>[2768, 2823, 5]"]
|
||||
82["Segment<br>[2829, 2865, 5]"]
|
||||
83["Segment<br>[2871, 2926, 5]"]
|
||||
84["Segment<br>[2932, 2968, 5]"]
|
||||
85["Segment<br>[2974, 3029, 5]"]
|
||||
86["Segment<br>[3035, 3091, 5]"]
|
||||
end
|
||||
subgraph path113 [Path]
|
||||
113["Path<br>[3240, 3291, 5]"]
|
||||
114["Segment<br>[3240, 3291, 5]"]
|
||||
115[Solid2d]
|
||||
end
|
||||
subgraph path120 [Path]
|
||||
120["Path<br>[3470, 3529, 5]"]
|
||||
121["Segment<br>[3535, 3603, 5]"]
|
||||
122["Segment<br>[3609, 3709, 5]"]
|
||||
123["Segment<br>[3715, 3832, 5]"]
|
||||
124["Segment<br>[3838, 3923, 5]"]
|
||||
125["Segment<br>[3929, 3936, 5]"]
|
||||
126[Solid2d]
|
||||
end
|
||||
subgraph path127 [Path]
|
||||
127["Path<br>[3947, 3998, 5]"]
|
||||
128["Segment<br>[3947, 3998, 5]"]
|
||||
129[Solid2d]
|
||||
end
|
||||
subgraph path130 [Path]
|
||||
130["Path<br>[4013, 4160, 5]"]
|
||||
131["Segment<br>[4013, 4160, 5]"]
|
||||
132[Solid2d]
|
||||
end
|
||||
subgraph path133 [Path]
|
||||
133["Path<br>[4175, 4323, 5]"]
|
||||
134["Segment<br>[4175, 4323, 5]"]
|
||||
135[Solid2d]
|
||||
end
|
||||
subgraph path136 [Path]
|
||||
136["Path<br>[4338, 4486, 5]"]
|
||||
137["Segment<br>[4338, 4486, 5]"]
|
||||
138[Solid2d]
|
||||
end
|
||||
subgraph path139 [Path]
|
||||
139["Path<br>[4501, 4650, 5]"]
|
||||
140["Segment<br>[4501, 4650, 5]"]
|
||||
141[Solid2d]
|
||||
end
|
||||
subgraph path157 [Path]
|
||||
157["Path<br>[4795, 4833, 5]"]
|
||||
158["Segment<br>[4795, 4833, 5]"]
|
||||
159[Solid2d]
|
||||
end
|
||||
subgraph path165 [Path]
|
||||
165["Path<br>[4906, 4942, 5]"]
|
||||
166["Segment<br>[4906, 4942, 5]"]
|
||||
167[Solid2d]
|
||||
end
|
||||
subgraph path181 [Path]
|
||||
181["Path<br>[277, 327, 6]"]
|
||||
182["Segment<br>[277, 327, 6]"]
|
||||
183[Solid2d]
|
||||
end
|
||||
subgraph path191 [Path]
|
||||
191["Path<br>[502, 537, 6]"]
|
||||
192["Segment<br>[502, 537, 6]"]
|
||||
193[Solid2d]
|
||||
end
|
||||
subgraph path203 [Path]
|
||||
203["Path<br>[216, 255, 7]"]
|
||||
204["Segment<br>[261, 291, 7]"]
|
||||
205["Segment<br>[297, 336, 7]"]
|
||||
206["Segment<br>[342, 366, 7]"]
|
||||
207["Segment<br>[372, 396, 7]"]
|
||||
208["Segment<br>[402, 443, 7]"]
|
||||
209["Segment<br>[449, 487, 7]"]
|
||||
210["Segment<br>[493, 516, 7]"]
|
||||
211["Segment<br>[522, 539, 7]"]
|
||||
212["Segment<br>[545, 566, 7]"]
|
||||
213["Segment<br>[572, 659, 7]"]
|
||||
214["Segment<br>[665, 702, 7]"]
|
||||
215["Segment<br>[708, 745, 7]"]
|
||||
216["Segment<br>[751, 758, 7]"]
|
||||
217[Solid2d]
|
||||
end
|
||||
subgraph path243 [Path]
|
||||
243["Path<br>[1100, 1212, 7]"]
|
||||
244["Segment<br>[1220, 1330, 7]"]
|
||||
245["Segment<br>[1338, 1672, 7]"]
|
||||
246["Segment<br>[1680, 2016, 7]"]
|
||||
247["Segment<br>[2024, 2255, 7]"]
|
||||
248["Segment<br>[2263, 2270, 7]"]
|
||||
249[Solid2d]
|
||||
end
|
||||
subgraph path251 [Path]
|
||||
251["Path<br>[1100, 1212, 7]"]
|
||||
252["Segment<br>[1220, 1330, 7]"]
|
||||
253["Segment<br>[1338, 1672, 7]"]
|
||||
254["Segment<br>[1680, 2016, 7]"]
|
||||
255["Segment<br>[2024, 2255, 7]"]
|
||||
256["Segment<br>[2263, 2270, 7]"]
|
||||
257[Solid2d]
|
||||
end
|
||||
subgraph path259 [Path]
|
||||
259["Path<br>[1100, 1212, 7]"]
|
||||
264["Segment<br>[2263, 2270, 7]"]
|
||||
265[Solid2d]
|
||||
end
|
||||
1["Plane<br>[300, 317, 5]"]
|
||||
24["Sweep Extrusion<br>[1485, 1504, 5]"]
|
||||
25[Wall]
|
||||
26[Wall]
|
||||
27[Wall]
|
||||
28[Wall]
|
||||
29["Cap Start"]
|
||||
30["Cap End"]
|
||||
31["SweepEdge Opposite"]
|
||||
32["SweepEdge Adjacent"]
|
||||
33["SweepEdge Opposite"]
|
||||
34["SweepEdge Adjacent"]
|
||||
35["SweepEdge Opposite"]
|
||||
36["SweepEdge Adjacent"]
|
||||
37["SweepEdge Opposite"]
|
||||
38["SweepEdge Adjacent"]
|
||||
50["Sweep Extrusion<br>[2338, 2358, 5]"]
|
||||
51[Wall]
|
||||
52[Wall]
|
||||
53[Wall]
|
||||
54[Wall]
|
||||
55[Wall]
|
||||
56[Wall]
|
||||
57[Wall]
|
||||
58[Wall]
|
||||
59["SweepEdge Opposite"]
|
||||
60["SweepEdge Adjacent"]
|
||||
61["SweepEdge Opposite"]
|
||||
62["SweepEdge Adjacent"]
|
||||
63["SweepEdge Opposite"]
|
||||
64["SweepEdge Adjacent"]
|
||||
65["SweepEdge Opposite"]
|
||||
66["SweepEdge Adjacent"]
|
||||
67["SweepEdge Opposite"]
|
||||
68["SweepEdge Adjacent"]
|
||||
69["SweepEdge Opposite"]
|
||||
70["SweepEdge Adjacent"]
|
||||
71["SweepEdge Opposite"]
|
||||
72["SweepEdge Adjacent"]
|
||||
73["SweepEdge Opposite"]
|
||||
74["SweepEdge Adjacent"]
|
||||
75["Sweep Extrusion<br>[2338, 2358, 5]"]
|
||||
76["Sweep Extrusion<br>[2338, 2358, 5]"]
|
||||
77["Sweep Extrusion<br>[2338, 2358, 5]"]
|
||||
87["Sweep Extrusion<br>[3097, 3132, 5]"]
|
||||
88[Wall]
|
||||
89[Wall]
|
||||
90[Wall]
|
||||
91[Wall]
|
||||
92[Wall]
|
||||
93[Wall]
|
||||
94[Wall]
|
||||
95[Wall]
|
||||
96["Cap End"]
|
||||
97["SweepEdge Opposite"]
|
||||
98["SweepEdge Adjacent"]
|
||||
99["SweepEdge Opposite"]
|
||||
100["SweepEdge Adjacent"]
|
||||
101["SweepEdge Opposite"]
|
||||
102["SweepEdge Adjacent"]
|
||||
103["SweepEdge Opposite"]
|
||||
104["SweepEdge Adjacent"]
|
||||
105["SweepEdge Opposite"]
|
||||
106["SweepEdge Adjacent"]
|
||||
107["SweepEdge Opposite"]
|
||||
108["SweepEdge Adjacent"]
|
||||
109["SweepEdge Opposite"]
|
||||
110["SweepEdge Adjacent"]
|
||||
111["SweepEdge Opposite"]
|
||||
112["SweepEdge Adjacent"]
|
||||
116["Sweep Extrusion<br>[3297, 3335, 5]"]
|
||||
117[Wall]
|
||||
118["SweepEdge Opposite"]
|
||||
119["SweepEdge Adjacent"]
|
||||
142["Sweep Extrusion<br>[4660, 4679, 5]"]
|
||||
143[Wall]
|
||||
144[Wall]
|
||||
145[Wall]
|
||||
146[Wall]
|
||||
147["Cap Start"]
|
||||
148["Cap End"]
|
||||
149["SweepEdge Opposite"]
|
||||
150["SweepEdge Adjacent"]
|
||||
151["SweepEdge Opposite"]
|
||||
152["SweepEdge Adjacent"]
|
||||
153["SweepEdge Opposite"]
|
||||
154["SweepEdge Adjacent"]
|
||||
155["SweepEdge Opposite"]
|
||||
156["SweepEdge Adjacent"]
|
||||
160["Sweep Extrusion<br>[4839, 4859, 5]"]
|
||||
161[Wall]
|
||||
162["Cap End"]
|
||||
163["SweepEdge Opposite"]
|
||||
164["SweepEdge Adjacent"]
|
||||
168["Sweep Extrusion<br>[4948, 4969, 5]"]
|
||||
169[Wall]
|
||||
170["SweepEdge Opposite"]
|
||||
171["SweepEdge Adjacent"]
|
||||
172["EdgeCut Fillet<br>[5010, 5521, 5]"]
|
||||
173["EdgeCut Fillet<br>[5010, 5521, 5]"]
|
||||
174["EdgeCut Fillet<br>[5010, 5521, 5]"]
|
||||
175["EdgeCut Fillet<br>[5010, 5521, 5]"]
|
||||
176["EdgeCut Fillet<br>[5010, 5521, 5]"]
|
||||
177["EdgeCut Fillet<br>[5010, 5521, 5]"]
|
||||
178["EdgeCut Fillet<br>[5010, 5521, 5]"]
|
||||
179["EdgeCut Fillet<br>[5010, 5521, 5]"]
|
||||
180["Plane<br>[204, 231, 6]"]
|
||||
184["Sweep Extrusion<br>[333, 353, 6]"]
|
||||
185[Wall]
|
||||
186["Cap Start"]
|
||||
187["Cap End"]
|
||||
188["SweepEdge Opposite"]
|
||||
189["SweepEdge Adjacent"]
|
||||
190["Plane<br>[467, 495, 6]"]
|
||||
194["Sweep Extrusion<br>[543, 564, 6]"]
|
||||
195[Wall]
|
||||
196["Cap Start"]
|
||||
197["Cap End"]
|
||||
198["SweepEdge Opposite"]
|
||||
199["SweepEdge Adjacent"]
|
||||
200["EdgeCut Fillet<br>[394, 452, 6]"]
|
||||
201["EdgeCut Fillet<br>[394, 452, 6]"]
|
||||
202["Plane<br>[193, 210, 7]"]
|
||||
218["Sweep Revolve<br>[764, 846, 7]"]
|
||||
219[Wall]
|
||||
220[Wall]
|
||||
221[Wall]
|
||||
222[Wall]
|
||||
223[Wall]
|
||||
224[Wall]
|
||||
225[Wall]
|
||||
226[Wall]
|
||||
227[Wall]
|
||||
228[Wall]
|
||||
229[Wall]
|
||||
230[Wall]
|
||||
231["SweepEdge Adjacent"]
|
||||
232["SweepEdge Adjacent"]
|
||||
233["SweepEdge Adjacent"]
|
||||
234["SweepEdge Adjacent"]
|
||||
235["SweepEdge Adjacent"]
|
||||
236["SweepEdge Adjacent"]
|
||||
237["SweepEdge Adjacent"]
|
||||
238["SweepEdge Adjacent"]
|
||||
239["SweepEdge Adjacent"]
|
||||
240["SweepEdge Adjacent"]
|
||||
241["SweepEdge Adjacent"]
|
||||
242["Plane<br>[1053, 1091, 7]"]
|
||||
250["Plane<br>[1053, 1091, 7]"]
|
||||
258["Plane<br>[1053, 1091, 7]"]
|
||||
260["SweepEdge Opposite"]
|
||||
261["SweepEdge Opposite"]
|
||||
262["SweepEdge Opposite"]
|
||||
263["SweepEdge Opposite"]
|
||||
266["Sweep Loft<br>[2389, 2509, 7]"]
|
||||
267[Wall]
|
||||
268[Wall]
|
||||
269[Wall]
|
||||
270[Wall]
|
||||
271["Cap End"]
|
||||
272["Cap End"]
|
||||
273["SweepEdge Adjacent"]
|
||||
274["SweepEdge Adjacent"]
|
||||
275["SweepEdge Adjacent"]
|
||||
276["SweepEdge Adjacent"]
|
||||
277["StartSketchOnFace<br>[1597, 1640, 5]"]
|
||||
278["StartSketchOnFace<br>[2498, 2541, 5]"]
|
||||
279["StartSketchOnFace<br>[3197, 3234, 5]"]
|
||||
280["StartSketchOnFace<br>[3421, 3458, 5]"]
|
||||
281["StartSketchOnFace<br>[4746, 4789, 5]"]
|
||||
282["StartSketchOnFace<br>[4861, 4900, 5]"]
|
||||
283["StartSketchOnPlane<br>[244, 271, 6]"]
|
||||
284["StartSketchOnPlane<br>[453, 496, 6]"]
|
||||
285["StartSketchOnPlane<br>[1039, 1092, 7]"]
|
||||
286["StartSketchOnPlane<br>[1039, 1092, 7]"]
|
||||
287["StartSketchOnPlane<br>[1039, 1092, 7]"]
|
||||
1 --- 2
|
||||
1 --- 9
|
||||
1 --- 12
|
||||
1 --- 15
|
||||
1 --- 18
|
||||
1 --- 21
|
||||
2 --- 3
|
||||
2 --- 4
|
||||
2 --- 5
|
||||
2 --- 6
|
||||
2 --- 7
|
||||
2 ---- 24
|
||||
2 --- 8
|
||||
3 --- 25
|
||||
3 --- 31
|
||||
3 --- 32
|
||||
4 --- 26
|
||||
4 --- 33
|
||||
4 --- 34
|
||||
5 --- 27
|
||||
5 --- 35
|
||||
5 --- 36
|
||||
6 --- 28
|
||||
6 --- 37
|
||||
6 --- 38
|
||||
9 --- 10
|
||||
9 --- 11
|
||||
12 --- 13
|
||||
12 --- 14
|
||||
15 --- 16
|
||||
15 --- 17
|
||||
18 --- 19
|
||||
18 --- 20
|
||||
21 --- 22
|
||||
21 --- 23
|
||||
24 --- 25
|
||||
24 --- 26
|
||||
24 --- 27
|
||||
24 --- 28
|
||||
24 --- 29
|
||||
24 --- 30
|
||||
24 --- 31
|
||||
24 --- 32
|
||||
24 --- 33
|
||||
24 --- 34
|
||||
24 --- 35
|
||||
24 --- 36
|
||||
24 --- 37
|
||||
24 --- 38
|
||||
30 --- 39
|
||||
30 --- 78
|
||||
30 --- 157
|
||||
39 --- 40
|
||||
39 --- 41
|
||||
39 --- 42
|
||||
39 --- 43
|
||||
39 --- 44
|
||||
39 --- 45
|
||||
39 --- 46
|
||||
39 --- 47
|
||||
39 --- 48
|
||||
39 ---- 50
|
||||
39 --- 49
|
||||
40 --- 51
|
||||
40 --- 59
|
||||
40 --- 60
|
||||
41 --- 52
|
||||
41 --- 61
|
||||
41 --- 62
|
||||
42 --- 53
|
||||
42 --- 63
|
||||
42 --- 64
|
||||
43 --- 54
|
||||
43 --- 65
|
||||
43 --- 66
|
||||
44 --- 55
|
||||
44 --- 67
|
||||
44 --- 68
|
||||
45 --- 56
|
||||
45 --- 69
|
||||
45 --- 70
|
||||
46 --- 57
|
||||
46 --- 71
|
||||
46 --- 72
|
||||
47 --- 58
|
||||
47 --- 73
|
||||
47 --- 74
|
||||
50 --- 51
|
||||
50 --- 52
|
||||
50 --- 53
|
||||
50 --- 54
|
||||
50 --- 55
|
||||
50 --- 56
|
||||
50 --- 57
|
||||
50 --- 58
|
||||
50 --- 59
|
||||
50 --- 60
|
||||
50 --- 61
|
||||
50 --- 62
|
||||
50 --- 63
|
||||
50 --- 64
|
||||
50 --- 65
|
||||
50 --- 66
|
||||
50 --- 67
|
||||
50 --- 68
|
||||
50 --- 69
|
||||
50 --- 70
|
||||
50 --- 71
|
||||
50 --- 72
|
||||
50 --- 73
|
||||
50 --- 74
|
||||
78 --- 79
|
||||
78 --- 80
|
||||
78 --- 81
|
||||
78 --- 82
|
||||
78 --- 83
|
||||
78 --- 84
|
||||
78 --- 85
|
||||
78 --- 86
|
||||
78 ---- 87
|
||||
79 --- 88
|
||||
79 --- 97
|
||||
79 --- 98
|
||||
80 --- 89
|
||||
80 --- 99
|
||||
80 --- 100
|
||||
81 --- 90
|
||||
81 --- 101
|
||||
81 --- 102
|
||||
82 --- 91
|
||||
82 --- 103
|
||||
82 --- 104
|
||||
83 --- 92
|
||||
83 --- 105
|
||||
83 --- 106
|
||||
84 --- 93
|
||||
84 --- 107
|
||||
84 --- 108
|
||||
85 --- 94
|
||||
85 --- 109
|
||||
85 --- 110
|
||||
86 --- 95
|
||||
86 --- 111
|
||||
86 --- 112
|
||||
87 --- 88
|
||||
87 --- 89
|
||||
87 --- 90
|
||||
87 --- 91
|
||||
87 --- 92
|
||||
87 --- 93
|
||||
87 --- 94
|
||||
87 --- 95
|
||||
87 --- 96
|
||||
87 --- 97
|
||||
87 --- 98
|
||||
87 --- 99
|
||||
87 --- 100
|
||||
87 --- 101
|
||||
87 --- 102
|
||||
87 --- 103
|
||||
87 --- 104
|
||||
87 --- 105
|
||||
87 --- 106
|
||||
87 --- 107
|
||||
87 --- 108
|
||||
87 --- 109
|
||||
87 --- 110
|
||||
87 --- 111
|
||||
87 --- 112
|
||||
96 --- 113
|
||||
96 --- 120
|
||||
96 --- 127
|
||||
96 --- 130
|
||||
96 --- 133
|
||||
96 --- 136
|
||||
96 --- 139
|
||||
113 --- 114
|
||||
113 ---- 116
|
||||
113 --- 115
|
||||
114 --- 117
|
||||
114 --- 118
|
||||
114 --- 119
|
||||
116 --- 117
|
||||
116 --- 118
|
||||
116 --- 119
|
||||
120 --- 121
|
||||
120 --- 122
|
||||
120 --- 123
|
||||
120 --- 124
|
||||
120 --- 125
|
||||
120 ---- 142
|
||||
120 --- 126
|
||||
121 --- 143
|
||||
121 --- 149
|
||||
121 --- 150
|
||||
122 --- 144
|
||||
122 --- 151
|
||||
122 --- 152
|
||||
123 --- 145
|
||||
123 --- 153
|
||||
123 --- 154
|
||||
124 --- 146
|
||||
124 --- 155
|
||||
124 --- 156
|
||||
127 --- 128
|
||||
127 --- 129
|
||||
130 --- 131
|
||||
130 --- 132
|
||||
133 --- 134
|
||||
133 --- 135
|
||||
136 --- 137
|
||||
136 --- 138
|
||||
139 --- 140
|
||||
139 --- 141
|
||||
142 --- 143
|
||||
142 --- 144
|
||||
142 --- 145
|
||||
142 --- 146
|
||||
142 --- 147
|
||||
142 --- 148
|
||||
142 --- 149
|
||||
142 --- 150
|
||||
142 --- 151
|
||||
142 --- 152
|
||||
142 --- 153
|
||||
142 --- 154
|
||||
142 --- 155
|
||||
142 --- 156
|
||||
157 --- 158
|
||||
157 ---- 160
|
||||
157 --- 159
|
||||
158 --- 161
|
||||
158 --- 163
|
||||
158 --- 164
|
||||
160 --- 161
|
||||
160 --- 162
|
||||
160 --- 163
|
||||
160 --- 164
|
||||
162 --- 165
|
||||
165 --- 166
|
||||
165 ---- 168
|
||||
165 --- 167
|
||||
166 --- 169
|
||||
166 --- 170
|
||||
166 --- 171
|
||||
168 --- 169
|
||||
168 --- 170
|
||||
168 --- 171
|
||||
32 <--x 172
|
||||
34 <--x 173
|
||||
36 <--x 174
|
||||
38 <--x 175
|
||||
150 <--x 176
|
||||
152 <--x 177
|
||||
154 <--x 178
|
||||
156 <--x 179
|
||||
180 --- 181
|
||||
181 --- 182
|
||||
181 ---- 184
|
||||
181 --- 183
|
||||
182 --- 185
|
||||
182 --- 188
|
||||
182 --- 189
|
||||
182 --- 201
|
||||
184 --- 185
|
||||
184 --- 186
|
||||
184 --- 187
|
||||
184 --- 188
|
||||
184 --- 189
|
||||
190 --- 191
|
||||
191 --- 192
|
||||
191 ---- 194
|
||||
191 --- 193
|
||||
192 --- 195
|
||||
192 --- 198
|
||||
192 --- 199
|
||||
194 --- 195
|
||||
194 --- 196
|
||||
194 --- 197
|
||||
194 --- 198
|
||||
194 --- 199
|
||||
188 <--x 200
|
||||
202 --- 203
|
||||
203 --- 204
|
||||
203 --- 205
|
||||
203 --- 206
|
||||
203 --- 207
|
||||
203 --- 208
|
||||
203 --- 209
|
||||
203 --- 210
|
||||
203 --- 211
|
||||
203 --- 212
|
||||
203 --- 213
|
||||
203 --- 214
|
||||
203 --- 215
|
||||
203 --- 216
|
||||
203 ---- 218
|
||||
203 --- 217
|
||||
204 --- 219
|
||||
204 x--> 231
|
||||
205 --- 220
|
||||
205 --- 231
|
||||
206 --- 221
|
||||
206 --- 232
|
||||
207 --- 222
|
||||
207 --- 233
|
||||
208 --- 223
|
||||
208 --- 234
|
||||
209 --- 224
|
||||
209 --- 235
|
||||
210 --- 225
|
||||
210 --- 236
|
||||
211 --- 226
|
||||
211 --- 237
|
||||
212 --- 227
|
||||
212 --- 238
|
||||
213 --- 228
|
||||
213 --- 239
|
||||
214 --- 229
|
||||
214 --- 240
|
||||
215 --- 230
|
||||
215 --- 241
|
||||
218 --- 219
|
||||
218 --- 220
|
||||
218 --- 221
|
||||
218 --- 222
|
||||
218 --- 223
|
||||
218 --- 224
|
||||
218 --- 225
|
||||
218 --- 226
|
||||
218 --- 227
|
||||
218 --- 228
|
||||
218 --- 229
|
||||
218 --- 230
|
||||
218 <--x 204
|
||||
218 --- 231
|
||||
218 <--x 205
|
||||
218 <--x 206
|
||||
218 --- 232
|
||||
218 <--x 207
|
||||
218 --- 233
|
||||
218 <--x 208
|
||||
218 --- 234
|
||||
218 <--x 209
|
||||
218 --- 235
|
||||
218 <--x 210
|
||||
218 --- 236
|
||||
218 <--x 211
|
||||
218 --- 237
|
||||
218 <--x 212
|
||||
218 --- 238
|
||||
218 <--x 213
|
||||
218 --- 239
|
||||
218 <--x 214
|
||||
218 --- 240
|
||||
218 <--x 215
|
||||
218 --- 241
|
||||
242 --- 243
|
||||
243 --- 244
|
||||
243 --- 245
|
||||
243 --- 246
|
||||
243 --- 247
|
||||
243 --- 248
|
||||
243 ---- 266
|
||||
243 --- 249
|
||||
244 --- 267
|
||||
244 --- 260
|
||||
244 --- 273
|
||||
245 --- 268
|
||||
245 --- 261
|
||||
245 --- 274
|
||||
246 --- 269
|
||||
246 --- 262
|
||||
246 --- 275
|
||||
247 --- 270
|
||||
247 --- 263
|
||||
247 --- 276
|
||||
250 --- 251
|
||||
251 --- 252
|
||||
251 --- 253
|
||||
251 --- 254
|
||||
251 --- 255
|
||||
251 --- 256
|
||||
251 x---> 266
|
||||
251 --- 257
|
||||
258 --- 259
|
||||
259 x--> 260
|
||||
259 x--> 261
|
||||
259 x--> 262
|
||||
259 x--> 263
|
||||
259 --- 264
|
||||
259 x---> 266
|
||||
259 --- 265
|
||||
266 --- 260
|
||||
266 --- 261
|
||||
266 --- 262
|
||||
266 --- 263
|
||||
266 --- 267
|
||||
266 --- 268
|
||||
266 --- 269
|
||||
266 --- 270
|
||||
266 --- 271
|
||||
266 --- 272
|
||||
266 --- 273
|
||||
266 --- 274
|
||||
266 --- 275
|
||||
266 --- 276
|
||||
30 <--x 277
|
||||
30 <--x 278
|
||||
96 <--x 279
|
||||
96 <--x 280
|
||||
30 <--x 281
|
||||
162 <--x 282
|
||||
180 <--x 283
|
||||
190 <--x 284
|
||||
242 <--x 285
|
||||
250 <--x 286
|
||||
258 <--x 287
|
||||
```
|
||||
220
rust/kcl-lib/tests/kcl_samples/axial-fan/ast.snap
Normal file
220
rust/kcl-lib/tests/kcl_samples/axial-fan/ast.snap
Normal file
@ -0,0 +1,220 @@
|
||||
---
|
||||
source: kcl-lib/src/simulation_tests.rs
|
||||
description: Result of parsing axial-fan.kcl
|
||||
---
|
||||
{
|
||||
"Ok": {
|
||||
"body": [
|
||||
{
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"path": {
|
||||
"type": "Kcl",
|
||||
"filename": "fan-housing.kcl"
|
||||
},
|
||||
"preComments": [
|
||||
"// Import all parts into assembly file"
|
||||
],
|
||||
"selector": {
|
||||
"type": "None",
|
||||
"alias": {
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"name": "fanHousing",
|
||||
"start": 0,
|
||||
"type": "Identifier"
|
||||
}
|
||||
},
|
||||
"start": 0,
|
||||
"type": "ImportStatement",
|
||||
"type": "ImportStatement"
|
||||
},
|
||||
{
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"path": {
|
||||
"type": "Kcl",
|
||||
"filename": "motor.kcl"
|
||||
},
|
||||
"selector": {
|
||||
"type": "None",
|
||||
"alias": {
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"name": "motor",
|
||||
"start": 0,
|
||||
"type": "Identifier"
|
||||
}
|
||||
},
|
||||
"start": 0,
|
||||
"type": "ImportStatement",
|
||||
"type": "ImportStatement"
|
||||
},
|
||||
{
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"path": {
|
||||
"type": "Kcl",
|
||||
"filename": "fan.kcl"
|
||||
},
|
||||
"selector": {
|
||||
"type": "None",
|
||||
"alias": {
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"name": "fan",
|
||||
"start": 0,
|
||||
"type": "Identifier"
|
||||
}
|
||||
},
|
||||
"start": 0,
|
||||
"type": "ImportStatement",
|
||||
"type": "ImportStatement"
|
||||
},
|
||||
{
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"expression": {
|
||||
"abs_path": false,
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"name": {
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"name": "fanHousing",
|
||||
"start": 0,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 0,
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
},
|
||||
"preComments": [
|
||||
"",
|
||||
"",
|
||||
"// Produce the model for each imported part"
|
||||
],
|
||||
"start": 0,
|
||||
"type": "ExpressionStatement",
|
||||
"type": "ExpressionStatement"
|
||||
},
|
||||
{
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"expression": {
|
||||
"abs_path": false,
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"name": {
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"name": "motor",
|
||||
"start": 0,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 0,
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
},
|
||||
"start": 0,
|
||||
"type": "ExpressionStatement",
|
||||
"type": "ExpressionStatement"
|
||||
},
|
||||
{
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"expression": {
|
||||
"abs_path": false,
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"name": {
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"name": "fan",
|
||||
"start": 0,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 0,
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
},
|
||||
"start": 0,
|
||||
"type": "ExpressionStatement",
|
||||
"type": "ExpressionStatement"
|
||||
}
|
||||
],
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"innerAttrs": [
|
||||
{
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"name": {
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"name": "settings",
|
||||
"start": 0,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"preComments": [
|
||||
"// PC Fan",
|
||||
"// A small axial fan, used to push or draw airflow over components to remove excess heat",
|
||||
"",
|
||||
"",
|
||||
"// Set units"
|
||||
],
|
||||
"properties": [
|
||||
{
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"key": {
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"name": "defaultLengthUnit",
|
||||
"start": 0,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"start": 0,
|
||||
"type": "ObjectProperty",
|
||||
"value": {
|
||||
"abs_path": false,
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"name": {
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"name": "mm",
|
||||
"start": 0,
|
||||
"type": "Identifier"
|
||||
},
|
||||
"path": [],
|
||||
"start": 0,
|
||||
"type": "Name",
|
||||
"type": "Name"
|
||||
}
|
||||
}
|
||||
],
|
||||
"start": 0,
|
||||
"type": "Annotation"
|
||||
}
|
||||
],
|
||||
"nonCodeMeta": {
|
||||
"nonCodeNodes": {},
|
||||
"startNodes": [
|
||||
{
|
||||
"commentStart": 0,
|
||||
"end": 0,
|
||||
"start": 0,
|
||||
"type": "NonCodeNode",
|
||||
"value": {
|
||||
"type": "newLine"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"start": 0
|
||||
}
|
||||
}
|
||||
2098
rust/kcl-lib/tests/kcl_samples/axial-fan/ops.snap
Normal file
2098
rust/kcl-lib/tests/kcl_samples/axial-fan/ops.snap
Normal file
File diff suppressed because it is too large
Load Diff
18
rust/kcl-lib/tests/kcl_samples/axial-fan/program_memory.snap
Normal file
18
rust/kcl-lib/tests/kcl_samples/axial-fan/program_memory.snap
Normal file
@ -0,0 +1,18 @@
|
||||
---
|
||||
source: kcl-lib/src/simulation_tests.rs
|
||||
description: Variables in memory after executing axial-fan.kcl
|
||||
---
|
||||
{
|
||||
"fan": {
|
||||
"type": "Module",
|
||||
"value": 7
|
||||
},
|
||||
"fanHousing": {
|
||||
"type": "Module",
|
||||
"value": 5
|
||||
},
|
||||
"motor": {
|
||||
"type": "Module",
|
||||
"value": 6
|
||||
}
|
||||
}
|
||||
BIN
rust/kcl-lib/tests/kcl_samples/axial-fan/rendered_model.png
Normal file
BIN
rust/kcl-lib/tests/kcl_samples/axial-fan/rendered_model.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 105 KiB |
544
rust/kcl-lib/tests/kcl_samples/bottle/artifact_commands.snap
Normal file
544
rust/kcl-lib/tests/kcl_samples/bottle/artifact_commands.snap
Normal file
@ -0,0 +1,544 @@
|
||||
---
|
||||
source: kcl-lib/src/simulation_tests.rs
|
||||
description: Artifact commands bottle.kcl
|
||||
---
|
||||
[
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "edge_lines_visible",
|
||||
"hidden": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "object_visible",
|
||||
"object_id": "[uuid]",
|
||||
"hidden": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "object_visible",
|
||||
"object_id": "[uuid]",
|
||||
"hidden": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "set_scene_units",
|
||||
"unit": "mm"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "make_plane",
|
||||
"origin": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"x_axis": {
|
||||
"x": 1.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"y_axis": {
|
||||
"x": 0.0,
|
||||
"y": 1.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"size": 60.0,
|
||||
"clobber": false,
|
||||
"hide": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "enable_sketch_mode",
|
||||
"entity_id": "[uuid]",
|
||||
"ortho": false,
|
||||
"animated": false,
|
||||
"adjust_camera": false,
|
||||
"planar_normal": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 1.0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "start_path"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "move_path_pen",
|
||||
"path": "[uuid]",
|
||||
"to": {
|
||||
"x": -62.5,
|
||||
"y": 0.0,
|
||||
"z": 0.0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "sketch_mode_disable"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "extend_path",
|
||||
"path": "[uuid]",
|
||||
"segment": {
|
||||
"type": "line",
|
||||
"end": {
|
||||
"x": 0.0,
|
||||
"y": 26.6667,
|
||||
"z": 0.0
|
||||
},
|
||||
"relative": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "extend_path",
|
||||
"path": "[uuid]",
|
||||
"segment": {
|
||||
"type": "arc_to",
|
||||
"interior": {
|
||||
"x": 0.0,
|
||||
"y": 40.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"end": {
|
||||
"x": 62.5,
|
||||
"y": 26.6667,
|
||||
"z": 0.0
|
||||
},
|
||||
"relative": false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "extend_path",
|
||||
"path": "[uuid]",
|
||||
"segment": {
|
||||
"type": "line",
|
||||
"end": {
|
||||
"x": 62.5,
|
||||
"y": 0.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"relative": false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "entity_mirror",
|
||||
"ids": [
|
||||
"[uuid]"
|
||||
],
|
||||
"axis": {
|
||||
"x": 1.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0
|
||||
},
|
||||
"point": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "entity_get_all_child_uuids",
|
||||
"entity_id": "[uuid]"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "close_path",
|
||||
"path_id": "[uuid]"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "enable_sketch_mode",
|
||||
"entity_id": "[uuid]",
|
||||
"ortho": false,
|
||||
"animated": false,
|
||||
"adjust_camera": false,
|
||||
"planar_normal": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 1.0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 202.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "sketch_mode_disable"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "object_bring_to_front",
|
||||
"object_id": "[uuid]"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "solid3d_get_extrusion_face_info",
|
||||
"object_id": "[uuid]",
|
||||
"edge_id": "[uuid]"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "solid3d_get_opposite_edge",
|
||||
"object_id": "[uuid]",
|
||||
"edge_id": "[uuid]",
|
||||
"face_id": "[uuid]"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "solid3d_get_next_adjacent_edge",
|
||||
"object_id": "[uuid]",
|
||||
"edge_id": "[uuid]",
|
||||
"face_id": "[uuid]"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "solid3d_get_opposite_edge",
|
||||
"object_id": "[uuid]",
|
||||
"edge_id": "[uuid]",
|
||||
"face_id": "[uuid]"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "solid3d_get_next_adjacent_edge",
|
||||
"object_id": "[uuid]",
|
||||
"edge_id": "[uuid]",
|
||||
"face_id": "[uuid]"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "solid3d_get_opposite_edge",
|
||||
"object_id": "[uuid]",
|
||||
"edge_id": "[uuid]",
|
||||
"face_id": "[uuid]"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "solid3d_get_next_adjacent_edge",
|
||||
"object_id": "[uuid]",
|
||||
"edge_id": "[uuid]",
|
||||
"face_id": "[uuid]"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "solid3d_get_opposite_edge",
|
||||
"object_id": "[uuid]",
|
||||
"edge_id": "[uuid]",
|
||||
"face_id": "[uuid]"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "solid3d_get_next_adjacent_edge",
|
||||
"object_id": "[uuid]",
|
||||
"edge_id": "[uuid]",
|
||||
"face_id": "[uuid]"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "solid3d_get_opposite_edge",
|
||||
"object_id": "[uuid]",
|
||||
"edge_id": "[uuid]",
|
||||
"face_id": "[uuid]"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "solid3d_get_next_adjacent_edge",
|
||||
"object_id": "[uuid]",
|
||||
"edge_id": "[uuid]",
|
||||
"face_id": "[uuid]"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "enable_sketch_mode",
|
||||
"entity_id": "[uuid]",
|
||||
"ortho": false,
|
||||
"animated": false,
|
||||
"adjust_camera": false,
|
||||
"planar_normal": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "start_path"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "move_path_pen",
|
||||
"path": "[uuid]",
|
||||
"to": {
|
||||
"x": 22.5,
|
||||
"y": 0.0,
|
||||
"z": 0.0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "sketch_mode_disable"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "extend_path",
|
||||
"path": "[uuid]",
|
||||
"segment": {
|
||||
"type": "arc",
|
||||
"center": {
|
||||
"x": 0.0,
|
||||
"y": 0.0
|
||||
},
|
||||
"radius": 22.5,
|
||||
"start": {
|
||||
"unit": "degrees",
|
||||
"value": 0.0
|
||||
},
|
||||
"end": {
|
||||
"unit": "degrees",
|
||||
"value": 360.0
|
||||
},
|
||||
"relative": false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "close_path",
|
||||
"path_id": "[uuid]"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "enable_sketch_mode",
|
||||
"entity_id": "[uuid]",
|
||||
"ortho": false,
|
||||
"animated": false,
|
||||
"adjust_camera": false,
|
||||
"planar_normal": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "extrude",
|
||||
"target": "[uuid]",
|
||||
"distance": 18.0,
|
||||
"faces": null,
|
||||
"opposite": "None"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "sketch_mode_disable"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "object_bring_to_front",
|
||||
"object_id": "[uuid]"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "solid3d_get_extrusion_face_info",
|
||||
"object_id": "[uuid]",
|
||||
"edge_id": "[uuid]"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "solid3d_get_opposite_edge",
|
||||
"object_id": "[uuid]",
|
||||
"edge_id": "[uuid]",
|
||||
"face_id": "[uuid]"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "solid3d_get_next_adjacent_edge",
|
||||
"object_id": "[uuid]",
|
||||
"edge_id": "[uuid]",
|
||||
"face_id": "[uuid]"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "solid3d_shell_face",
|
||||
"object_id": "[uuid]",
|
||||
"face_ids": [
|
||||
"[uuid]"
|
||||
],
|
||||
"shell_thickness": 4.0,
|
||||
"hollow": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "object_set_material_params_pbr",
|
||||
"object_id": "[uuid]",
|
||||
"color": {
|
||||
"r": 0.0,
|
||||
"g": 0.47058824,
|
||||
"b": 0.7607843,
|
||||
"a": 100.0
|
||||
},
|
||||
"metalness": 0.0,
|
||||
"roughness": 0.0,
|
||||
"ambient_occlusion": 0.0
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "set_scene_units",
|
||||
"unit": "mm"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "set_scene_units",
|
||||
"unit": "mm"
|
||||
}
|
||||
},
|
||||
{
|
||||
"cmdId": "[uuid]",
|
||||
"range": [],
|
||||
"command": {
|
||||
"type": "set_scene_units",
|
||||
"unit": "mm"
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -0,0 +1,6 @@
|
||||
---
|
||||
source: kcl-lib/src/simulation_tests.rs
|
||||
description: Artifact graph flowchart bottle.kcl
|
||||
extension: md
|
||||
snapshot_kind: binary
|
||||
---
|
||||
@ -0,0 +1,44 @@
|
||||
```mermaid
|
||||
flowchart LR
|
||||
subgraph path2 [Path]
|
||||
2["Path<br>[337, 378, 0]"]
|
||||
3["Segment<br>[384, 415, 0]"]
|
||||
4["Segment<br>[421, 528, 0]"]
|
||||
5["Segment<br>[534, 556, 0]"]
|
||||
6["Segment<br>[586, 593, 0]"]
|
||||
7[Solid2d]
|
||||
end
|
||||
subgraph path10 [Path]
|
||||
10["Path<br>[750, 800, 0]"]
|
||||
11["Segment<br>[750, 800, 0]"]
|
||||
12[Solid2d]
|
||||
end
|
||||
1["Plane<br>[314, 331, 0]"]
|
||||
8["Sweep Extrusion<br>[599, 641, 0]"]
|
||||
9["Plane<br>[750, 800, 0]"]
|
||||
13["Sweep Extrusion<br>[806, 833, 0]"]
|
||||
14[Wall]
|
||||
15["Cap End"]
|
||||
16["SweepEdge Opposite"]
|
||||
17["SweepEdge Adjacent"]
|
||||
18["StartSketchOnFace<br>[707, 744, 0]"]
|
||||
1 --- 2
|
||||
2 --- 3
|
||||
2 --- 4
|
||||
2 --- 5
|
||||
2 --- 6
|
||||
2 ---- 8
|
||||
2 --- 7
|
||||
9 --- 10
|
||||
10 --- 11
|
||||
10 ---- 13
|
||||
10 --- 12
|
||||
11 --- 14
|
||||
11 --- 16
|
||||
11 --- 17
|
||||
13 --- 14
|
||||
13 --- 15
|
||||
13 --- 16
|
||||
13 --- 17
|
||||
9 <--x 18
|
||||
```
|
||||
1401
rust/kcl-lib/tests/kcl_samples/bottle/ast.snap
Normal file
1401
rust/kcl-lib/tests/kcl_samples/bottle/ast.snap
Normal file
File diff suppressed because it is too large
Load Diff
152
rust/kcl-lib/tests/kcl_samples/bottle/ops.snap
Normal file
152
rust/kcl-lib/tests/kcl_samples/bottle/ops.snap
Normal file
@ -0,0 +1,152 @@
|
||||
---
|
||||
source: kcl-lib/src/simulation_tests.rs
|
||||
description: Operations executed bottle.kcl
|
||||
---
|
||||
[
|
||||
{
|
||||
"labeledArgs": {
|
||||
"planeOrSolid": {
|
||||
"value": {
|
||||
"type": "Plane",
|
||||
"artifact_id": "[uuid]"
|
||||
},
|
||||
"sourceRange": []
|
||||
}
|
||||
},
|
||||
"name": "startSketchOn",
|
||||
"sourceRange": [],
|
||||
"type": "StdLibCall",
|
||||
"unlabeledArg": null
|
||||
},
|
||||
{
|
||||
"labeledArgs": {
|
||||
"length": {
|
||||
"value": {
|
||||
"type": "Number",
|
||||
"value": 202.0,
|
||||
"ty": {
|
||||
"type": "Default",
|
||||
"len": {
|
||||
"type": "Mm"
|
||||
},
|
||||
"angle": {
|
||||
"type": "Degrees"
|
||||
}
|
||||
}
|
||||
},
|
||||
"sourceRange": []
|
||||
}
|
||||
},
|
||||
"name": "extrude",
|
||||
"sourceRange": [],
|
||||
"type": "StdLibCall",
|
||||
"unlabeledArg": {
|
||||
"value": {
|
||||
"type": "Sketch",
|
||||
"value": {
|
||||
"artifactId": "[uuid]"
|
||||
}
|
||||
},
|
||||
"sourceRange": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"labeledArgs": {
|
||||
"face": {
|
||||
"value": {
|
||||
"type": "String",
|
||||
"value": "end"
|
||||
},
|
||||
"sourceRange": []
|
||||
}
|
||||
},
|
||||
"name": "startSketchOn",
|
||||
"sourceRange": [],
|
||||
"type": "StdLibCall",
|
||||
"unlabeledArg": {
|
||||
"value": {
|
||||
"type": "Solid",
|
||||
"value": {
|
||||
"artifactId": "[uuid]"
|
||||
}
|
||||
},
|
||||
"sourceRange": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"labeledArgs": {
|
||||
"length": {
|
||||
"value": {
|
||||
"type": "Number",
|
||||
"value": 18.0,
|
||||
"ty": {
|
||||
"type": "Default",
|
||||
"len": {
|
||||
"type": "Mm"
|
||||
},
|
||||
"angle": {
|
||||
"type": "Degrees"
|
||||
}
|
||||
}
|
||||
},
|
||||
"sourceRange": []
|
||||
}
|
||||
},
|
||||
"name": "extrude",
|
||||
"sourceRange": [],
|
||||
"type": "StdLibCall",
|
||||
"unlabeledArg": {
|
||||
"value": {
|
||||
"type": "Sketch",
|
||||
"value": {
|
||||
"artifactId": "[uuid]"
|
||||
}
|
||||
},
|
||||
"sourceRange": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"labeledArgs": {
|
||||
"faces": {
|
||||
"value": {
|
||||
"type": "Array",
|
||||
"value": [
|
||||
{
|
||||
"type": "String",
|
||||
"value": "end"
|
||||
}
|
||||
]
|
||||
},
|
||||
"sourceRange": []
|
||||
},
|
||||
"thickness": {
|
||||
"value": {
|
||||
"type": "Number",
|
||||
"value": 4.0,
|
||||
"ty": {
|
||||
"type": "Default",
|
||||
"len": {
|
||||
"type": "Mm"
|
||||
},
|
||||
"angle": {
|
||||
"type": "Degrees"
|
||||
}
|
||||
}
|
||||
},
|
||||
"sourceRange": []
|
||||
}
|
||||
},
|
||||
"name": "shell",
|
||||
"sourceRange": [],
|
||||
"type": "StdLibCall",
|
||||
"unlabeledArg": {
|
||||
"value": {
|
||||
"type": "Solid",
|
||||
"value": {
|
||||
"artifactId": "[uuid]"
|
||||
}
|
||||
},
|
||||
"sourceRange": []
|
||||
}
|
||||
}
|
||||
]
|
||||
817
rust/kcl-lib/tests/kcl_samples/bottle/program_memory.snap
Normal file
817
rust/kcl-lib/tests/kcl_samples/bottle/program_memory.snap
Normal file
@ -0,0 +1,817 @@
|
||||
---
|
||||
source: kcl-lib/src/simulation_tests.rs
|
||||
description: Variables in memory after executing bottle.kcl
|
||||
---
|
||||
{
|
||||
"bottleBody": {
|
||||
"type": "Solid",
|
||||
"value": {
|
||||
"type": "Solid",
|
||||
"id": "[uuid]",
|
||||
"artifactId": "[uuid]",
|
||||
"value": [],
|
||||
"sketch": {
|
||||
"type": "Sketch",
|
||||
"id": "[uuid]",
|
||||
"paths": [
|
||||
{
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": []
|
||||
},
|
||||
"from": [
|
||||
-62.5,
|
||||
0.0
|
||||
],
|
||||
"tag": null,
|
||||
"to": [
|
||||
-62.5,
|
||||
26.6667
|
||||
],
|
||||
"type": "ToPoint",
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
{
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": []
|
||||
},
|
||||
"from": [
|
||||
-62.5,
|
||||
26.6667
|
||||
],
|
||||
"p1": [
|
||||
-62.5,
|
||||
26.666666666666668
|
||||
],
|
||||
"p2": [
|
||||
0.0,
|
||||
40.0
|
||||
],
|
||||
"p3": [
|
||||
62.5,
|
||||
26.666666666666668
|
||||
],
|
||||
"tag": null,
|
||||
"to": [
|
||||
62.5,
|
||||
26.6667
|
||||
],
|
||||
"type": "ArcThreePoint",
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
{
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": []
|
||||
},
|
||||
"from": [
|
||||
62.5,
|
||||
26.6667
|
||||
],
|
||||
"tag": null,
|
||||
"to": [
|
||||
62.5,
|
||||
0.0
|
||||
],
|
||||
"type": "ToPoint",
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
{
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": []
|
||||
},
|
||||
"from": [
|
||||
62.5,
|
||||
0.0
|
||||
],
|
||||
"tag": null,
|
||||
"to": [
|
||||
-62.5,
|
||||
0.0
|
||||
],
|
||||
"type": "ToPoint",
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
}
|
||||
],
|
||||
"on": {
|
||||
"type": "plane",
|
||||
"id": "[uuid]",
|
||||
"artifactId": "[uuid]",
|
||||
"value": "XY",
|
||||
"origin": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0,
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
"xAxis": {
|
||||
"x": 1.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0,
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
"yAxis": {
|
||||
"x": 0.0,
|
||||
"y": 1.0,
|
||||
"z": 0.0,
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
"zAxis": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 1.0,
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
"start": {
|
||||
"from": [
|
||||
-62.5,
|
||||
0.0
|
||||
],
|
||||
"to": [
|
||||
-62.5,
|
||||
0.0
|
||||
],
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
},
|
||||
"tag": null,
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": []
|
||||
}
|
||||
},
|
||||
"artifactId": "[uuid]",
|
||||
"originalId": "[uuid]",
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
"height": 202.0,
|
||||
"startCapId": "[uuid]",
|
||||
"endCapId": "[uuid]",
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
}
|
||||
},
|
||||
"bottleHeight": {
|
||||
"type": "Number",
|
||||
"value": 220.0,
|
||||
"ty": {
|
||||
"type": "Default",
|
||||
"len": {
|
||||
"type": "Mm"
|
||||
},
|
||||
"angle": {
|
||||
"type": "Degrees"
|
||||
}
|
||||
}
|
||||
},
|
||||
"bottleLength": {
|
||||
"type": "Number",
|
||||
"value": 125.0,
|
||||
"ty": {
|
||||
"type": "Default",
|
||||
"len": {
|
||||
"type": "Mm"
|
||||
},
|
||||
"angle": {
|
||||
"type": "Degrees"
|
||||
}
|
||||
}
|
||||
},
|
||||
"bottleNeck": {
|
||||
"type": "Solid",
|
||||
"value": {
|
||||
"type": "Solid",
|
||||
"id": "[uuid]",
|
||||
"artifactId": "[uuid]",
|
||||
"value": [
|
||||
{
|
||||
"faceId": "[uuid]",
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [],
|
||||
"tag": null,
|
||||
"type": "extrudeArc"
|
||||
}
|
||||
],
|
||||
"sketch": {
|
||||
"type": "Sketch",
|
||||
"id": "[uuid]",
|
||||
"paths": [
|
||||
{
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": []
|
||||
},
|
||||
"ccw": true,
|
||||
"center": [
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"from": [
|
||||
22.5,
|
||||
0.0
|
||||
],
|
||||
"radius": 22.5,
|
||||
"tag": null,
|
||||
"to": [
|
||||
22.5,
|
||||
0.0
|
||||
],
|
||||
"type": "Circle",
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
}
|
||||
],
|
||||
"on": {
|
||||
"type": "face",
|
||||
"id": "[uuid]",
|
||||
"artifactId": "[uuid]",
|
||||
"value": "end",
|
||||
"xAxis": {
|
||||
"x": 1.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0,
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
"yAxis": {
|
||||
"x": 0.0,
|
||||
"y": 1.0,
|
||||
"z": 0.0,
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
"zAxis": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 1.0,
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
"solid": {
|
||||
"type": "Solid",
|
||||
"id": "[uuid]",
|
||||
"artifactId": "[uuid]",
|
||||
"value": [],
|
||||
"sketch": {
|
||||
"type": "Sketch",
|
||||
"id": "[uuid]",
|
||||
"paths": [
|
||||
{
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": []
|
||||
},
|
||||
"from": [
|
||||
-62.5,
|
||||
0.0
|
||||
],
|
||||
"tag": null,
|
||||
"to": [
|
||||
-62.5,
|
||||
26.6667
|
||||
],
|
||||
"type": "ToPoint",
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
{
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": []
|
||||
},
|
||||
"from": [
|
||||
-62.5,
|
||||
26.6667
|
||||
],
|
||||
"p1": [
|
||||
-62.5,
|
||||
26.666666666666668
|
||||
],
|
||||
"p2": [
|
||||
0.0,
|
||||
40.0
|
||||
],
|
||||
"p3": [
|
||||
62.5,
|
||||
26.666666666666668
|
||||
],
|
||||
"tag": null,
|
||||
"to": [
|
||||
62.5,
|
||||
26.6667
|
||||
],
|
||||
"type": "ArcThreePoint",
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
{
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": []
|
||||
},
|
||||
"from": [
|
||||
62.5,
|
||||
26.6667
|
||||
],
|
||||
"tag": null,
|
||||
"to": [
|
||||
62.5,
|
||||
0.0
|
||||
],
|
||||
"type": "ToPoint",
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
{
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": []
|
||||
},
|
||||
"from": [
|
||||
62.5,
|
||||
0.0
|
||||
],
|
||||
"tag": null,
|
||||
"to": [
|
||||
-62.5,
|
||||
0.0
|
||||
],
|
||||
"type": "ToPoint",
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
}
|
||||
],
|
||||
"on": {
|
||||
"type": "plane",
|
||||
"id": "[uuid]",
|
||||
"artifactId": "[uuid]",
|
||||
"value": "XY",
|
||||
"origin": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0,
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
"xAxis": {
|
||||
"x": 1.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0,
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
"yAxis": {
|
||||
"x": 0.0,
|
||||
"y": 1.0,
|
||||
"z": 0.0,
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
"zAxis": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 1.0,
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
"start": {
|
||||
"from": [
|
||||
-62.5,
|
||||
0.0
|
||||
],
|
||||
"to": [
|
||||
-62.5,
|
||||
0.0
|
||||
],
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
},
|
||||
"tag": null,
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": []
|
||||
}
|
||||
},
|
||||
"artifactId": "[uuid]",
|
||||
"originalId": "[uuid]",
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
"height": 202.0,
|
||||
"startCapId": "[uuid]",
|
||||
"endCapId": "[uuid]",
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
"start": {
|
||||
"from": [
|
||||
22.5,
|
||||
0.0
|
||||
],
|
||||
"to": [
|
||||
22.5,
|
||||
0.0
|
||||
],
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
},
|
||||
"tag": null,
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": []
|
||||
}
|
||||
},
|
||||
"artifactId": "[uuid]",
|
||||
"originalId": "[uuid]",
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
"height": 18.0,
|
||||
"startCapId": null,
|
||||
"endCapId": "[uuid]",
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
}
|
||||
},
|
||||
"bottleShell": {
|
||||
"type": "Solid",
|
||||
"value": {
|
||||
"type": "Solid",
|
||||
"id": "[uuid]",
|
||||
"artifactId": "[uuid]",
|
||||
"value": [
|
||||
{
|
||||
"faceId": "[uuid]",
|
||||
"id": "[uuid]",
|
||||
"sourceRange": [],
|
||||
"tag": null,
|
||||
"type": "extrudeArc"
|
||||
}
|
||||
],
|
||||
"sketch": {
|
||||
"type": "Sketch",
|
||||
"id": "[uuid]",
|
||||
"paths": [
|
||||
{
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": []
|
||||
},
|
||||
"ccw": true,
|
||||
"center": [
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"from": [
|
||||
22.5,
|
||||
0.0
|
||||
],
|
||||
"radius": 22.5,
|
||||
"tag": null,
|
||||
"to": [
|
||||
22.5,
|
||||
0.0
|
||||
],
|
||||
"type": "Circle",
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
}
|
||||
],
|
||||
"on": {
|
||||
"type": "face",
|
||||
"id": "[uuid]",
|
||||
"artifactId": "[uuid]",
|
||||
"value": "end",
|
||||
"xAxis": {
|
||||
"x": 1.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0,
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
"yAxis": {
|
||||
"x": 0.0,
|
||||
"y": 1.0,
|
||||
"z": 0.0,
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
"zAxis": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 1.0,
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
"solid": {
|
||||
"type": "Solid",
|
||||
"id": "[uuid]",
|
||||
"artifactId": "[uuid]",
|
||||
"value": [],
|
||||
"sketch": {
|
||||
"type": "Sketch",
|
||||
"id": "[uuid]",
|
||||
"paths": [
|
||||
{
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": []
|
||||
},
|
||||
"from": [
|
||||
-62.5,
|
||||
0.0
|
||||
],
|
||||
"tag": null,
|
||||
"to": [
|
||||
-62.5,
|
||||
26.6667
|
||||
],
|
||||
"type": "ToPoint",
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
{
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": []
|
||||
},
|
||||
"from": [
|
||||
-62.5,
|
||||
26.6667
|
||||
],
|
||||
"p1": [
|
||||
-62.5,
|
||||
26.666666666666668
|
||||
],
|
||||
"p2": [
|
||||
0.0,
|
||||
40.0
|
||||
],
|
||||
"p3": [
|
||||
62.5,
|
||||
26.666666666666668
|
||||
],
|
||||
"tag": null,
|
||||
"to": [
|
||||
62.5,
|
||||
26.6667
|
||||
],
|
||||
"type": "ArcThreePoint",
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
{
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": []
|
||||
},
|
||||
"from": [
|
||||
62.5,
|
||||
26.6667
|
||||
],
|
||||
"tag": null,
|
||||
"to": [
|
||||
62.5,
|
||||
0.0
|
||||
],
|
||||
"type": "ToPoint",
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
{
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": []
|
||||
},
|
||||
"from": [
|
||||
62.5,
|
||||
0.0
|
||||
],
|
||||
"tag": null,
|
||||
"to": [
|
||||
-62.5,
|
||||
0.0
|
||||
],
|
||||
"type": "ToPoint",
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
}
|
||||
],
|
||||
"on": {
|
||||
"type": "plane",
|
||||
"id": "[uuid]",
|
||||
"artifactId": "[uuid]",
|
||||
"value": "XY",
|
||||
"origin": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0,
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
"xAxis": {
|
||||
"x": 1.0,
|
||||
"y": 0.0,
|
||||
"z": 0.0,
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
"yAxis": {
|
||||
"x": 0.0,
|
||||
"y": 1.0,
|
||||
"z": 0.0,
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
"zAxis": {
|
||||
"x": 0.0,
|
||||
"y": 0.0,
|
||||
"z": 1.0,
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
"start": {
|
||||
"from": [
|
||||
-62.5,
|
||||
0.0
|
||||
],
|
||||
"to": [
|
||||
-62.5,
|
||||
0.0
|
||||
],
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
},
|
||||
"tag": null,
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": []
|
||||
}
|
||||
},
|
||||
"artifactId": "[uuid]",
|
||||
"originalId": "[uuid]",
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
"height": 202.0,
|
||||
"startCapId": "[uuid]",
|
||||
"endCapId": "[uuid]",
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
"start": {
|
||||
"from": [
|
||||
22.5,
|
||||
0.0
|
||||
],
|
||||
"to": [
|
||||
22.5,
|
||||
0.0
|
||||
],
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
},
|
||||
"tag": null,
|
||||
"__geoMeta": {
|
||||
"id": "[uuid]",
|
||||
"sourceRange": []
|
||||
}
|
||||
},
|
||||
"artifactId": "[uuid]",
|
||||
"originalId": "[uuid]",
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
},
|
||||
"height": 18.0,
|
||||
"startCapId": null,
|
||||
"endCapId": "[uuid]",
|
||||
"units": {
|
||||
"type": "Mm"
|
||||
}
|
||||
}
|
||||
},
|
||||
"bottleWidth": {
|
||||
"type": "Number",
|
||||
"value": 80.0,
|
||||
"ty": {
|
||||
"type": "Default",
|
||||
"len": {
|
||||
"type": "Mm"
|
||||
},
|
||||
"angle": {
|
||||
"type": "Degrees"
|
||||
}
|
||||
}
|
||||
},
|
||||
"neckDepth": {
|
||||
"type": "Number",
|
||||
"value": 18.0,
|
||||
"ty": {
|
||||
"type": "Default",
|
||||
"len": {
|
||||
"type": "Mm"
|
||||
},
|
||||
"angle": {
|
||||
"type": "Degrees"
|
||||
}
|
||||
}
|
||||
},
|
||||
"neckDiameter": {
|
||||
"type": "Number",
|
||||
"value": 45.0,
|
||||
"ty": {
|
||||
"type": "Default",
|
||||
"len": {
|
||||
"type": "Mm"
|
||||
},
|
||||
"angle": {
|
||||
"type": "Degrees"
|
||||
}
|
||||
}
|
||||
},
|
||||
"wallThickness": {
|
||||
"type": "Number",
|
||||
"value": 4.0,
|
||||
"ty": {
|
||||
"type": "Default",
|
||||
"len": {
|
||||
"type": "Mm"
|
||||
},
|
||||
"angle": {
|
||||
"type": "Degrees"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
rust/kcl-lib/tests/kcl_samples/bottle/rendered_model.png
Normal file
BIN
rust/kcl-lib/tests/kcl_samples/bottle/rendered_model.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 70 KiB |
BIN
rust/kcl-lib/tests/outputs/serial_test_example_appearance9.png
Normal file
BIN
rust/kcl-lib/tests/outputs/serial_test_example_appearance9.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 74 KiB |
@ -23,6 +23,7 @@ pub struct EngineConnection {
|
||||
batch: Arc<RwLock<Vec<(WebSocketRequest, kcl_lib::SourceRange)>>>,
|
||||
batch_end: Arc<RwLock<IndexMap<uuid::Uuid, (WebSocketRequest, kcl_lib::SourceRange)>>>,
|
||||
core_test: Arc<RwLock<String>>,
|
||||
ids_of_async_commands: Arc<RwLock<IndexMap<Uuid, kcl_lib::SourceRange>>>,
|
||||
/// The default planes for the scene.
|
||||
default_planes: Arc<RwLock<Option<DefaultPlanes>>>,
|
||||
stats: EngineStats,
|
||||
@ -37,6 +38,7 @@ impl EngineConnection {
|
||||
batch_end: Arc::new(RwLock::new(IndexMap::new())),
|
||||
core_test: result,
|
||||
default_planes: Default::default(),
|
||||
ids_of_async_commands: Arc::new(RwLock::new(IndexMap::new())),
|
||||
stats: Default::default(),
|
||||
})
|
||||
}
|
||||
@ -379,6 +381,10 @@ impl kcl_lib::EngineManager for EngineConnection {
|
||||
Arc::new(RwLock::new(Vec::new()))
|
||||
}
|
||||
|
||||
fn ids_of_async_commands(&self) -> Arc<RwLock<IndexMap<Uuid, kcl_lib::SourceRange>>> {
|
||||
self.ids_of_async_commands.clone()
|
||||
}
|
||||
|
||||
fn get_default_planes(&self) -> Arc<RwLock<Option<DefaultPlanes>>> {
|
||||
self.default_planes.clone()
|
||||
}
|
||||
@ -391,6 +397,25 @@ impl kcl_lib::EngineManager for EngineConnection {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn inner_fire_modeling_cmd(
|
||||
&self,
|
||||
id: uuid::Uuid,
|
||||
source_range: kcl_lib::SourceRange,
|
||||
cmd: WebSocketRequest,
|
||||
id_to_source_range: HashMap<Uuid, kcl_lib::SourceRange>,
|
||||
) -> Result<(), KclError> {
|
||||
// Pop off the id we care about.
|
||||
self.ids_of_async_commands.write().await.swap_remove(&id);
|
||||
|
||||
// Add the response to our responses.
|
||||
let response = self
|
||||
.inner_send_modeling_cmd(id, source_range, cmd, id_to_source_range)
|
||||
.await?;
|
||||
self.responses().write().await.insert(id, response);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn inner_send_modeling_cmd(
|
||||
&self,
|
||||
id: uuid::Uuid,
|
||||
|
||||
@ -9,6 +9,7 @@ use wasm_bindgen::prelude::*;
|
||||
#[wasm_bindgen]
|
||||
pub struct Context {
|
||||
engine: Arc<Box<dyn EngineManager>>,
|
||||
response_context: Arc<kcl_lib::wasm_engine::ResponseContext>,
|
||||
fs: Arc<FileManager>,
|
||||
mock_engine: Arc<Box<dyn EngineManager>>,
|
||||
}
|
||||
@ -22,9 +23,10 @@ impl Context {
|
||||
) -> Result<Self, JsValue> {
|
||||
console_error_panic_hook::set_once();
|
||||
|
||||
let response_context = Arc::new(kcl_lib::wasm_engine::ResponseContext::new());
|
||||
Ok(Self {
|
||||
engine: Arc::new(Box::new(
|
||||
kcl_lib::wasm_engine::EngineConnection::new(engine_manager)
|
||||
kcl_lib::wasm_engine::EngineConnection::new(engine_manager, response_context.clone())
|
||||
.await
|
||||
.map_err(|e| format!("{:?}", e))?,
|
||||
)),
|
||||
@ -34,6 +36,7 @@ impl Context {
|
||||
.await
|
||||
.map_err(|e| format!("{:?}", e))?,
|
||||
)),
|
||||
response_context,
|
||||
})
|
||||
}
|
||||
|
||||
@ -100,6 +103,12 @@ impl Context {
|
||||
}
|
||||
}
|
||||
|
||||
/// Send a response to kcl lib's engine.
|
||||
#[wasm_bindgen(js_name = sendResponse)]
|
||||
pub async fn send_response(&self, data: js_sys::Uint8Array) -> Result<(), JsValue> {
|
||||
self.response_context.send_response(data).await
|
||||
}
|
||||
|
||||
/// Execute a program in mock mode.
|
||||
#[wasm_bindgen(js_name = executeMock)]
|
||||
pub async fn execute_mock(
|
||||
|
||||
@ -127,7 +127,7 @@ export const CreateNewVariable = ({
|
||||
autoFocus={true}
|
||||
autoCapitalize="off"
|
||||
autoCorrect="off"
|
||||
className={`font-mono flex-1 sm:text-sm px-2 py-1 rounded-sm bg-chalkboard-10 dark:bg-chalkboard-90 text-chalkboard-90 dark:text-chalkboard-10 ${
|
||||
className={`flex-1 sm:text-sm px-2 py-1 rounded-sm bg-chalkboard-10 dark:bg-chalkboard-90 text-chalkboard-90 dark:text-chalkboard-10 ${
|
||||
!shouldCreateVariable ? 'opacity-50' : ''
|
||||
}`}
|
||||
value={newVariableName}
|
||||
|
||||
@ -628,8 +628,8 @@ const CustomIconMap = {
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M4 3H4.5H11H11.2071L11.3536 3.14645L15.8536 7.64646L16 7.7929V8.00001V11.3773C15.6992 11.1362 15.3628 10.9376 15 10.7908V8.50001H11H10.5V8.00001V4H5V16H9.79076C9.93763 16.3628 10.1362 16.6992 10.3773 17H4.5H4V16.5V3.5V3ZM11.5 4.70711L14.2929 7.50001H11.5V4.70711ZM13.8123 17.3904L16.3123 15.3904L15.6877 14.6096L14 15.9597V12H13V15.9597L11.3123 14.6096L10.6877 15.3904L13.1877 17.3904L13.5 17.6403L13.8123 17.3904Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
.header {
|
||||
@apply z-10 relative rounded-tr;
|
||||
@apply flex h-[41px] items-center justify-between gap-2 px-2;
|
||||
@apply font-mono text-xs font-bold select-none text-chalkboard-90;
|
||||
@apply text-xs select-none text-chalkboard-90;
|
||||
@apply bg-chalkboard-10 border-b border-chalkboard-30;
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
.button {
|
||||
@apply flex justify-between items-center gap-2 px-2 py-1 text-left border-none rounded-sm;
|
||||
@apply font-mono !no-underline text-xs font-bold select-none text-chalkboard-90;
|
||||
@apply !no-underline text-xs select-none text-chalkboard-90;
|
||||
@apply ui-active:bg-primary/10 ui-active:text-primary ui-active:text-inherit;
|
||||
@apply transition-colors ease-out;
|
||||
@apply m-0;
|
||||
|
||||
@ -1617,6 +1617,12 @@ export class EngineCommandManager extends EventTarget {
|
||||
return
|
||||
}
|
||||
|
||||
// In either case we want to send the response back over the wire to
|
||||
// the rust side.
|
||||
this.rustContext?.sendResponse(message).catch((err) => {
|
||||
console.error('Error sending response to rust', err)
|
||||
})
|
||||
|
||||
const pending = this.pendingCommands[message.request_id || '']
|
||||
|
||||
if (pending && !message.success) {
|
||||
@ -1931,6 +1937,46 @@ export class EngineCommandManager extends EventTarget {
|
||||
return e
|
||||
})
|
||||
}
|
||||
/**
|
||||
* A wrapper around the sendCommand where all inputs are JSON strings
|
||||
*
|
||||
* This one does not wait for a response.
|
||||
*/
|
||||
fireModelingCommandFromWasm(
|
||||
id: string,
|
||||
rangeStr: string,
|
||||
commandStr: string,
|
||||
idToRangeStr: string
|
||||
): void | Error {
|
||||
if (this.engineConnection === undefined)
|
||||
return new Error('engineConnection is undefined')
|
||||
if (
|
||||
!this.engineConnection?.isReady() &&
|
||||
!this.engineConnection.isUsingConnectionLite
|
||||
)
|
||||
return new Error('engineConnection is not ready')
|
||||
if (id === undefined) return new Error('id is undefined')
|
||||
if (rangeStr === undefined) return new Error('rangeStr is undefined')
|
||||
if (commandStr === undefined) return new Error('commandStr is undefined')
|
||||
const range: SourceRange = JSON.parse(rangeStr)
|
||||
const command: EngineCommand = JSON.parse(commandStr)
|
||||
const idToRangeMap: { [key: string]: SourceRange } =
|
||||
JSON.parse(idToRangeStr)
|
||||
|
||||
// Current executeAst is stale, going to interrupt, a new executeAst will trigger
|
||||
// Used in conjunction with rejectAllModelingCommands
|
||||
if (this?.kclManager?.executeIsStale) {
|
||||
return new Error(EXECUTE_AST_INTERRUPT_ERROR_MESSAGE)
|
||||
}
|
||||
|
||||
// We purposely don't wait for a response here
|
||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||
this.sendCommand(id, {
|
||||
command,
|
||||
range,
|
||||
idToRangeMap,
|
||||
})
|
||||
}
|
||||
/**
|
||||
* A wrapper around the sendCommand where all inputs are JSON strings
|
||||
*/
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import toast from 'react-hot-toast'
|
||||
|
||||
import { BSON } from 'bson'
|
||||
import type { Configuration } from '@rust/kcl-lib/bindings/Configuration'
|
||||
import type { DefaultPlanes } from '@rust/kcl-lib/bindings/DefaultPlanes'
|
||||
import type { KclError as RustKclError } from '@rust/kcl-lib/bindings/KclError'
|
||||
@ -24,6 +25,7 @@ import { err, reportRejection } from '@src/lib/trap'
|
||||
import type { DeepPartial } from '@src/lib/types'
|
||||
import type { ModuleType } from '@src/lib/wasm_lib_wrapper'
|
||||
import { getModule } from '@src/lib/wasm_lib_wrapper'
|
||||
import type { Models } from '@kittycad/lib/dist/types/src'
|
||||
|
||||
export default class RustContext {
|
||||
private wasmInitFailed: boolean = true
|
||||
@ -58,6 +60,7 @@ export default class RustContext {
|
||||
// Create a new context instance
|
||||
async create(): Promise<Context> {
|
||||
this.rustInstance = getModule()
|
||||
|
||||
// We need this await here, DO NOT REMOVE it even if your editor says it's
|
||||
// unnecessary. The constructor of the module is async and it will not
|
||||
// resolve if you don't await it.
|
||||
@ -203,6 +206,21 @@ export default class RustContext {
|
||||
return this.defaultPlanes[key]
|
||||
}
|
||||
|
||||
// Send a response back to the rust side, that we got back from the engine.
|
||||
async sendResponse(
|
||||
response: Models['WebSocketResponse_type']
|
||||
): Promise<void> {
|
||||
const instance = await this._checkInstance()
|
||||
|
||||
try {
|
||||
const serialized = BSON.serialize(response)
|
||||
await instance.sendResponse(serialized)
|
||||
} catch (e: any) {
|
||||
const err = errFromErrWithOutputs(e)
|
||||
return Promise.reject(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Helper to check if context instance exists
|
||||
private async _checkInstance(): Promise<Context> {
|
||||
if (!this.ctxInstance) {
|
||||
|
||||
Reference in New Issue
Block a user