Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Add edit flow for Shell thickness #5525

Draft
wants to merge 13 commits into
base: main
Choose a base branch
from
82 changes: 82 additions & 0 deletions e2e/playwright/point-click.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2285,6 +2285,8 @@ chamfer04 = chamfer(extrude001, length = 5, tags = [getOppositeEdge(seg02)])
const [clickOnCap] = scene.makeMouseHelpers(testPoint.x, testPoint.y)
const shellDeclaration =
"shell001 = shell(extrude001, faces = ['end'], thickness = 5)"
const editedShellDeclaration =
"shell001 = shell(extrude001, faces = ['end'], thickness = 2)"

await test.step(`Look for the grey of the shape`, async () => {
await scene.expectPixelColor([127, 127, 127], testPoint, 15)
Expand Down Expand Up @@ -2351,6 +2353,47 @@ chamfer04 = chamfer(extrude001, length = 5, tags = [getOppositeEdge(seg02)])
})
await scene.expectPixelColor([146, 146, 146], testPoint, 15)
})

await test.step('Edit shell via feature tree selection works', async () => {
await toolbar.closePane('code')
await toolbar.openPane('feature-tree')
const operationButton = await toolbar.getFeatureTreeOperation(
'Shell',
0
)
await operationButton.dblclick({ button: 'left' })
await cmdBar.expectState({
stage: 'arguments',
currentArgKey: 'thickness',
currentArgValue: '5',
headerArguments: {
Selection: '1 cap',
Thickness: '5',
},
highlightedHeaderArg: 'thickness',
commandName: 'Shell',
})
await page.keyboard.insertText('2')
await cmdBar.progressCmdBar()
await cmdBar.expectState({
stage: 'review',
headerArguments: {
Selection: '1 cap',
Thickness: '2',
},
commandName: 'Shell',
})
await cmdBar.progressCmdBar()
await toolbar.closePane('feature-tree')
await scene.expectPixelColor([150, 150, 150], testPoint, 15)
await toolbar.openPane('code')
await editor.expectEditor.toContain(editedShellDeclaration)
await editor.expectState({
diagnostics: [],
activeLines: [editedShellDeclaration],
highlightedCode: '',
})
})
})
})

Expand Down Expand Up @@ -2386,6 +2429,8 @@ extrude001 = extrude(sketch001, length = 40)
const mutatedCode = 'xLine(-40, %, $seg01)'
const shellDeclaration =
"shell001 = shell(extrude001, faces = ['end', seg01], thickness = 5)"
const editedShellDeclaration =
"shell001 = shell(extrude001, faces = ['end', seg01], thickness = 1)"

await test.step(`Look for the grey of the shape`, async () => {
await scene.expectPixelColor([99, 99, 99], testPoint, 15)
Expand Down Expand Up @@ -2434,6 +2479,43 @@ extrude001 = extrude(sketch001, length = 40)
await scene.expectPixelColor([49, 49, 49], testPoint, 15)
})

await test.step('Edit shell via feature tree selection works', async () => {
await editor.closePane()
const operationButton = await toolbar.getFeatureTreeOperation('Shell', 0)
await operationButton.dblclick({ button: 'left' })
await cmdBar.expectState({
stage: 'arguments',
currentArgKey: 'thickness',
currentArgValue: '5',
headerArguments: {
Selection: '1 cap, 1 face',
Thickness: '5',
},
highlightedHeaderArg: 'thickness',
commandName: 'Shell',
})
await page.keyboard.insertText('1')
await cmdBar.progressCmdBar()
await cmdBar.expectState({
stage: 'review',
headerArguments: {
Selection: '1 cap, 1 face',
Thickness: '1',
},
commandName: 'Shell',
})
await cmdBar.progressCmdBar()
await toolbar.closePane('feature-tree')
await scene.expectPixelColor([150, 150, 150], testPoint, 15)
await toolbar.openPane('code')
await editor.expectEditor.toContain(editedShellDeclaration)
await editor.expectState({
diagnostics: [],
activeLines: [editedShellDeclaration],
highlightedCode: '',
})
})

