Add edit flow for Shell thickness (#5525)
* WIP: Add edit flow for Shell thickness Would fix #5406 but not like this :sad: * Early win with working edit on shell * Extend to logic to walls with tags * Remove skip * Add wall test * Fixing inconsistencies in code. Tests not working on win * Refactor addShell for consitency * Clean up * More clean up * Add validation on both params * A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores) * Passing tests * Prettier * Change from test.skip to comment * Clean up for review * Add review suggestions and disable thickness validator * A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores) * A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores) * Remove uneccessary changes * Add edit flow for Shell thickness Fixes #5406 * Enable edit step in test that works only if the start code is properly formatted * Clean up for review --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
This commit is contained in:
@ -1,4 +1,5 @@
|
||||
import {
|
||||
Expr,
|
||||
PathToNode,
|
||||
VariableDeclaration,
|
||||
VariableDeclarator,
|
||||
@ -13,7 +14,7 @@ import {
|
||||
Selection,
|
||||
updateSelections,
|
||||
} from 'lib/selections'
|
||||
import { assign, fromPromise, fromCallback, setup } from 'xstate'
|
||||
import { assign, fromPromise, setup } from 'xstate'
|
||||
import { SidebarType } from 'components/ModelingSidebar/ModelingPanes'
|
||||
import { isNodeSafeToReplacePath } from 'lang/queryAst'
|
||||
import { getNodePathFromSourceRange } from 'lang/queryAstNodePathUtils'
|
||||
@ -43,7 +44,10 @@ import { revolveSketch } from 'lang/modifyAst/addRevolve'
|
||||
import {
|
||||
addHelix,
|
||||
addOffsetPlane,
|
||||
addShell,
|
||||
addSweep,
|
||||
createIdentifier,
|
||||
createLiteral,
|
||||
extrudeSketch,
|
||||
loftSketches,
|
||||
} from 'lang/modifyAst'
|
||||
@ -52,6 +56,8 @@ import {
|
||||
ChamferParameters,
|
||||
EdgeTreatmentType,
|
||||
FilletParameters,
|
||||
getPathToExtrudeForSegmentSelection,
|
||||
mutateAstWithTagForSketchSegment,
|
||||
} from 'lang/modifyAst/addEdgeTreatment'
|
||||
import { getNodeFromPath } from '../lang/queryAst'
|
||||
import {
|
||||
@ -78,7 +84,6 @@ import { ToolbarModeName } from 'lib/toolbar'
|
||||
import { quaternionFromUpNForward } from 'clientSideScene/helpers'
|
||||
import { Mesh, Vector3 } from 'three'
|
||||
import { MachineManager } from 'components/MachineManagerProvider'
|
||||
import { addShell } from 'lang/modifyAst/addShell'
|
||||
import { KclCommandValue } from 'lib/commandTypes'
|
||||
import { ModelingMachineContext } from 'components/ModelingMachineProvider'
|
||||
import {
|
||||
@ -1994,42 +1999,162 @@ export const modelingMachine = setup({
|
||||
|
||||
// Extract inputs
|
||||
const ast = kclManager.ast
|
||||
const { selection, thickness } = input
|
||||
const { selection, thickness, nodeToEdit } = input
|
||||
let variableName: string | undefined = undefined
|
||||
let insertIndex: number | undefined = undefined
|
||||
|
||||
// Insert the thickness variable if it exists
|
||||
if (
|
||||
'variableName' in thickness &&
|
||||
thickness.variableName &&
|
||||
thickness.insertIndex !== undefined
|
||||
) {
|
||||
const newBody = [...ast.body]
|
||||
newBody.splice(
|
||||
thickness.insertIndex,
|
||||
0,
|
||||
thickness.variableDeclarationAst
|
||||
// If this is an edit flow, first we're going to remove the old extrusion
|
||||
if (nodeToEdit && typeof nodeToEdit[1][0] === 'number') {
|
||||
// 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 statement
|
||||
const newBody = [...ast.body]
|
||||
newBody.splice(nodeToEdit[1][0], 1)
|
||||
ast.body = newBody
|
||||
insertIndex = nodeToEdit[1][0]
|
||||
}
|
||||
|
||||
// Turn the selection into the faces list
|
||||
const clonedAstForGetExtrude = structuredClone(ast)
|
||||
const faces: Expr[] = []
|
||||
let pathToExtrudeNode: PathToNode | undefined = undefined
|
||||
for (const graphSelection of selection.graphSelections) {
|
||||
const extrudeLookupResult = getPathToExtrudeForSegmentSelection(
|
||||
clonedAstForGetExtrude,
|
||||
graphSelection,
|
||||
engineCommandManager.artifactGraph
|
||||
)
|
||||
if (err(extrudeLookupResult)) {
|
||||
return new Error(
|
||||
"Couldn't find extrude paths from getPathToExtrudeForSegmentSelection",
|
||||
{ cause: extrudeLookupResult }
|
||||
)
|
||||
}
|
||||
|
||||
const extrudeNode = getNodeFromPath<VariableDeclaration>(
|
||||
ast,
|
||||
extrudeLookupResult.pathToExtrudeNode,
|
||||
'VariableDeclaration'
|
||||
)
|
||||
if (err(extrudeNode)) {
|
||||
return new Error("Couldn't find extrude node from selection", {
|
||||
cause: extrudeNode,
|
||||
})
|
||||
}
|
||||
|
||||
const segmentNode = getNodeFromPath<VariableDeclaration>(
|
||||
ast,
|
||||
extrudeLookupResult.pathToSegmentNode,
|
||||
'VariableDeclaration'
|
||||
)
|
||||
if (err(segmentNode)) {
|
||||
return new Error("Couldn't find segment node from selection", {
|
||||
cause: segmentNode,
|
||||
})
|
||||
}
|
||||
|
||||
if (
|
||||
extrudeNode.node.declaration.init.type === 'CallExpression' ||
|
||||
extrudeNode.node.declaration.init.type === 'CallExpressionKw'
|
||||
) {
|
||||
pathToExtrudeNode = extrudeLookupResult.pathToExtrudeNode
|
||||
} else if (
|
||||
segmentNode.node.declaration.init.type === 'PipeExpression'
|
||||
) {
|
||||
pathToExtrudeNode = extrudeLookupResult.pathToSegmentNode
|
||||
} else {
|
||||
return new Error(
|
||||
"Couldn't find extrude node that was either a call expression or a pipe",
|
||||
{ cause: segmentNode }
|
||||
)
|
||||
}
|
||||
|
||||
const selectedArtifact = graphSelection.artifact
|
||||
if (!selectedArtifact) {
|
||||
return new Error('Bad artifact from selection')
|
||||
}
|
||||
|
||||
// Check on the selection, and handle the wall vs cap casees
|
||||
let expr: Expr
|
||||
if (selectedArtifact.type === 'cap') {
|
||||
expr = createLiteral(selectedArtifact.subType)
|
||||
} else if (selectedArtifact.type === 'wall') {
|
||||
const tagResult = mutateAstWithTagForSketchSegment(
|
||||
ast,
|
||||
extrudeLookupResult.pathToSegmentNode
|
||||
)
|
||||
if (err(tagResult)) {
|
||||
return tagResult
|
||||
}
|
||||
|
||||
const { tag } = tagResult
|
||||
expr = createIdentifier(tag)
|
||||
} else {
|
||||
return new Error('Artifact is neither a cap nor a wall')
|
||||
}
|
||||
|
||||
faces.push(expr)
|
||||
}
|
||||
|
||||
if (!pathToExtrudeNode) {
|
||||
return new Error('No path to extrude node found')
|
||||
}
|
||||
|
||||
const extrudeNode = getNodeFromPath<VariableDeclarator>(
|
||||
ast,
|
||||
pathToExtrudeNode,
|
||||
'VariableDeclarator'
|
||||
)
|
||||
if (err(extrudeNode)) {
|
||||
return new Error("Couldn't find extrude node", { cause: extrudeNode })
|
||||
}
|
||||
|
||||
// Perform the shell op
|
||||
const shellResult = addShell({
|
||||
const sweepName = extrudeNode.node.id.name
|
||||
const addResult = addShell({
|
||||
node: ast,
|
||||
selection,
|
||||
artifactGraph: engineCommandManager.artifactGraph,
|
||||
sweepName,
|
||||
faces: faces,
|
||||
thickness:
|
||||
'variableName' in thickness
|
||||
? thickness.variableIdentifierAst
|
||||
: thickness.valueAst,
|
||||
insertIndex,
|
||||
variableName,
|
||||
})
|
||||
if (err(shellResult)) {
|
||||
return err(shellResult)
|
||||
|
||||
// Insert the thickness variable if the user has provided a variable name
|
||||
if (
|
||||
'variableName' in thickness &&
|
||||
thickness.variableName &&
|
||||
typeof addResult.pathToNode[1][0] === 'number'
|
||||
) {
|
||||
const insertIndex = Math.min(
|
||||
addResult.pathToNode[1][0],
|
||||
thickness.insertIndex
|
||||
)
|
||||
const newBody = [...addResult.modifiedAst.body]
|
||||
newBody.splice(insertIndex, 0, thickness.variableDeclarationAst)
|
||||
addResult.modifiedAst.body = newBody
|
||||
// Since we inserted a new variable, we need to update the path to the extrude argument
|
||||
addResult.pathToNode[1][0]++
|
||||
}
|
||||
|
||||
const updateAstResult = await kclManager.updateAst(
|
||||
shellResult.modifiedAst,
|
||||
addResult.modifiedAst,
|
||||
true,
|
||||
{
|
||||
focusPath: [shellResult.pathToNode],
|
||||
focusPath: [addResult.pathToNode],
|
||||
}
|
||||
)
|
||||
|
||||
|
Reference in New Issue
Block a user