Add selection guard and clean up

This commit is contained in:
Pierre Jacquier
2024-12-05 14:06:09 -05:00
parent 12859598a3
commit e4b0de0ead
6 changed files with 45 additions and 16 deletions

View File

@ -776,7 +776,6 @@ const shellPointAndClickCapCases = [
shellPointAndClickCapCases.forEach(({ shouldPreselect }) => { shellPointAndClickCapCases.forEach(({ shouldPreselect }) => {
test(`Shell point-and-click cap (preselected sketches: ${shouldPreselect})`, async ({ test(`Shell point-and-click cap (preselected sketches: ${shouldPreselect})`, async ({
app, app,
page,
scene, scene,
editor, editor,
toolbar, toolbar,
@ -877,7 +876,7 @@ extrude001 = extrude(40, sketch001)
// One dumb hardcoded screen pixel value // One dumb hardcoded screen pixel value
const testPoint = { x: 580, y: 250 } const testPoint = { x: 580, y: 250 }
const [clickOnCap] = scene.makeMouseHelpers(testPoint.x, testPoint.y) const [clickOnWall] = scene.makeMouseHelpers(testPoint.x, testPoint.y)
const mutatedCode = 'xLine(-40, %, $seg01)' const mutatedCode = 'xLine(-40, %, $seg01)'
const shellDeclaration = const shellDeclaration =
'shell001 = shell({ faces = [seg01], thickness = 5 }, extrude001)' 'shell001 = shell({ faces = [seg01], thickness = 5 }, extrude001)'
@ -899,7 +898,7 @@ extrude001 = extrude(40, sketch001)
highlightedHeaderArg: 'selection', highlightedHeaderArg: 'selection',
commandName: 'Shell', commandName: 'Shell',
}) })
await clickOnCap() await clickOnWall()
await cmdBar.progressCmdBar() await cmdBar.progressCmdBar()
await cmdBar.expectState({ await cmdBar.expectState({
stage: 'review', stage: 'review',

View File

@ -70,6 +70,7 @@ import {
} from 'lang/modifyAst' } from 'lang/modifyAst'
import { Program, parse, recast } from 'lang/wasm' import { Program, parse, recast } from 'lang/wasm'
import { import {
doesSceneHaveExtrudedSketch,
doesSceneHaveSweepableSketch, doesSceneHaveSweepableSketch,
getNodePathFromSourceRange, getNodePathFromSourceRange,
isSingleCursorInPipe, isSingleCursorInPipe,
@ -586,18 +587,21 @@ export const ModelingMachineProvider = ({
if (err(canLoft)) return false if (err(canLoft)) return false
return canLoft return canLoft
}, },
'has valid shell selection': ({ context: { selectionRanges } }) => { 'has valid shell selection': ({
context: { selectionRanges },
event,
}) => {
const hasNoSelection = const hasNoSelection =
selectionRanges.graphSelections.length === 0 || selectionRanges.graphSelections.length === 0 ||
isRangeBetweenCharacters(selectionRanges) || isRangeBetweenCharacters(selectionRanges) ||
isSelectionLastLine(selectionRanges, codeManager.code) isSelectionLastLine(selectionRanges, codeManager.code)
if (hasNoSelection) { if (hasNoSelection) {
// TODO: find extrude in ast return doesSceneHaveExtrudedSketch(kclManager.ast)
// return doesSceneHaveSweepableSketch(kclManager.ast, count)
} }
const canShell = canShellSelection(selectionRanges) const canShell = canShellSelection(selectionRanges)
console.log('canShellSelection', canShellSelection(selectionRanges))
if (err(canShell)) return false if (err(canShell)) return false
return canShell return canShell
}, },

View File

@ -1042,6 +1042,35 @@ export function doesSceneHaveSweepableSketch(ast: Node<Program>, count = 1) {
return Object.keys(theMap).length >= count return Object.keys(theMap).length >= count
} }
export function doesSceneHaveExtrudedSketch(ast: Node<Program>) {
const theMap: any = {}
traverse(ast as any, {
enter(node) {
if (
node.type === 'VariableDeclarator' &&
node.init?.type === 'PipeExpression'
) {
for (const pipe of node.init.body) {
if (
pipe.type === 'CallExpression' &&
pipe.callee.name === 'extrude'
) {
theMap[node.id.name] = true
break
}
}
} else if (
node.type === 'CallExpression' &&
node.callee.name === 'extrude' &&
node.arguments[1]?.type === 'Identifier'
) {
theMap[node.moduleId] = true
}
},
})
return Object.keys(theMap).length > 0
}
export function getObjExprProperty( export function getObjExprProperty(
node: ObjectExpression, node: ObjectExpression,
propName: string propName: string

View File

@ -289,7 +289,7 @@ export const modelingMachineCommandConfig: StateMachineCommandSetConfig<
selection: { selection: {
inputType: 'selection', inputType: 'selection',
selectionTypes: ['cap', 'wall'], selectionTypes: ['cap', 'wall'],
// TODO: check if we can have multiple here // TODO: allow multiple faces to be selected here
multiple: false, multiple: false,
required: true, required: true,
skip: true, skip: true,

View File

@ -583,15 +583,10 @@ export function canShellSelection(selection: Selections) {
const commonNodes = selection.graphSelections.map((_, i) => const commonNodes = selection.graphSelections.map((_, i) =>
buildCommonNodeFromSelection(selection, i) buildCommonNodeFromSelection(selection, i)
) )
return ( return commonNodes.every(
// TODO: check what's needed here (n) =>
// !!isCursorInSketchCommandRange( n.selection.artifact?.type == 'cap' ||
// engineCommandManager.artifactGraph, n.selection.artifact?.type == 'wall'
// selection
// ) &&
commonNodes.every((n) => !hasSketchPipeBeenExtruded(n.selection, n.ast)) &&
commonNodes.every((n) => nodeHasClose(n) || nodeHasCircle(n)) &&
commonNodes.every((n) => !nodeHasExtrude(n))
) )
} }

View File

@ -1682,11 +1682,13 @@ export const modelingMachine = setup({
Loft: { Loft: {
target: 'Applying loft', target: 'Applying loft',
guard: 'has valid loft selection',
reenter: true, reenter: true,
}, },
Shell: { Shell: {
target: 'Applying shell', target: 'Applying shell',
guard: 'has valid shell selection',
reenter: true, reenter: true,
}, },