Remove old dry-run validations on Sweep, Loft, Revolve, and Shell (#6969)
This commit is contained in:
@ -1931,84 +1931,6 @@ sketch002 = startSketchOn(XZ)
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test(`Sweep point-and-click failing validation`, async ({
|
|
||||||
context,
|
|
||||||
page,
|
|
||||||
homePage,
|
|
||||||
scene,
|
|
||||||
toolbar,
|
|
||||||
cmdBar,
|
|
||||||
}) => {
|
|
||||||
const initialCode = `@settings(defaultLengthUnit = in)
|
|
||||||
sketch001 = startSketchOn(YZ)
|
|
||||||
|> circle(
|
|
||||||
center = [0, 0],
|
|
||||||
radius = 500
|
|
||||||
)
|
|
||||||
sketch002 = startSketchOn(XZ)
|
|
||||||
|> startProfile(at = [0, 0])
|
|
||||||
|> xLine(length = -500)
|
|
||||||
|> line(endAbsolute = [-2000, 500])
|
|
||||||
`
|
|
||||||
await context.addInitScript((initialCode) => {
|
|
||||||
localStorage.setItem('persistCode', initialCode)
|
|
||||||
}, initialCode)
|
|
||||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
|
||||||
await homePage.goToModelingScene()
|
|
||||||
await scene.settled(cmdBar)
|
|
||||||
|
|
||||||
// One dumb hardcoded screen pixel value
|
|
||||||
const testPoint = { x: 700, y: 250 }
|
|
||||||
const [clickOnSketch1] = scene.makeMouseHelpers(testPoint.x, testPoint.y)
|
|
||||||
const [clickOnSketch2] = scene.makeMouseHelpers(
|
|
||||||
testPoint.x - 50,
|
|
||||||
testPoint.y
|
|
||||||
)
|
|
||||||
|
|
||||||
await test.step(`Look for sketch001`, async () => {
|
|
||||||
await toolbar.closePane('code')
|
|
||||||
await scene.expectPixelColor([53, 53, 53], testPoint, 15)
|
|
||||||
})
|
|
||||||
|
|
||||||
await test.step(`Go through the command bar flow and fail validation with a toast`, async () => {
|
|
||||||
await toolbar.sweepButton.click()
|
|
||||||
await expect
|
|
||||||
.poll(() => page.getByText('Please select one').count())
|
|
||||||
.toBe(1)
|
|
||||||
await cmdBar.expectState({
|
|
||||||
commandName: 'Sweep',
|
|
||||||
currentArgKey: 'sketches',
|
|
||||||
currentArgValue: '',
|
|
||||||
headerArguments: {
|
|
||||||
Sectional: '',
|
|
||||||
Sketches: '',
|
|
||||||
Path: '',
|
|
||||||
},
|
|
||||||
highlightedHeaderArg: 'sketches',
|
|
||||||
stage: 'arguments',
|
|
||||||
})
|
|
||||||
await clickOnSketch1()
|
|
||||||
await cmdBar.progressCmdBar()
|
|
||||||
await cmdBar.expectState({
|
|
||||||
commandName: 'Sweep',
|
|
||||||
currentArgKey: 'path',
|
|
||||||
currentArgValue: '',
|
|
||||||
headerArguments: {
|
|
||||||
Sectional: '',
|
|
||||||
Sketches: '1 face',
|
|
||||||
Path: '',
|
|
||||||
},
|
|
||||||
highlightedHeaderArg: 'path',
|
|
||||||
stage: 'arguments',
|
|
||||||
})
|
|
||||||
await clickOnSketch2()
|
|
||||||
await cmdBar.progressCmdBar()
|
|
||||||
await expect(
|
|
||||||
page.getByText('Unable to sweep with the current selection. Reason:')
|
|
||||||
).toBeVisible()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
test(`Fillet point-and-click`, async ({
|
test(`Fillet point-and-click`, async ({
|
||||||
context,
|
context,
|
||||||
page,
|
page,
|
||||||
@ -3627,67 +3549,6 @@ profile001 = startProfile(sketch001, at = [-20, 20])
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test(`Shell dry-run validation rejects sweeps`, async ({
|
|
||||||
context,
|
|
||||||
page,
|
|
||||||
homePage,
|
|
||||||
scene,
|
|
||||||
editor,
|
|
||||||
toolbar,
|
|
||||||
cmdBar,
|
|
||||||
}) => {
|
|
||||||
const initialCode = `sketch001 = startSketchOn(YZ)
|
|
||||||
|> circle(
|
|
||||||
center = [0, 0],
|
|
||||||
radius = 500
|
|
||||||
)
|
|
||||||
sketch002 = startSketchOn(XZ)
|
|
||||||
|> startProfile(at = [0, 0])
|
|
||||||
|> xLine(length = -2000)
|
|
||||||
sweep001 = sweep(sketch001, path = sketch002)
|
|
||||||
`
|
|
||||||
await context.addInitScript((initialCode) => {
|
|
||||||
localStorage.setItem('persistCode', initialCode)
|
|
||||||
}, initialCode)
|
|
||||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
|
||||||
await homePage.goToModelingScene()
|
|
||||||
await scene.settled(cmdBar)
|
|
||||||
|
|
||||||
// One dumb hardcoded screen pixel value
|
|
||||||
const testPoint = { x: 500, y: 250 }
|
|
||||||
const [clickOnSweep] = scene.makeMouseHelpers(testPoint.x, testPoint.y)
|
|
||||||
|
|
||||||
await test.step(`Confirm sweep exists`, async () => {
|
|
||||||
await toolbar.closePane('code')
|
|
||||||
await scene.expectPixelColor([231, 231, 231], testPoint, 15)
|
|
||||||
})
|
|
||||||
|
|
||||||
await test.step(`Go through the Shell flow and fail validation with a toast`, async () => {
|
|
||||||
await toolbar.shellButton.click()
|
|
||||||
await expect
|
|
||||||
.poll(() => page.getByText('Please select one').count())
|
|
||||||
.toBe(1)
|
|
||||||
await cmdBar.expectState({
|
|
||||||
stage: 'arguments',
|
|
||||||
currentArgKey: 'selection',
|
|
||||||
currentArgValue: '',
|
|
||||||
headerArguments: {
|
|
||||||
Selection: '',
|
|
||||||
Thickness: '',
|
|
||||||
},
|
|
||||||
highlightedHeaderArg: 'selection',
|
|
||||||
commandName: 'Shell',
|
|
||||||
})
|
|
||||||
await clickOnSweep()
|
|
||||||
await page.waitForTimeout(500)
|
|
||||||
await cmdBar.progressCmdBar()
|
|
||||||
await expect(
|
|
||||||
page.getByText('Unable to shell with the current selection. Reason:')
|
|
||||||
).toBeVisible()
|
|
||||||
await page.waitForTimeout(1000)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
test.describe('Revolve point and click workflows', () => {
|
test.describe('Revolve point and click workflows', () => {
|
||||||
test('Base case workflow, auto spam continue in command bar', async ({
|
test('Base case workflow, auto spam continue in command bar', async ({
|
||||||
context,
|
context,
|
||||||
|
@ -12,12 +12,6 @@ import type {
|
|||||||
VariableDeclarator,
|
VariableDeclarator,
|
||||||
} from '@src/lang/wasm'
|
} from '@src/lang/wasm'
|
||||||
import { isPathToNode } from '@src/lang/wasm'
|
import { isPathToNode } from '@src/lang/wasm'
|
||||||
import {
|
|
||||||
loftValidator,
|
|
||||||
revolveAxisValidator,
|
|
||||||
shellValidator,
|
|
||||||
sweepValidator,
|
|
||||||
} from '@src/lib/commandBarConfigs/validators'
|
|
||||||
import type {
|
import type {
|
||||||
KclCommandValue,
|
KclCommandValue,
|
||||||
StateMachineCommandSetConfig,
|
StateMachineCommandSetConfig,
|
||||||
@ -428,7 +422,6 @@ export const modelingMachineCommandConfig: StateMachineCommandSetConfig<
|
|||||||
selectionTypes: ['segment'],
|
selectionTypes: ['segment'],
|
||||||
required: true,
|
required: true,
|
||||||
multiple: false,
|
multiple: false,
|
||||||
validation: sweepValidator,
|
|
||||||
hidden: (context) => Boolean(context.argumentsToSubmit.nodeToEdit),
|
hidden: (context) => Boolean(context.argumentsToSubmit.nodeToEdit),
|
||||||
},
|
},
|
||||||
sectional: {
|
sectional: {
|
||||||
@ -455,7 +448,6 @@ export const modelingMachineCommandConfig: StateMachineCommandSetConfig<
|
|||||||
selectionTypes: ['solid2d'],
|
selectionTypes: ['solid2d'],
|
||||||
multiple: true,
|
multiple: true,
|
||||||
required: true,
|
required: true,
|
||||||
validation: loftValidator,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -508,7 +500,6 @@ export const modelingMachineCommandConfig: StateMachineCommandSetConfig<
|
|||||||
inputType: 'selection',
|
inputType: 'selection',
|
||||||
selectionTypes: ['segment', 'sweepEdge', 'edgeCutEdge'],
|
selectionTypes: ['segment', 'sweepEdge', 'edgeCutEdge'],
|
||||||
multiple: false,
|
multiple: false,
|
||||||
validation: revolveAxisValidator,
|
|
||||||
hidden: (context) => Boolean(context.argumentsToSubmit.nodeToEdit),
|
hidden: (context) => Boolean(context.argumentsToSubmit.nodeToEdit),
|
||||||
},
|
},
|
||||||
angle: {
|
angle: {
|
||||||
@ -535,7 +526,6 @@ export const modelingMachineCommandConfig: StateMachineCommandSetConfig<
|
|||||||
selectionTypes: ['cap', 'wall'],
|
selectionTypes: ['cap', 'wall'],
|
||||||
multiple: true,
|
multiple: true,
|
||||||
required: true,
|
required: true,
|
||||||
validation: shellValidator,
|
|
||||||
hidden: (context) => Boolean(context.argumentsToSubmit.nodeToEdit),
|
hidden: (context) => Boolean(context.argumentsToSubmit.nodeToEdit),
|
||||||
},
|
},
|
||||||
thickness: {
|
thickness: {
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
import { parseEngineErrorMessage } from '@src/lib/commandBarConfigs/validators'
|
|
||||||
|
|
||||||
describe('parseEngineErrorMessage', () => {
|
|
||||||
it('takes an engine error string and parses its json message', () => {
|
|
||||||
const engineError =
|
|
||||||
'[{"success": false,"request_id": "e6c0104b-ec60-4779-8e98-722f0a5019ec","errors": [{"error_code": "internal_engine","message": "Trajectory curve must be G1 continuous (with continuous tangents)"}]}]'
|
|
||||||
const parsedEngineError = JSON.parse(engineError)
|
|
||||||
const message = parseEngineErrorMessage(parsedEngineError)
|
|
||||||
expect(message).toEqual(
|
|
||||||
'Trajectory curve must be G1 continuous (with continuous tangents)'
|
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
|
@ -1,317 +0,0 @@
|
|||||||
import type { Models } from '@kittycad/lib'
|
|
||||||
|
|
||||||
import type { Selections } from '@src/lib/selections'
|
|
||||||
import { engineCommandManager, kclManager } from '@src/lib/singletons'
|
|
||||||
import { isArray, uuidv4 } from '@src/lib/utils'
|
|
||||||
import type { CommandBarContext } from '@src/machines/commandBarMachine'
|
|
||||||
|
|
||||||
export const disableDryRunWithRetry = async (numberOfRetries = 3) => {
|
|
||||||
for (let tries = 0; tries < numberOfRetries; tries++) {
|
|
||||||
try {
|
|
||||||
await engineCommandManager.sendSceneCommand({
|
|
||||||
type: 'modeling_cmd_req',
|
|
||||||
cmd_id: uuidv4(),
|
|
||||||
cmd: { type: 'disable_dry_run' },
|
|
||||||
})
|
|
||||||
// Exit out since the command was successful
|
|
||||||
return
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e)
|
|
||||||
console.error('disable_dry_run failed. This is bad!')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Takes a callback function and wraps it around enable_dry_run and disable_dry_run
|
|
||||||
export const dryRunWrapper = async (
|
|
||||||
callback: () => Promise<
|
|
||||||
| Models['WebSocketResponse_type']
|
|
||||||
| [Models['WebSocketResponse_type']]
|
|
||||||
| undefined
|
|
||||||
| null
|
|
||||||
>
|
|
||||||
): Promise<[Models['WebSocketResponse_type']] | undefined> => {
|
|
||||||
// Gotcha: What about race conditions?
|
|
||||||
try {
|
|
||||||
await engineCommandManager.sendSceneCommand({
|
|
||||||
type: 'modeling_cmd_req',
|
|
||||||
cmd_id: uuidv4(),
|
|
||||||
cmd: { type: 'enable_dry_run' },
|
|
||||||
})
|
|
||||||
const result = await callback()
|
|
||||||
if (!result) {
|
|
||||||
return undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isArray(result)) {
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
return [result]
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e)
|
|
||||||
} finally {
|
|
||||||
await disableDryRunWithRetry(5)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function isSelections(selections: unknown): selections is Selections {
|
|
||||||
return (
|
|
||||||
(selections as Selections).graphSelections !== undefined &&
|
|
||||||
(selections as Selections).otherSelections !== undefined
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function parseEngineErrorMessage(
|
|
||||||
engineErrors?: [Models['WebSocketResponse_type']]
|
|
||||||
): string | undefined {
|
|
||||||
if (!engineErrors) {
|
|
||||||
return undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!engineErrors[0]) {
|
|
||||||
return undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
const engineError = engineErrors[0]
|
|
||||||
|
|
||||||
if (engineError.success) {
|
|
||||||
return undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
const errors = engineError.errors
|
|
||||||
if (!errors[0]) {
|
|
||||||
return undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
return errors[0].message
|
|
||||||
}
|
|
||||||
|
|
||||||
export const revolveAxisValidator = async ({
|
|
||||||
data,
|
|
||||||
context,
|
|
||||||
}: {
|
|
||||||
data: { [key: string]: Selections }
|
|
||||||
context: CommandBarContext
|
|
||||||
}): Promise<boolean | string> => {
|
|
||||||
if (!isSelections(context.argumentsToSubmit.sketches)) {
|
|
||||||
return 'Unable to revolve, selections are missing'
|
|
||||||
}
|
|
||||||
// Gotcha: this validation only works for the first sketch
|
|
||||||
const artifact =
|
|
||||||
context.argumentsToSubmit.sketches.graphSelections[0].artifact
|
|
||||||
|
|
||||||
if (!artifact) {
|
|
||||||
return 'Unable to revolve, sketch not found'
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!('pathId' in artifact)) {
|
|
||||||
return 'Unable to revolve, sketch has no path'
|
|
||||||
}
|
|
||||||
|
|
||||||
const sketchSelection = artifact.pathId
|
|
||||||
let edgeSelection = data.edge.graphSelections[0].artifact?.id
|
|
||||||
|
|
||||||
if (!sketchSelection) {
|
|
||||||
return 'Unable to revolve, sketch is missing'
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!edgeSelection) {
|
|
||||||
return 'Unable to revolve, edge is missing'
|
|
||||||
}
|
|
||||||
|
|
||||||
const angleInDegrees: Models['Angle_type'] = {
|
|
||||||
unit: 'degrees',
|
|
||||||
value: 360,
|
|
||||||
}
|
|
||||||
|
|
||||||
const command = async () => {
|
|
||||||
return await engineCommandManager.sendSceneCommand({
|
|
||||||
type: 'modeling_cmd_req',
|
|
||||||
cmd_id: uuidv4(),
|
|
||||||
cmd: {
|
|
||||||
type: 'revolve_about_edge',
|
|
||||||
angle: angleInDegrees,
|
|
||||||
edge_id: edgeSelection,
|
|
||||||
target: sketchSelection,
|
|
||||||
// Gotcha: Playwright will fail with larger tolerances, need to use a smaller one.
|
|
||||||
tolerance: 1e-7,
|
|
||||||
// WARNING: I'm not sure this is what it should be.
|
|
||||||
opposite: 'None',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
const result = await dryRunWrapper(command)
|
|
||||||
if (result && result[0] && result[0].success) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
const reason = parseEngineErrorMessage(result) || 'unknown'
|
|
||||||
return `Unable to revolve with the current selection. Reason: ${reason}`
|
|
||||||
}
|
|
||||||
|
|
||||||
export const loftValidator = async ({
|
|
||||||
data,
|
|
||||||
}: {
|
|
||||||
data: { [key: string]: Selections }
|
|
||||||
context: CommandBarContext
|
|
||||||
}): Promise<boolean | string> => {
|
|
||||||
if (!isSelections(data.sketches)) {
|
|
||||||
return 'Unable to loft, selections are missing'
|
|
||||||
}
|
|
||||||
const { sketches } = data
|
|
||||||
|
|
||||||
if (sketches.graphSelections.some((s) => s.artifact?.type !== 'solid2d')) {
|
|
||||||
return 'Unable to loft, some selection are not solid2ds'
|
|
||||||
}
|
|
||||||
|
|
||||||
const sectionIds = sketches.graphSelections.flatMap((s) =>
|
|
||||||
s.artifact?.type === 'solid2d' ? s.artifact.pathId : []
|
|
||||||
)
|
|
||||||
|
|
||||||
if (sectionIds.length < 2) {
|
|
||||||
return 'Unable to loft, selection contains less than two solid2ds'
|
|
||||||
}
|
|
||||||
|
|
||||||
const command = async () => {
|
|
||||||
// TODO: check what to do with these
|
|
||||||
const DEFAULT_V_DEGREE = 2
|
|
||||||
const DEFAULT_TOLERANCE = 2
|
|
||||||
const DEFAULT_BEZ_APPROXIMATE_RATIONAL = false
|
|
||||||
return await engineCommandManager.sendSceneCommand({
|
|
||||||
type: 'modeling_cmd_req',
|
|
||||||
cmd_id: uuidv4(),
|
|
||||||
cmd: {
|
|
||||||
section_ids: sectionIds,
|
|
||||||
type: 'loft',
|
|
||||||
bez_approximate_rational: DEFAULT_BEZ_APPROXIMATE_RATIONAL,
|
|
||||||
tolerance: DEFAULT_TOLERANCE,
|
|
||||||
v_degree: DEFAULT_V_DEGREE,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
const result = await dryRunWrapper(command)
|
|
||||||
if (result && result[0] && result[0].success) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
const reason = parseEngineErrorMessage(result) || 'unknown'
|
|
||||||
return `Unable to loft with the current selection. Reason: ${reason}`
|
|
||||||
}
|
|
||||||
|
|
||||||
export const shellValidator = async ({
|
|
||||||
data,
|
|
||||||
}: {
|
|
||||||
data: { selection: Selections }
|
|
||||||
}): Promise<boolean | string> => {
|
|
||||||
if (!isSelections(data.selection)) {
|
|
||||||
return 'Unable to shell, selections are missing'
|
|
||||||
}
|
|
||||||
|
|
||||||
// No validation on the faces, filtering is done upstream and we have the dry run validation just below
|
|
||||||
const face_ids = data.selection.graphSelections.flatMap((s) =>
|
|
||||||
s.artifact ? s.artifact.id : []
|
|
||||||
)
|
|
||||||
|
|
||||||
// We don't have the concept of solid3ds in TS yet.
|
|
||||||
// So we're listing out the sweeps as if they were solids and taking the first one, just like in Rust for Shell:
|
|
||||||
// https://github.com/KittyCAD/modeling-app/blob/e61fff115b9fa94aaace6307b1842cc15d41655e/src/wasm-lib/kcl/src/std/shell.rs#L237-L238
|
|
||||||
// TODO: This is one cheap way to make sketch-on-face supported now but will likely fail multiple solids
|
|
||||||
const object_id = kclManager.artifactGraph
|
|
||||||
.values()
|
|
||||||
.find((v) => v.type === 'sweep')?.pathId
|
|
||||||
|
|
||||||
if (!object_id) {
|
|
||||||
return "Unable to shell, couldn't find the solid"
|
|
||||||
}
|
|
||||||
|
|
||||||
const command = async () => {
|
|
||||||
// TODO: figure out something better than an arbitrarily small value
|
|
||||||
const DEFAULT_THICKNESS: Models['LengthUnit_type'] = 1e-9
|
|
||||||
const DEFAULT_HOLLOW = false
|
|
||||||
const cmdArgs = {
|
|
||||||
face_ids,
|
|
||||||
object_id,
|
|
||||||
hollow: DEFAULT_HOLLOW,
|
|
||||||
shell_thickness: DEFAULT_THICKNESS,
|
|
||||||
}
|
|
||||||
return await engineCommandManager.sendSceneCommand({
|
|
||||||
type: 'modeling_cmd_req',
|
|
||||||
cmd_id: uuidv4(),
|
|
||||||
cmd: {
|
|
||||||
type: 'solid3d_shell_face',
|
|
||||||
...cmdArgs,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = await dryRunWrapper(command)
|
|
||||||
if (result && result[0] && result[0].success) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
const reason = parseEngineErrorMessage(result) || 'unknown'
|
|
||||||
return `Unable to shell with the current selection. Reason: ${reason}`
|
|
||||||
}
|
|
||||||
|
|
||||||
export const sweepValidator = async ({
|
|
||||||
context,
|
|
||||||
data,
|
|
||||||
}: {
|
|
||||||
context: CommandBarContext
|
|
||||||
data: { path: Selections }
|
|
||||||
}): Promise<boolean | string> => {
|
|
||||||
if (!isSelections(data.path)) {
|
|
||||||
console.log('Unable to sweep, selections are missing')
|
|
||||||
return 'Unable to sweep, selections are missing'
|
|
||||||
}
|
|
||||||
|
|
||||||
// Retrieve the parent path from the segment selection directly
|
|
||||||
const trajectoryArtifact = data.path.graphSelections[0].artifact
|
|
||||||
if (!trajectoryArtifact) {
|
|
||||||
return "Unable to sweep, couldn't find the trajectory artifact"
|
|
||||||
}
|
|
||||||
if (trajectoryArtifact.type !== 'segment') {
|
|
||||||
return "Unable to sweep, couldn't find the target from a non-segment selection"
|
|
||||||
}
|
|
||||||
const trajectory = trajectoryArtifact.pathId
|
|
||||||
|
|
||||||
// Get the former arg in the command bar flow, and retrieve the path from the solid2d directly
|
|
||||||
const targetArg = context.argumentsToSubmit['sketches'] as Selections
|
|
||||||
const targetArtifact = targetArg.graphSelections[0].artifact
|
|
||||||
if (!targetArtifact) {
|
|
||||||
return "Unable to sweep, couldn't find the profile artifact"
|
|
||||||
}
|
|
||||||
if (targetArtifact.type !== 'solid2d') {
|
|
||||||
return "Unable to sweep, couldn't find the target from a non-solid2d selection"
|
|
||||||
}
|
|
||||||
const target = targetArtifact.pathId
|
|
||||||
|
|
||||||
const command = async () => {
|
|
||||||
// TODO: second look on defaults here
|
|
||||||
const DEFAULT_TOLERANCE: Models['LengthUnit_type'] = 1e-7
|
|
||||||
const DEFAULT_SECTIONAL = false
|
|
||||||
const cmdArgs = {
|
|
||||||
target,
|
|
||||||
trajectory,
|
|
||||||
sectional: DEFAULT_SECTIONAL,
|
|
||||||
tolerance: DEFAULT_TOLERANCE,
|
|
||||||
}
|
|
||||||
return await engineCommandManager.sendSceneCommand({
|
|
||||||
type: 'modeling_cmd_req',
|
|
||||||
cmd_id: uuidv4(),
|
|
||||||
cmd: {
|
|
||||||
type: 'sweep',
|
|
||||||
...cmdArgs,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = await dryRunWrapper(command)
|
|
||||||
if (result && result[0] && result[0].success) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
const reason = parseEngineErrorMessage(result) || 'unknown'
|
|
||||||
return `Unable to sweep with the current selection. Reason: ${reason}`
|
|
||||||
}
|
|
Reference in New Issue
Block a user