Working edit flow
This commit is contained in:
@ -447,13 +447,15 @@ export function addSweep(
|
||||
node: Node<Program>,
|
||||
profileDeclarator: VariableDeclarator,
|
||||
pathDeclarator: VariableDeclarator,
|
||||
sectional: boolean
|
||||
sectional: boolean,
|
||||
variableName: string | undefined
|
||||
): {
|
||||
modifiedAst: Node<Program>
|
||||
pathToNode: PathToNode
|
||||
} {
|
||||
const modifiedAst = structuredClone(node)
|
||||
const name = findUniqueName(node, KCL_DEFAULT_CONSTANT_PREFIXES.SWEEP)
|
||||
const name =
|
||||
variableName ?? findUniqueName(node, KCL_DEFAULT_CONSTANT_PREFIXES.SWEEP)
|
||||
const sweep = createCallExpressionStdLibKw(
|
||||
'sweep',
|
||||
createIdentifier(profileDeclarator.id.name),
|
||||
|
||||
@ -51,6 +51,9 @@ export type ModelingCommandSchema = {
|
||||
distance: KclCommandValue
|
||||
}
|
||||
Sweep: {
|
||||
// Enables editing workflow
|
||||
nodeToEdit?: PathToNode
|
||||
// Arguments
|
||||
target: Selections
|
||||
trajectory: Selections
|
||||
sectional: boolean
|
||||
@ -341,6 +344,13 @@ export const modelingMachineCommandConfig: StateMachineCommandSetConfig<
|
||||
icon: 'sweep',
|
||||
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,
|
||||
},
|
||||
target: {
|
||||
inputType: 'selection',
|
||||
selectionTypes: ['solid2d'],
|
||||
@ -350,7 +360,7 @@ export const modelingMachineCommandConfig: StateMachineCommandSetConfig<
|
||||
},
|
||||
trajectory: {
|
||||
inputType: 'selection',
|
||||
selectionTypes: ['segment', 'path'],
|
||||
selectionTypes: ['segment'],
|
||||
required: true,
|
||||
skip: true,
|
||||
multiple: false,
|
||||
@ -365,7 +375,7 @@ export const modelingMachineCommandConfig: StateMachineCommandSetConfig<
|
||||
{ name: 'True', value: true },
|
||||
{ name: 'False', value: false },
|
||||
],
|
||||
validation: sweepValidator,
|
||||
// validation: sweepValidator,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@ -191,6 +191,133 @@ const prepareToEditOffsetPlane: PrepareToEditCallback = async ({
|
||||
}
|
||||
}
|
||||
|
||||
const prepareToEditSweep: PrepareToEditCallback = async ({
|
||||
artifact,
|
||||
operation,
|
||||
}) => {
|
||||
const baseCommand = {
|
||||
name: 'Sweep',
|
||||
groupId: 'modeling',
|
||||
}
|
||||
if (
|
||||
operation.type !== 'StdLibCall' ||
|
||||
!operation.labeledArgs ||
|
||||
!operation.unlabeledArg ||
|
||||
!('sectional' in operation.labeledArgs) ||
|
||||
!operation.labeledArgs.sectional
|
||||
) {
|
||||
return baseCommand
|
||||
}
|
||||
if (!artifact || !('pathId' in artifact) || operation.type !== 'StdLibCall') {
|
||||
return baseCommand
|
||||
}
|
||||
|
||||
// We have to go a little roundabout to get from the original artifact
|
||||
// to the solid2DId that we need to pass to the Extrude command.
|
||||
const pathArtifact = getArtifactOfTypes(
|
||||
{
|
||||
key: artifact.pathId,
|
||||
types: ['path'],
|
||||
},
|
||||
engineCommandManager.artifactGraph
|
||||
)
|
||||
if (
|
||||
err(pathArtifact) ||
|
||||
pathArtifact.type !== 'path' ||
|
||||
!pathArtifact.solid2dId
|
||||
)
|
||||
return baseCommand
|
||||
const targetArtifact = getArtifactOfTypes(
|
||||
{
|
||||
key: pathArtifact.solid2dId,
|
||||
types: ['solid2d'],
|
||||
},
|
||||
engineCommandManager.artifactGraph
|
||||
)
|
||||
if (err(targetArtifact) || targetArtifact.type !== 'solid2d') {
|
||||
return baseCommand
|
||||
}
|
||||
|
||||
const target = {
|
||||
graphSelections: [
|
||||
{
|
||||
artifact: targetArtifact,
|
||||
codeRef: pathArtifact.codeRef,
|
||||
},
|
||||
],
|
||||
otherSelections: [],
|
||||
}
|
||||
|
||||
// Same roundabout but twice for 'path' aka trajectory: sketch -> path -> segment
|
||||
if (!('path' in operation.labeledArgs) || !operation.labeledArgs.path)
|
||||
return baseCommand
|
||||
|
||||
if (operation.labeledArgs.path.value.type !== 'Sketch') {
|
||||
return baseCommand
|
||||
}
|
||||
const trajectoryPathArtifact = getArtifactOfTypes(
|
||||
{
|
||||
key: operation.labeledArgs.path.value.value.artifactId,
|
||||
types: ['path'],
|
||||
},
|
||||
engineCommandManager.artifactGraph
|
||||
)
|
||||
if (err(trajectoryPathArtifact) || trajectoryPathArtifact.type !== 'path') {
|
||||
return baseCommand
|
||||
}
|
||||
|
||||
const trajectoryArtifact = getArtifactOfTypes(
|
||||
{
|
||||
key: trajectoryPathArtifact.segIds[0],
|
||||
types: ['segment'],
|
||||
},
|
||||
engineCommandManager.artifactGraph
|
||||
)
|
||||
if (err(trajectoryArtifact) || trajectoryArtifact.type !== 'segment') {
|
||||
return baseCommand
|
||||
}
|
||||
|
||||
const trajectory = {
|
||||
graphSelections: [
|
||||
{
|
||||
artifact: trajectoryArtifact,
|
||||
codeRef: trajectoryArtifact.codeRef,
|
||||
},
|
||||
],
|
||||
otherSelections: [],
|
||||
}
|
||||
|
||||
// sectional options boolean arg
|
||||
if (
|
||||
!('sectional' in operation.labeledArgs) ||
|
||||
!operation.labeledArgs.sectional
|
||||
)
|
||||
return baseCommand
|
||||
const sectional =
|
||||
codeManager.code.slice(
|
||||
operation.labeledArgs.sectional.sourceRange[0],
|
||||
operation.labeledArgs.sectional.sourceRange[1]
|
||||
) === 'true'
|
||||
|
||||
// Assemble the default argument values for the Offset Plane command,
|
||||
// with `nodeToEdit` set, which will let the Offset Plane actor know
|
||||
// to edit the node that corresponds to the StdLibCall.
|
||||
const argDefaultValues: ModelingCommandSchema['Sweep'] = {
|
||||
target: target,
|
||||
trajectory,
|
||||
sectional,
|
||||
nodeToEdit: getNodePathFromSourceRange(
|
||||
kclManager.ast,
|
||||
sourceRangeFromRust(operation.sourceRange)
|
||||
),
|
||||
}
|
||||
|
||||
return {
|
||||
...baseCommand,
|
||||
argDefaultValues,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A map of standard library calls to their corresponding information
|
||||
* for use in the feature tree UI.
|
||||
@ -285,6 +412,7 @@ export const stdLibMap: Record<string, StdLibCallInfo> = {
|
||||
sweep: {
|
||||
label: 'Sweep',
|
||||
icon: 'sweep',
|
||||
prepareToEdit: prepareToEditSweep,
|
||||
supportsAppearance: true,
|
||||
},
|
||||
}
|
||||
|
||||
@ -1861,9 +1861,31 @@ export const modelingMachine = setup({
|
||||
if (!input) return new Error('No input provided')
|
||||
// Extract inputs
|
||||
const ast = kclManager.ast
|
||||
const { target, trajectory, sectional } = input
|
||||
const { target, trajectory, sectional, nodeToEdit } = input
|
||||
const isEditing = nodeToEdit !== undefined // && typeof nodeToEdit[1][0] === 'number'
|
||||
let variableName: string | undefined = undefined
|
||||
|
||||
// Find the profile declaration
|
||||
// If this is an edit flow, first we're going to remove the old extrusion
|
||||
if (isEditing) {
|
||||
// Extract the plane name from the node to edit
|
||||
const variableNode = getNodeFromPath<VariableDeclaration>(
|
||||
ast,
|
||||
nodeToEdit,
|
||||
'VariableDeclaration'
|
||||
)
|
||||
if (err(variableNode)) {
|
||||
console.error('Error extracting name')
|
||||
} else {
|
||||
variableName = variableNode.node.declaration.id.name
|
||||
}
|
||||
|
||||
// Removing the old extrusion statement
|
||||
const newBody = [...ast.body]
|
||||
newBody.splice(nodeToEdit[1][0] as number, 1)
|
||||
ast.body = newBody
|
||||
}
|
||||
|
||||
// Find the target declaration
|
||||
const targetNodePath = getNodePathFromSourceRange(
|
||||
ast,
|
||||
target.graphSelections[0].codeRef.range
|
||||
@ -1878,7 +1900,7 @@ export const modelingMachine = setup({
|
||||
}
|
||||
const targetDeclarator = targetNode.node
|
||||
|
||||
// Find the path declaration
|
||||
// Find the trajectory (or path) declaration
|
||||
const trajectoryNodePath = getNodePathFromSourceRange(
|
||||
ast,
|
||||
trajectory.graphSelections[0].codeRef.range
|
||||
@ -1894,26 +1916,25 @@ export const modelingMachine = setup({
|
||||
const trajectoryDeclarator = trajectoryNode.node
|
||||
|
||||
// Perform the sweep
|
||||
const sweepRes = addSweep(
|
||||
const result = addSweep(
|
||||
ast,
|
||||
targetDeclarator,
|
||||
trajectoryDeclarator,
|
||||
sectional
|
||||
sectional,
|
||||
variableName
|
||||
)
|
||||
const updateAstResult = await kclManager.updateAst(
|
||||
sweepRes.modifiedAst,
|
||||
const updatedAst = await kclManager.updateAst(
|
||||
result.modifiedAst,
|
||||
true,
|
||||
{
|
||||
focusPath: [sweepRes.pathToNode],
|
||||
focusPath: [result.pathToNode],
|
||||
}
|
||||
)
|
||||
|
||||
await codeManager.updateEditorWithAstAndWriteToFile(
|
||||
updateAstResult.newAst
|
||||
)
|
||||
await codeManager.updateEditorWithAstAndWriteToFile(updatedAst.newAst)
|
||||
|
||||
if (updateAstResult?.selections) {
|
||||
editorManager.selectRange(updateAstResult?.selections)
|
||||
if (updatedAst?.selections) {
|
||||
editorManager.selectRange(updatedAst?.selections)
|
||||
}
|
||||
}
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user