await test.step('Delete shell via feature tree selection', async () => {
await editor.closePane()
const operationButton = await toolbar.getFeatureTreeOperation('Shell', 0)
Expand Down
54 changes: 54 additions & 0 deletions src/lang/modifyAst.ts
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,60 @@ export function loftSketches(
}
}

export function addShell({
node,
sweepName,
faces,
thickness,
insertIndex,
variableName,
}: {
node: Node<Program>
sweepName: string
faces: Expr[]
thickness: Expr
insertIndex?: number
variableName?: string
}): { modifiedAst: Node<Program>; pathToNode: PathToNode } {
const modifiedAst = structuredClone(node)
const name =
variableName ?? findUniqueName(node, KCL_DEFAULT_CONSTANT_PREFIXES.SHELL)
const shell = createCallExpressionStdLibKw(
'shell',
createIdentifier(sweepName),
[
createLabeledArg('faces', createArrayExpression(faces)),
createLabeledArg('thickness', thickness),
]
)
const variable = createVariableDeclaration(name, shell)
const insertAt =
insertIndex !== undefined
? insertIndex
: modifiedAst.body.length
? modifiedAst.body.length
: 0

modifiedAst.body.length
? modifiedAst.body.splice(insertAt, 0, variable)
: modifiedAst.body.push(variable)
const argIndex = 0
const pathToNode: PathToNode = [
['body', ''],
[insertAt, 'index'],
['declaration', 'VariableDeclaration'],
['init', 'VariableDeclarator'],
['arguments', 'CallExpressionKw'],
[argIndex, ARG_INDEX_FIELD],
['arg', LABELED_ARG_FIELD],
]

return {
modifiedAst,
pathToNode,
}
}

export function addSweep(
node: Node<Program>,
profileDeclarator: VariableDeclarator,
Expand Down
135 changes: 0 additions & 135 deletions src/lang/modifyAst/addShell.ts

This file was deleted.

12 changes: 11 additions & 1 deletion src/lib/commandBarConfigs/modelingCommandConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ export type ModelingCommandSchema = {
selection: Selections
}
Shell: {
// Enables editing workflow
nodeToEdit?: PathToNode
// KCL stdlib arguments
selection: Selections
thickness: KclCommandValue
}
Expand Down Expand Up @@ -380,6 +383,13 @@ export const modelingMachineCommandConfig: StateMachineCommandSetConfig<
icon: 'shell',
needsReview: true,
args: {
nodeToEdit: {
description:
'Path to the node in the AST to edit. Never shown to the user.',
skip: true,
inputType: 'text',
required: false,
},
selection: {
inputType: 'selection',
selectionTypes: ['cap', 'wall'],
Expand All @@ -391,7 +401,7 @@ export const modelingMachineCommandConfig: StateMachineCommandSetConfig<
inputType: 'kcl',
defaultValue: KCL_DEFAULT_LENGTH,
required: true,
// TODO: add dry-run validation on thickness param
validation: shellValidator,
},
},
},
Expand Down
21 changes: 15 additions & 6 deletions src/lib/commandBarConfigs/validators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { uuidv4 } from 'lib/utils'
import { CommandBarContext } from 'machines/commandBarMachine'
import { Selections } from 'lib/selections'
import { ApiError_type } from '@kittycad/lib/dist/types/src/models'
import { KclExpression } from 'lib/commandTypes'

export const disableDryRunWithRetry = async (numberOfRetries = 3) => {
for (let tries = 0; tries < numberOfRetries; tries++) {
Expand Down Expand Up @@ -171,16 +172,26 @@ export const loftValidator = async ({
}

export const shellValidator = async ({
context,
data,
}: {
data: { selection: Selections }
context: CommandBarContext
data: { selection?: Selections; thickness?: KclExpression }
}): Promise<boolean | string> => {
if (!isSelections(data.selection)) {
// Retrieve the thickness argument if it exists
const thicknessArgument = data.thickness
? Number(data.thickness.valueCalculated)
: undefined
const thickness: Models['LengthUnit_type'] = thicknessArgument ?? 1e-9

// Retrieve the selection from the previous arg or this arg's data directly
const selection = data.selection ?? context.argumentsToSubmit['selection']
if (!isSelections(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) =>
const face_ids = selection.graphSelections.flatMap((s) =>
s.artifact ? s.artifact.id : []
)

Expand All @@ -197,14 +208,12 @@ export const shellValidator = async ({
}

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,
shell_thickness: thickness,
}
return await engineCommandManager.sendSceneCommand({
type: 'modeling_cmd_req',
Expand Down
Loading
Loading