Add support for deleting sketches on caps (not walls)

This commit is contained in:
Frank Noirot
2025-02-12 20:12:57 -05:00
parent 3747db01b8
commit 09f3e6e170
3 changed files with 110 additions and 43 deletions

View File

@ -60,7 +60,14 @@ import { Models } from '@kittycad/lib'
import { ExtrudeFacePlane } from 'machines/modelingMachine' import { ExtrudeFacePlane } from 'machines/modelingMachine'
import { Node } from 'wasm-lib/kcl/bindings/Node' import { Node } from 'wasm-lib/kcl/bindings/Node'
import { KclExpressionWithVariable } from 'lib/commandTypes' import { KclExpressionWithVariable } from 'lib/commandTypes'
import { Artifact, expandPath, expandPlane, getPathsFromArtifact } from './std/artifactGraph' import {
Artifact,
expandCap,
expandPath,
expandPlane,
getPathsFromArtifact,
getPlaneFromArtifact,
} from './std/artifactGraph'
import { BodyItem } from 'wasm-lib/kcl/bindings/BodyItem' import { BodyItem } from 'wasm-lib/kcl/bindings/BodyItem'
import { findKwArg } from './util' import { findKwArg } from './util'
import { deleteEdgeTreatment } from './modifyAst/addEdgeTreatment' import { deleteEdgeTreatment } from './modifyAst/addEdgeTreatment'
@ -106,10 +113,10 @@ export function insertNewStartProfileAt(
insertType: 'start' | 'end' = 'end' insertType: 'start' | 'end' = 'end'
): ):
| { | {
modifiedAst: Node<Program> modifiedAst: Node<Program>
updatedSketchNodePaths: PathToNode[] updatedSketchNodePaths: PathToNode[]
updatedEntryNodePath: PathToNode updatedEntryNodePath: PathToNode
} }
| Error { | Error {
const varDec = getNodeFromPath<VariableDeclarator>( const varDec = getNodeFromPath<VariableDeclarator>(
node, node,
@ -334,10 +341,10 @@ export function extrudeSketch({
artifact?: Artifact artifact?: Artifact
}): }):
| { | {
modifiedAst: Node<Program> modifiedAst: Node<Program>
pathToNode: PathToNode pathToNode: PathToNode
pathToExtrudeArg: PathToNode pathToExtrudeArg: PathToNode
} }
| Error { | Error {
const orderedSketchNodePaths = getPathsFromArtifact({ const orderedSketchNodePaths = getPathsFromArtifact({
artifact: artifact, artifact: artifact,
@ -473,10 +480,10 @@ export function revolveSketch(
angle: Expr = createLiteral(4) angle: Expr = createLiteral(4)
): ):
| { | {
modifiedAst: Node<Program> modifiedAst: Node<Program>
pathToNode: PathToNode pathToNode: PathToNode
pathToRevolveArg: PathToNode pathToRevolveArg: PathToNode
} }
| Error { | Error {
const _node = structuredClone(node) const _node = structuredClone(node)
const _node1 = getNodeFromPath(_node, pathToNode) const _node1 = getNodeFromPath(_node, pathToNode)
@ -677,8 +684,8 @@ export function addOffsetPlane({
insertIndex !== undefined insertIndex !== undefined
? insertIndex ? insertIndex
: modifiedAst.body.length : modifiedAst.body.length
? modifiedAst.body.length ? modifiedAst.body.length
: 0 : 0
modifiedAst.body.length modifiedAst.body.length
? modifiedAst.body.splice(insertAt, 0, newPlane) ? modifiedAst.body.splice(insertAt, 0, newPlane)
@ -1142,11 +1149,11 @@ export function giveSketchFnCallTag(
tag?: string tag?: string
): ):
| { | {
modifiedAst: Node<Program> modifiedAst: Node<Program>
tag: string tag: string
isTagExisting: boolean isTagExisting: boolean
pathToNode: PathToNode pathToNode: PathToNode
} }
| Error { | Error {
const path = getNodePathFromSourceRange(ast, range) const path = getNodePathFromSourceRange(ast, range)
const maybeTag = (() => { const maybeTag = (() => {
@ -1312,11 +1319,11 @@ export function deleteSegmentFromPipeExpression(
const constraintInfo = const constraintInfo =
callExp.node.type === 'CallExpression' callExp.node.type === 'CallExpression'
? getConstraintInfo(callExp.node, code, path).find(({ sourceRange }) => ? getConstraintInfo(callExp.node, code, path).find(({ sourceRange }) =>
isOverlap(sourceRange, range) isOverlap(sourceRange, range)
) )
: getConstraintInfoKw(callExp.node, code, path).find( : getConstraintInfoKw(callExp.node, code, path).find(
({ sourceRange }) => isOverlap(sourceRange, range) ({ sourceRange }) => isOverlap(sourceRange, range)
) )
if (!constraintInfo) return if (!constraintInfo) return
if (!constraintInfo.argPosition) return if (!constraintInfo.argPosition) return
@ -1356,9 +1363,9 @@ export function removeSingleConstraintInfo(
memVars: VariableMap memVars: VariableMap
): ):
| { | {
modifiedAst: Node<Program> modifiedAst: Node<Program>
pathToNodeMap: PathToNodeMap pathToNodeMap: PathToNodeMap
} }
| false { | false {
const transform = removeSingleConstraint({ const transform = removeSingleConstraint({
pathToCallExp, pathToCallExp,
@ -1386,10 +1393,19 @@ export async function deleteFromSelection(
): Promise<Node<Program> | Error> { ): Promise<Node<Program> | Error> {
const astClone = structuredClone(ast) const astClone = structuredClone(ast)
console.log('deleting', selection, variables) console.log('deleting', selection, variables)
if (selection.artifact?.type === 'plane' && selection.artifact.pathIds.length) { if (
const plane = expandPlane(selection.artifact, engineCommandManager.artifactGraph) (selection.artifact?.type === 'plane' ||
selection.artifact?.type === 'cap') &&
selection.artifact.pathIds.length
) {
const plane =
selection.artifact.type === 'plane'
? expandPlane(selection.artifact, engineCommandManager.artifactGraph)
: expandCap(selection.artifact, engineCommandManager.artifactGraph)
console.log('plane expanded', plane) console.log('plane expanded', plane)
for (const path of plane.paths.sort((a, b) => b.codeRef.range[0] - a.codeRef.range[0])) { for (const path of plane.paths.sort(
(a, b) => b.codeRef.range[0] - a.codeRef.range[0]
)) {
const varDec = getNodeFromPath<VariableDeclarator>( const varDec = getNodeFromPath<VariableDeclarator>(
ast, ast,
path.codeRef.pathToNode, path.codeRef.pathToNode,
@ -1399,6 +1415,11 @@ export async function deleteFromSelection(
const bodyIndex = Number(varDec.shallowPath[1][0]) const bodyIndex = Number(varDec.shallowPath[1][0])
astClone.body.splice(bodyIndex, 1) astClone.body.splice(bodyIndex, 1)
} }
// If it's a cap, we're not going to continue and try to
// delete the extrusion
if (selection.artifact.type === 'cap') {
return astClone
}
} }
const varDec = getNodeFromPath<VariableDeclarator>( const varDec = getNodeFromPath<VariableDeclarator>(
ast, ast,
@ -1477,7 +1498,7 @@ export async function deleteFromSelection(
astClone.body.splice(expressionIndex, 1) astClone.body.splice(expressionIndex, 1)
if (extrudeNameToDelete) { if (extrudeNameToDelete) {
await new Promise((resolve) => { await new Promise((resolve) => {
; (async () => { ;(async () => {
let currentVariableName = '' let currentVariableName = ''
const pathsDependingOnExtrude: Array<{ const pathsDependingOnExtrude: Array<{
path: PathToNode path: PathToNode
@ -1490,7 +1511,7 @@ export async function deleteFromSelection(
} }
}, },
enter: (node, path) => { enter: (node, path) => {
; (async () => { ;(async () => {
if (node.type === 'VariableDeclaration') { if (node.type === 'VariableDeclaration') {
currentVariableName = node.declaration.id.name currentVariableName = node.declaration.id.name
} }
@ -1640,8 +1661,8 @@ export function getInsertIndex(
const insertIndex = !sketchNodePaths.length const insertIndex = !sketchNodePaths.length
? Number(planeNodePath[1][0]) + 1 ? Number(planeNodePath[1][0]) + 1
: insertType === 'start' : insertType === 'start'
? minIndex ? minIndex
: maxIndex + 1 : maxIndex + 1
return insertIndex return insertIndex
} }
@ -1709,10 +1730,10 @@ export function splitPipedProfile(
pathToPipe: PathToNode pathToPipe: PathToNode
): ):
| { | {
modifiedAst: Program modifiedAst: Program
pathToProfile: PathToNode pathToProfile: PathToNode
pathToPlane: PathToNode pathToPlane: PathToNode
} }
| Error { | Error {
const _ast = structuredClone(ast) const _ast = structuredClone(ast)
const varDec = getNodeFromPath<VariableDeclaration>( const varDec = getNodeFromPath<VariableDeclaration>(
@ -1752,9 +1773,9 @@ export function splitPipedProfile(
varDec.node.declaration.init.body.length <= 2 varDec.node.declaration.init.body.length <= 2
? firstCallOfNewPipe ? firstCallOfNewPipe
: createPipeExpression([ : createPipeExpression([
firstCallOfNewPipe, firstCallOfNewPipe,
...varDec.node.declaration.init.body.slice(2), ...varDec.node.declaration.init.body.slice(2),
]) ])
) )
const index = getBodyIndex(pathToPipe) const index = getBodyIndex(pathToPipe)
if (err(index)) return index if (err(index)) return index

View File

@ -20,6 +20,7 @@ import { Models } from '@kittycad/lib'
import { getNodePathFromSourceRange } from 'lang/queryAstNodePathUtils' import { getNodePathFromSourceRange } from 'lang/queryAstNodePathUtils'
import { err } from 'lib/trap' import { err } from 'lib/trap'
import { Cap, Plane, Wall } from 'wasm-lib/kcl/bindings/Artifact' import { Cap, Plane, Wall } from 'wasm-lib/kcl/bindings/Artifact'
import { CapSubType } from 'wasm-lib/kcl/bindings/Artifact'
export type { Artifact, ArtifactId, SegmentArtifact } from 'lang/wasm' export type { Artifact, ArtifactId, SegmentArtifact } from 'lang/wasm'
@ -38,6 +39,15 @@ export interface PlaneArtifactRich extends BaseArtifact {
codeRef: CodeRef codeRef: CodeRef
} }
export interface CapArtifactRich extends BaseArtifact {
type: 'cap'
subType: CapSubType
faceCodeRef: CodeRef
edgeCuts: Array<EdgeCut>
paths: Array<PathArtifact>
sweep?: SweepArtifact
}
export interface PathArtifactRich extends BaseArtifact { export interface PathArtifactRich extends BaseArtifact {
type: 'path' type: 'path'
/** A path must always lie on a plane */ /** A path must always lie on a plane */
@ -152,6 +162,41 @@ export function expandPlane(
} }
} }
export function expandCap(
cap: CapArtifact,
artifactGraph: ArtifactGraph
): CapArtifactRich {
const { pathIds, sweepId: _s, edgeCutEdgeIds, ...keptProperties } = cap
const paths = pathIds?.length
? Array.from(
getArtifactsOfTypes(
{ keys: cap.pathIds, types: ['path'] },
artifactGraph
).values()
)
: []
const maybeSweep = getArtifactOfTypes(
{ key: cap.sweepId, types: ['sweep'] },
artifactGraph
)
const sweep = err(maybeSweep) ? undefined : maybeSweep
const edgeCuts = edgeCutEdgeIds?.length
? Array.from(
getArtifactsOfTypes(
{ keys: cap.edgeCutEdgeIds, types: ['edgeCut'] },
artifactGraph
).values()
)
: []
return {
type: 'cap',
...keptProperties,
paths,
sweep,
edgeCuts,
}
}
export function expandPath( export function expandPath(
path: PathArtifact, path: PathArtifact,
artifactGraph: ArtifactGraph artifactGraph: ArtifactGraph

View File

@ -80,10 +80,11 @@ export function isCursorInSketchCommandRange(
const parentId = const parentId =
firstEntry?.type === 'segment' firstEntry?.type === 'segment'
? firstEntry.pathId ? firstEntry.pathId
: (firstEntry?.type === 'plane' || : ((firstEntry?.type === 'plane' ||
firstEntry?.type === 'cap' || firstEntry?.type === 'cap' ||
firstEntry?.type === 'wall') && firstEntry?.type === 'wall') &&
firstEntry.pathIds.length firstEntry.pathIds?.length) ||
false
? firstEntry.pathIds[0] ? firstEntry.pathIds[0]
: false : false