Compare commits
4 Commits
fillet-err
...
eslint
Author | SHA1 | Date | |
---|---|---|---|
e5091ebfcb | |||
8e4c5fb24d | |||
6993893600 | |||
bfdf8babed |
@ -17,9 +17,13 @@
|
|||||||
"extends": [
|
"extends": [
|
||||||
"plugin:css-modules/recommended",
|
"plugin:css-modules/recommended",
|
||||||
"plugin:jsx-a11y/recommended",
|
"plugin:jsx-a11y/recommended",
|
||||||
"plugin:react-hooks/recommended"
|
"plugin:react-hooks/recommended",
|
||||||
|
"plugin:react-perf/recommended"
|
||||||
],
|
],
|
||||||
"rules": {
|
"rules": {
|
||||||
|
"react-perf/jsx-no-new-object-as-prop": "off", // We don't think this helps anything.
|
||||||
|
"react-perf/jsx-no-new-function-as-prop": "off", // We don't think this helps anything.
|
||||||
|
"react-perf/jsx-no-new-array-as-prop": "off", // We don't think this helps anything.
|
||||||
"no-array-constructor": "off", // This is wrong; use the @typescript-eslint one instead.
|
"no-array-constructor": "off", // This is wrong; use the @typescript-eslint one instead.
|
||||||
"@typescript-eslint/no-array-constructor": "error",
|
"@typescript-eslint/no-array-constructor": "error",
|
||||||
"@typescript-eslint/no-array-delete": "error",
|
"@typescript-eslint/no-array-delete": "error",
|
||||||
|
File diff suppressed because one or more lines are too long
@ -32,53 +32,44 @@ test(
|
|||||||
})
|
})
|
||||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
|
|
||||||
page.on('console', console.log)
|
|
||||||
|
|
||||||
await test.step('on open of project', async () => {
|
await test.step('on open of project', async () => {
|
||||||
await expect(page.getByText(`bracket`)).toBeVisible()
|
// Open the project
|
||||||
|
const projectName = page.getByText(`bracket`)
|
||||||
|
await expect(projectName).toBeVisible()
|
||||||
|
await projectName.click()
|
||||||
|
await scene.waitForExecutionDone()
|
||||||
|
await page.waitForTimeout(1_000) // wait for panel buttons to be available
|
||||||
|
|
||||||
// open the project
|
// Expect zero errors in gutter
|
||||||
await page.getByText(`bracket`).click()
|
|
||||||
|
|
||||||
// expect zero errors in guter
|
|
||||||
await expect(page.locator('.cm-lint-marker-error')).not.toBeVisible()
|
await expect(page.locator('.cm-lint-marker-error')).not.toBeVisible()
|
||||||
|
|
||||||
// export the model
|
// Click the export button
|
||||||
const exportButton = page.getByTestId('export-pane-button')
|
const exportButton = page.getByTestId('export-pane-button')
|
||||||
await expect(exportButton).toBeVisible()
|
await expect(exportButton).toBeVisible()
|
||||||
|
|
||||||
await scene.waitForExecutionDone()
|
|
||||||
|
|
||||||
const gltfOption = page.getByText('glTF')
|
|
||||||
const submitButton = page.getByText('Confirm Export')
|
|
||||||
const exportingToastMessage = page.getByText(`Exporting...`)
|
|
||||||
const errorToastMessage = page.getByText(`Error while exporting`)
|
|
||||||
const engineErrorToastMessage = page.getByText(`Nothing to export`)
|
|
||||||
const alreadyExportingToastMessage = page.getByText(`Already exporting`)
|
|
||||||
// The open file's name is `main.kcl`, so the export file name should be `main.gltf`
|
|
||||||
const exportFileName = `main.gltf`
|
|
||||||
|
|
||||||
// Click the export button
|
|
||||||
await exportButton.click()
|
await exportButton.click()
|
||||||
|
await page.waitForTimeout(1_000) // wait for export options to be available
|
||||||
|
|
||||||
|
// Select the first format option
|
||||||
|
const gltfOption = page.getByText('glTF')
|
||||||
|
const exportFileName = `main.gltf` // source file is named `main.kcl`
|
||||||
await expect(gltfOption).toBeVisible()
|
await expect(gltfOption).toBeVisible()
|
||||||
await expect(page.getByText('STL')).toBeVisible()
|
|
||||||
|
|
||||||
await page.keyboard.press('Enter')
|
await page.keyboard.press('Enter')
|
||||||
|
|
||||||
// Click the checkbox
|
// Click the checkbox
|
||||||
|
const submitButton = page.getByText('Confirm Export')
|
||||||
await expect(submitButton).toBeVisible()
|
await expect(submitButton).toBeVisible()
|
||||||
|
|
||||||
await page.waitForTimeout(500)
|
await page.waitForTimeout(500)
|
||||||
|
|
||||||
await page.keyboard.press('Enter')
|
await page.keyboard.press('Enter')
|
||||||
|
|
||||||
// Find the toast.
|
|
||||||
// Look out for the toast message
|
// Look out for the toast message
|
||||||
|
const exportingToastMessage = page.getByText(`Exporting...`)
|
||||||
|
const alreadyExportingToastMessage = page.getByText(`Already exporting`)
|
||||||
await expect(exportingToastMessage).toBeVisible()
|
await expect(exportingToastMessage).toBeVisible()
|
||||||
await expect(alreadyExportingToastMessage).not.toBeVisible()
|
await expect(alreadyExportingToastMessage).not.toBeVisible()
|
||||||
|
|
||||||
// Expect it to succeed.
|
// Expect it to succeed
|
||||||
|
const errorToastMessage = page.getByText(`Error while exporting`)
|
||||||
|
const engineErrorToastMessage = page.getByText(`Nothing to export`)
|
||||||
await expect(errorToastMessage).not.toBeVisible()
|
await expect(errorToastMessage).not.toBeVisible()
|
||||||
await expect(engineErrorToastMessage).not.toBeVisible()
|
await expect(engineErrorToastMessage).not.toBeVisible()
|
||||||
|
|
||||||
@ -86,6 +77,7 @@ test(
|
|||||||
await expect(successToastMessage).toBeVisible()
|
await expect(successToastMessage).toBeVisible()
|
||||||
await expect(exportingToastMessage).not.toBeVisible()
|
await expect(exportingToastMessage).not.toBeVisible()
|
||||||
|
|
||||||
|
// Check for the exported file
|
||||||
const firstFileFullPath = path.resolve(
|
const firstFileFullPath = path.resolve(
|
||||||
getPlaywrightDownloadDir(tronApp.projectDirName),
|
getPlaywrightDownloadDir(tronApp.projectDirName),
|
||||||
exportFileName
|
exportFileName
|
||||||
@ -112,60 +104,53 @@ test(
|
|||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
await u.openFilePanel()
|
await u.openFilePanel()
|
||||||
|
|
||||||
|
// Click on the other file
|
||||||
const otherKclButton = page.getByRole('button', { name: 'other.kcl' })
|
const otherKclButton = page.getByRole('button', { name: 'other.kcl' })
|
||||||
|
|
||||||
// Click the file
|
|
||||||
await otherKclButton.click()
|
await otherKclButton.click()
|
||||||
|
|
||||||
// Close the file pane
|
// Close the file pane
|
||||||
await u.closeFilePanel()
|
await u.closeFilePanel()
|
||||||
|
await scene.waitForExecutionDone()
|
||||||
|
await page.waitForTimeout(1_000) // wait for panel buttons to be available
|
||||||
|
|
||||||
// FIXME: await scene.waitForExecutionDone() does not work. The modeling indicator stays in -receive-reliable and not execution done
|
// Expect zero errors in gutter
|
||||||
await page.waitForTimeout(10000)
|
|
||||||
|
|
||||||
// expect zero errors in guter
|
|
||||||
await expect(page.locator('.cm-lint-marker-error')).not.toBeVisible()
|
await expect(page.locator('.cm-lint-marker-error')).not.toBeVisible()
|
||||||
|
|
||||||
// export the model
|
// Click the export button
|
||||||
const exportButton = page.getByTestId('export-pane-button')
|
const exportButton = page.getByTestId('export-pane-button')
|
||||||
await expect(exportButton).toBeVisible()
|
await expect(exportButton).toBeVisible()
|
||||||
|
|
||||||
const gltfOption = page.getByText('glTF')
|
|
||||||
const submitButton = page.getByText('Confirm Export')
|
|
||||||
const exportingToastMessage = page.getByText(`Exporting...`)
|
|
||||||
const errorToastMessage = page.getByText(`Error while exporting`)
|
|
||||||
const engineErrorToastMessage = page.getByText(`Nothing to export`)
|
|
||||||
const alreadyExportingToastMessage = page.getByText(`Already exporting`)
|
|
||||||
// The open file's name is `other.kcl`, so the export file name should be `other.gltf`
|
|
||||||
const exportFileName = `other.gltf`
|
|
||||||
|
|
||||||
// Click the export button
|
|
||||||
await exportButton.click()
|
await exportButton.click()
|
||||||
|
await page.waitForTimeout(1_000) // wait for export options to be available
|
||||||
|
|
||||||
|
// Select the first format option
|
||||||
|
const gltfOption = page.getByText('glTF')
|
||||||
|
const exportFileName = `other.gltf` // source file is named `other.kcl`
|
||||||
await expect(gltfOption).toBeVisible()
|
await expect(gltfOption).toBeVisible()
|
||||||
await expect(page.getByText('STL')).toBeVisible()
|
|
||||||
|
|
||||||
await page.keyboard.press('Enter')
|
await page.keyboard.press('Enter')
|
||||||
|
|
||||||
// Click the checkbox
|
// Click the checkbox
|
||||||
|
const submitButton = page.getByText('Confirm Export')
|
||||||
await expect(submitButton).toBeVisible()
|
await expect(submitButton).toBeVisible()
|
||||||
|
await page.waitForTimeout(500)
|
||||||
await page.keyboard.press('Enter')
|
await page.keyboard.press('Enter')
|
||||||
|
|
||||||
// Find the toast.
|
|
||||||
// Look out for the toast message
|
// Look out for the toast message
|
||||||
|
const exportingToastMessage = page.getByText(`Exporting...`)
|
||||||
|
const alreadyExportingToastMessage = page.getByText(`Already exporting`)
|
||||||
await expect(exportingToastMessage).toBeVisible()
|
await expect(exportingToastMessage).toBeVisible()
|
||||||
|
await expect(alreadyExportingToastMessage).not.toBeVisible()
|
||||||
|
|
||||||
|
// Expect it to succeed
|
||||||
|
const errorToastMessage = page.getByText(`Error while exporting`)
|
||||||
|
const engineErrorToastMessage = page.getByText(`Nothing to export`)
|
||||||
|
await expect(errorToastMessage).not.toBeVisible()
|
||||||
|
await expect(engineErrorToastMessage).not.toBeVisible()
|
||||||
|
|
||||||
const successToastMessage = page.getByText(`Exported successfully`)
|
const successToastMessage = page.getByText(`Exported successfully`)
|
||||||
await test.step('Check the success toast message shows and nothing else', async () =>
|
await expect(successToastMessage).toBeVisible()
|
||||||
Promise.all([
|
await expect(exportingToastMessage).not.toBeVisible()
|
||||||
expect(alreadyExportingToastMessage).not.toBeVisible(),
|
|
||||||
expect(errorToastMessage).not.toBeVisible(),
|
|
||||||
expect(engineErrorToastMessage).not.toBeVisible(),
|
|
||||||
expect(successToastMessage).toBeVisible(),
|
|
||||||
expect(exportingToastMessage).not.toBeVisible(),
|
|
||||||
]))
|
|
||||||
|
|
||||||
|
// Check for the exported file=
|
||||||
const secondFileFullPath = path.resolve(
|
const secondFileFullPath = path.resolve(
|
||||||
getPlaywrightDownloadDir(tronApp.projectDirName),
|
getPlaywrightDownloadDir(tronApp.projectDirName),
|
||||||
exportFileName
|
exportFileName
|
||||||
|
@ -1315,4 +1315,38 @@ sketch001 = startSketchOn(XZ)
|
|||||||
const element = page.locator('[data-overlay-index="1"]')
|
const element = page.locator('[data-overlay-index="1"]')
|
||||||
await expect(element).toHaveAttribute('data-overlay-visible', 'true')
|
await expect(element).toHaveAttribute('data-overlay-visible', 'true')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test(`Only show axis planes when there are no errors`, async ({
|
||||||
|
page,
|
||||||
|
homePage,
|
||||||
|
scene,
|
||||||
|
cmdBar,
|
||||||
|
}) => {
|
||||||
|
await page.addInitScript(async () => {
|
||||||
|
localStorage.setItem(
|
||||||
|
'persistCode',
|
||||||
|
`sketch001 = startSketchOn(XZ)
|
||||||
|
profile001 = circle(sketch001, center = [-100.0, -100.0], radius = 50.0)
|
||||||
|
|
||||||
|
sketch002 = startSketchOn(XZ)
|
||||||
|
profile002 = circle(sketch002, center = [-100.0, 100.0], radius = 50.0)
|
||||||
|
extrude001 = extrude(profile002, length = 0)` // length = 0 is causing the error
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
const viewportSize = { width: 1200, height: 800 }
|
||||||
|
await page.setBodyDimensions(viewportSize)
|
||||||
|
|
||||||
|
await homePage.goToModelingScene()
|
||||||
|
|
||||||
|
await scene.connectionEstablished()
|
||||||
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
|
await scene.expectPixelColor(
|
||||||
|
TEST_COLORS.DARK_MODE_BKGD,
|
||||||
|
// This is a position where the blue part of the axis plane is visible if its rendered
|
||||||
|
{ x: viewportSize.width * 0.75, y: viewportSize.height * 0.2 },
|
||||||
|
15
|
||||||
|
)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -94,4 +94,4 @@ outsideWallSketch = startSketchOn(offsetPlane(XY, offset = -overallThickness / 2
|
|||||||
|> circle(center = [0, 0], radius = outsideDiameter / 2)
|
|> circle(center = [0, 0], radius = outsideDiameter / 2)
|
||||||
|> hole(circle(center = [0, 0], radius = shaftDia / 2 + wallThickness + sphereDia), %)
|
|> hole(circle(center = [0, 0], radius = shaftDia / 2 + wallThickness + sphereDia), %)
|
||||||
|
|
||||||
outsideWall = extrude(outsideWallSketch, length = overallThickness)
|
outsideWall = extrude(outsideWallSketch, length = overallThickness)
|
||||||
|
@ -21,7 +21,7 @@ archThickness = 1
|
|||||||
archRadius = mirrorRadius + archToMirrorGap
|
archRadius = mirrorRadius + archToMirrorGap
|
||||||
|
|
||||||
// Geometry
|
// Geometry
|
||||||
// Add a function to create the hinge
|
// Add a function to create the hinge
|
||||||
fn hingeFn(x, y, z) {
|
fn hingeFn(x, y, z) {
|
||||||
hingeBody = startSketchOn(offsetPlane(XY, offset = z))
|
hingeBody = startSketchOn(offsetPlane(XY, offset = z))
|
||||||
|> circle(center = [x, y], radius = hingeRadius)
|
|> circle(center = [x, y], radius = hingeRadius)
|
||||||
|
@ -9,7 +9,6 @@ import pipeInnerDiameter, pipeOuterDiameter, pipeLength from "parameters.kcl"
|
|||||||
|
|
||||||
// Create a function to make the pipe. Export
|
// Create a function to make the pipe. Export
|
||||||
export fn pipe() {
|
export fn pipe() {
|
||||||
|
|
||||||
// Create the pipe base
|
// Create the pipe base
|
||||||
pipeBase = startSketchOn(XZ)
|
pipeBase = startSketchOn(XZ)
|
||||||
|> circle(%, center = [0, 0], radius = pipeOuterDiameter / 2)
|
|> circle(%, center = [0, 0], radius = pipeOuterDiameter / 2)
|
||||||
|
@ -9,7 +9,6 @@ import pipeDiameter, mountingHoleDiameter, mountingHolePlacementDiameter, flange
|
|||||||
|
|
||||||
// Create a function to create the flange. We must create a function since we are using multiple flanges.
|
// Create a function to create the flange. We must create a function since we are using multiple flanges.
|
||||||
export fn flange() {
|
export fn flange() {
|
||||||
|
|
||||||
// Sketch the mounting hole pattern
|
// Sketch the mounting hole pattern
|
||||||
mountingHoles = startSketchOn(XY)
|
mountingHoles = startSketchOn(XY)
|
||||||
|> circle(%, center = [0, mountingHolePlacementDiameter / 2], radius = mountingHoleDiameter / 2)
|
|> circle(%, center = [0, mountingHolePlacementDiameter / 2], radius = mountingHoleDiameter / 2)
|
||||||
@ -42,4 +41,4 @@ export fn flange() {
|
|||||||
|> appearance(%, color = "#bab0b0")
|
|> appearance(%, color = "#bab0b0")
|
||||||
|
|
||||||
return pipeCut
|
return pipeCut
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,6 @@ import hexNutDiameter, hexNutFlatToFlat, hexNutThickness, hexNutFlatLength from
|
|||||||
|
|
||||||
// Create a function to make the hex nut. Must be a function since multiple hex nuts are used
|
// Create a function to make the hex nut. Must be a function since multiple hex nuts are used
|
||||||
export fn hexNut() {
|
export fn hexNut() {
|
||||||
|
|
||||||
// Create the base of the hex nut
|
// Create the base of the hex nut
|
||||||
hexNutBase = startSketchOn(XY)
|
hexNutBase = startSketchOn(XY)
|
||||||
|> startProfileAt([
|
|> startProfileAt([
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
// Import parameters
|
// Import parameters
|
||||||
import washerInnerDia, washerOuterDia, washerThickness from "parameters.kcl"
|
import washerInnerDia, washerOuterDia, washerThickness from "parameters.kcl"
|
||||||
|
|
||||||
// Create a function to make the washer. Must be a function since multiple washers are used.
|
// Create a function to make the washer. Must be a function since multiple washers are used.
|
||||||
export fn washer() {
|
export fn washer() {
|
||||||
// Create the base of the washer
|
// Create the base of the washer
|
||||||
washerBase = startSketchOn(XY)
|
washerBase = startSketchOn(XY)
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
import * from "parameters.kcl"
|
import * from "parameters.kcl"
|
||||||
|
|
||||||
// Import parts
|
// Import parts
|
||||||
import '9472k188-gasket.kcl' as gasket
|
import "9472k188-gasket.kcl" as gasket
|
||||||
import flange from "68095k348-flange.kcl"
|
import flange from "68095k348-flange.kcl"
|
||||||
import washer from "98017a257-washer.kcl"
|
import washer from "98017a257-washer.kcl"
|
||||||
import bolt from "91251a404-bolt.kcl"
|
import bolt from "91251a404-bolt.kcl"
|
||||||
|
@ -418,6 +418,9 @@ pub struct Sketch {
|
|||||||
pub artifact_id: ArtifactId,
|
pub artifact_id: ArtifactId,
|
||||||
#[ts(skip)]
|
#[ts(skip)]
|
||||||
pub original_id: uuid::Uuid,
|
pub original_id: uuid::Uuid,
|
||||||
|
/// If the sketch includes a mirror.
|
||||||
|
#[serde(skip)]
|
||||||
|
pub mirror: Option<uuid::Uuid>,
|
||||||
pub units: UnitLen,
|
pub units: UnitLen,
|
||||||
/// Metadata.
|
/// Metadata.
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
|
@ -13,7 +13,7 @@ use kcmc::{
|
|||||||
websocket::{ModelingCmdReq, OkWebSocketResponseData},
|
websocket::{ModelingCmdReq, OkWebSocketResponseData},
|
||||||
ModelingCmd,
|
ModelingCmd,
|
||||||
};
|
};
|
||||||
use kittycad_modeling_cmds as kcmc;
|
use kittycad_modeling_cmds::{self as kcmc};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -168,13 +168,18 @@ pub(crate) async fn do_post_extrude<'a>(
|
|||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
// The "get extrusion face info" API call requires *any* edge on the sketch being extruded.
|
let any_edge_id = if let Some(edge_id) = sketch.mirror {
|
||||||
// So, let's just use the first one.
|
edge_id
|
||||||
let Some(any_edge_id) = sketch.paths.first().map(|edge| edge.get_base().geo_meta.id) else {
|
} else {
|
||||||
return Err(KclError::Type(KclErrorDetails {
|
// The "get extrusion face info" API call requires *any* edge on the sketch being extruded.
|
||||||
message: "Expected a non-empty sketch".to_string(),
|
// So, let's just use the first one.
|
||||||
source_ranges: vec![args.source_range],
|
let Some(any_edge_id) = sketch.paths.first().map(|edge| edge.get_base().geo_meta.id) else {
|
||||||
}));
|
return Err(KclError::Type(KclErrorDetails {
|
||||||
|
message: "Expected a non-empty sketch".to_string(),
|
||||||
|
source_ranges: vec![args.source_range],
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
any_edge_id
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut sketch = sketch.clone();
|
let mut sketch = sketch.clone();
|
||||||
|
@ -2,10 +2,13 @@
|
|||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use kcmc::{each_cmd as mcmd, ModelingCmd};
|
use kcmc::{each_cmd as mcmd, ModelingCmd};
|
||||||
use kittycad_modeling_cmds::{self as kcmc, length_unit::LengthUnit, shared::Point3d};
|
use kittycad_modeling_cmds::{
|
||||||
|
self as kcmc, length_unit::LengthUnit, ok_response::OkModelingCmdResponse, output::EntityGetAllChildUuids,
|
||||||
|
shared::Point3d, websocket::OkWebSocketResponseData,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
errors::KclError,
|
errors::{KclError, KclErrorDetails},
|
||||||
execution::{
|
execution::{
|
||||||
types::{PrimitiveType, RuntimeType},
|
types::{PrimitiveType, RuntimeType},
|
||||||
ExecState, KclValue, Sketch,
|
ExecState, KclValue, Sketch,
|
||||||
@ -31,13 +34,21 @@ pub async fn mirror_2d(exec_state: &mut ExecState, args: Args) -> Result<KclValu
|
|||||||
Ok(sketches.into())
|
Ok(sketches.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Mirror a sketch.
|
||||||
|
///
|
||||||
|
/// Only works on unclosed sketches for now.
|
||||||
async fn inner_mirror_2d(
|
async fn inner_mirror_2d(
|
||||||
sketches: Vec<Sketch>,
|
sketches: Vec<Sketch>,
|
||||||
axis: Axis2dOrEdgeReference,
|
axis: Axis2dOrEdgeReference,
|
||||||
exec_state: &mut ExecState,
|
exec_state: &mut ExecState,
|
||||||
args: Args,
|
args: Args,
|
||||||
) -> Result<Vec<Sketch>, KclError> {
|
) -> Result<Vec<Sketch>, KclError> {
|
||||||
let starting_sketches = sketches;
|
let mut starting_sketches = sketches.clone();
|
||||||
|
|
||||||
|
// Update all to have a mirror.
|
||||||
|
starting_sketches.iter_mut().for_each(|sketch| {
|
||||||
|
sketch.mirror = Some(exec_state.next_uuid());
|
||||||
|
});
|
||||||
|
|
||||||
if args.ctx.no_engine_commands().await {
|
if args.ctx.no_engine_commands().await {
|
||||||
return Ok(starting_sketches);
|
return Ok(starting_sketches);
|
||||||
@ -77,5 +88,40 @@ async fn inner_mirror_2d(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// After the mirror, get the first child uuid for the path.
|
||||||
|
// The "get extrusion face info" API call requires *any* edge on the sketch being extruded.
|
||||||
|
// But if you mirror2d a sketch these IDs might change so we need to get the children versus
|
||||||
|
// using the IDs we already have.
|
||||||
|
// We only do this with mirrors because otherwise it is a waste of a websocket call.
|
||||||
|
for sketch in &mut starting_sketches {
|
||||||
|
let response = args
|
||||||
|
.send_modeling_cmd(
|
||||||
|
exec_state.next_uuid(),
|
||||||
|
ModelingCmd::from(mcmd::EntityGetAllChildUuids { entity_id: sketch.id }),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
let OkWebSocketResponseData::Modeling {
|
||||||
|
modeling_response:
|
||||||
|
OkModelingCmdResponse::EntityGetAllChildUuids(EntityGetAllChildUuids { entity_ids: child_ids }),
|
||||||
|
} = response
|
||||||
|
else {
|
||||||
|
return Err(KclError::Internal(KclErrorDetails {
|
||||||
|
message: "Expected a successful response from EntityGetAllChildUuids".to_string(),
|
||||||
|
source_ranges: vec![args.source_range],
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
if child_ids.len() >= 2 {
|
||||||
|
// The first child is the original sketch, the second is the mirrored sketch.
|
||||||
|
let child_id = child_ids[1];
|
||||||
|
sketch.mirror = Some(child_id);
|
||||||
|
} else {
|
||||||
|
return Err(KclError::Type(KclErrorDetails {
|
||||||
|
message: "Expected child uuids to be >= 2".to_string(),
|
||||||
|
source_ranges: vec![args.source_range],
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(starting_sketches)
|
Ok(starting_sketches)
|
||||||
}
|
}
|
||||||
|
@ -1343,6 +1343,7 @@ pub(crate) async fn inner_start_profile_at(
|
|||||||
on: sketch_surface.clone(),
|
on: sketch_surface.clone(),
|
||||||
paths: vec![],
|
paths: vec![],
|
||||||
units: sketch_surface.units(),
|
units: sketch_surface.units(),
|
||||||
|
mirror: Default::default(),
|
||||||
meta: vec![args.source_range.into()],
|
meta: vec![args.source_range.into()],
|
||||||
tags: if let Some(tag) = &tag {
|
tags: if let Some(tag) = &tag {
|
||||||
let mut tag_identifier: TagIdentifier = tag.into();
|
let mut tag_identifier: TagIdentifier = tag.into();
|
||||||
|
@ -96,6 +96,25 @@ export fn circle(
|
|||||||
///
|
///
|
||||||
/// example = extrude(sketch001, length = 10)
|
/// example = extrude(sketch001, length = 10)
|
||||||
/// ```
|
/// ```
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// // Sketch on the face of a mirrored sketch, that has been extruded.
|
||||||
|
/// sketch0011 = startSketchOn(XY)
|
||||||
|
/// |> startProfileAt([6.77, 0], %)
|
||||||
|
/// |> yLine(length = 1.27)
|
||||||
|
/// |> tangentialArcTo([5.96, 2.37], %)
|
||||||
|
/// |> tangentialArcTo([-6.2, 2.44], %)
|
||||||
|
/// |> tangentialArcTo([-6.6, 1.82], %)
|
||||||
|
/// |> yLine(length = -1.82)
|
||||||
|
/// |> mirror2d( axis = X )
|
||||||
|
/// |> extrude(length = 10)
|
||||||
|
///
|
||||||
|
/// sketch002 = startSketchOn(sketch0011, 'END')
|
||||||
|
/// |> circle( center = [-0.01, 1.58], radius = 1.2 )
|
||||||
|
/// |> extrude(length = 1.2)
|
||||||
|
///
|
||||||
|
/// shell([sketch002], faces = ['end'], thickness = .1 )
|
||||||
|
/// ```
|
||||||
@(impl = std_rust)
|
@(impl = std_rust)
|
||||||
export fn mirror2d(
|
export fn mirror2d(
|
||||||
/// The sketch or sketches to be reflected.
|
/// The sketch or sketches to be reflected.
|
||||||
|
@ -209,6 +209,14 @@ description: Artifact commands i-beam.kcl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "entity_get_all_child_uuids",
|
||||||
|
"entity_id": "[uuid]"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"cmdId": "[uuid]",
|
"cmdId": "[uuid]",
|
||||||
"range": [],
|
"range": [],
|
||||||
@ -229,6 +237,14 @@ description: Artifact commands i-beam.kcl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"cmdId": "[uuid]",
|
||||||
|
"range": [],
|
||||||
|
"command": {
|
||||||
|
"type": "entity_get_all_child_uuids",
|
||||||
|
"entity_id": "[uuid]"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"cmdId": "[uuid]",
|
"cmdId": "[uuid]",
|
||||||
"range": [],
|
"range": [],
|
||||||
@ -278,5 +294,345 @@ description: Artifact commands i-beam.kcl
|
|||||||
"object_id": "[uuid]",
|
"object_id": "[uuid]",
|
||||||
"edge_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": "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": "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": "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]"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -215,8 +215,8 @@ description: Variables in memory after executing i-beam.kcl
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"height": 72.00000000000001,
|
"height": 72.00000000000001,
|
||||||
"startCapId": null,
|
"startCapId": "[uuid]",
|
||||||
"endCapId": null,
|
"endCapId": "[uuid]",
|
||||||
"units": {
|
"units": {
|
||||||
"type": "Inches"
|
"type": "Inches"
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
After Width: | Height: | Size: 78 KiB |
Reference in New Issue
Block a user