Add edit flows for extrude and offset plane operations (#5045)
* Start implementing a "prepareToEdit" callback for extrude
* Start of generic edit flow for operations
* Actually invoking command bar send generically on double-click
* Refactor: break out non-React hook helper to calculate Kcl expression value
* Add unit tests, fmt
* Integrate helper to get calculated KclExpression
* Clean up unused imports, simplify use of `programMemoryFromVariables`
* Implement basic extrude editing
* Refactor: move DefaultPlanesStr to its own lib file
* Add support for editing offset planes
* Add Edit right-click menu option
* Turn off edit flow for sketch for now
* Add e2e tests for sketch and offset plane editing, fix bug found with offset plane editing
* Add failing e2e extrude edit test
* Remove action version of extrude AST mod
* Fix behavior when adding a constant while editing operation, fixing e2e test
* Patch in changes from 61b02b5703
* Remove shell's prepareToEdit
* Add other Surface types to `artifactIsPlaneWithPaths`
* refactor: rename `item` to `operation`
* Allow `prepareToEdit` to fail with a toast, signal sketch-on-offset is unimplemented
* Rework sketch e2e test to test several working and failing cases
* Fix tsc errors related to making `codeRef` optional
* Make basic error messages more friendly
* fmt
* Reset modifyAst.ts to main
* Fix broken artifactGraph unit test
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* Remove unused import
* Look at this (photo)Graph *in the voice of Nickelback*
* Make the offset plane insert at the end, not one before
* Fix bug caught by e2e test failure with "Command needs review" logic
* Update src/machines/modelingMachine.ts
Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>
* Remove console logs per @pierremtb
* Update src/components/CommandBar/CommandBarHeader.tsx
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
* Use better programMemory init thanks @jtran
* Fix tsc post merge of #5068
* Fix logic for `artifactIsPlaneWithPaths` post-merge
* Need to disable the sketch-on-face case now that artifactGraph is in Rust. Will active in a future PR (cc @jtran)
* Re-run CI after snapshots
* Update FeatureTreePane to not use `useCommandsContext`, missed during merge
* Fix merge issue, import location change on edited file
* fix click test step, which I believe is waiting for context scripts to load
* Convert toolbarFixture.exeIndicator to getter
We need to convert all these selectors on fixtures to getters, because
they can go stale if called on the fixture constructor.
* Missed a dumb little thing in toolbarFixture.ts
* Fix goof with merge
* fmt
* Another dumb missed thing during merge
I gotta get used to the LazyGit merge tool I'm not good at it yet
* 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)
* Conver sceneFixture's exeIndicator to a getter
Locators on fixtures will be frozen from the time of the fixture's
initialization, I'm increasingly convinced
* 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)
* 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)
* 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)
* 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)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
* Post-kwargs E2E test cleanup
* 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)
* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
This commit is contained in:
@ -70,7 +70,8 @@ import {
|
||||
} from 'components/Toolbar/SetAbsDistance'
|
||||
import { ModelingCommandSchema } from 'lib/commandBarConfigs/modelingCommandConfig'
|
||||
import { err, reportRejection, trap } from 'lib/trap'
|
||||
import { DefaultPlaneStr, getFaceDetails } from 'clientSideScene/sceneEntities'
|
||||
import { getFaceDetails } from 'clientSideScene/sceneEntities'
|
||||
import { DefaultPlaneStr } from 'lib/planes'
|
||||
import { uuidv4 } from 'lib/utils'
|
||||
import { Coords2d } from 'lang/std/sketch'
|
||||
import { deleteSegment } from 'clientSideScene/ClientSideSceneComp'
|
||||
@ -1452,24 +1453,49 @@ export const modelingMachine = setup({
|
||||
unknown,
|
||||
ModelingCommandSchema['Extrude'] | undefined
|
||||
>(async ({ input }) => {
|
||||
if (!input) return Promise.reject('No input provided')
|
||||
const { selection, distance } = input
|
||||
if (!input) return new Error('No input provided')
|
||||
const { selection, distance, nodeToEdit } = input
|
||||
const isEditing =
|
||||
nodeToEdit !== undefined && typeof nodeToEdit[1][0] === 'number'
|
||||
let ast = structuredClone(kclManager.ast)
|
||||
let extrudeName: string | undefined = undefined
|
||||
|
||||
// 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 extrudeNameNode = getNodeFromPath<VariableDeclaration>(
|
||||
ast,
|
||||
nodeToEdit,
|
||||
'VariableDeclaration'
|
||||
)
|
||||
if (err(extrudeNameNode)) {
|
||||
console.error('Error extracting plane name')
|
||||
} else {
|
||||
extrudeName = extrudeNameNode.node.declaration.id.name
|
||||
}
|
||||
|
||||
// Removing the old extrusion statement
|
||||
const newBody = [...ast.body]
|
||||
newBody.splice(nodeToEdit[1][0] as number, 1)
|
||||
ast.body = newBody
|
||||
}
|
||||
|
||||
const pathToNode = getNodePathFromSourceRange(
|
||||
ast,
|
||||
selection.graphSelections[0]?.codeRef.range
|
||||
)
|
||||
// Add an extrude statement to the AST
|
||||
const extrudeSketchRes = extrudeSketch(
|
||||
ast,
|
||||
const extrudeSketchRes = extrudeSketch({
|
||||
node: ast,
|
||||
pathToNode,
|
||||
false,
|
||||
'variableName' in distance
|
||||
? distance.variableIdentifierAst
|
||||
: distance.valueAst
|
||||
)
|
||||
if (err(extrudeSketchRes)) return Promise.reject(extrudeSketchRes)
|
||||
shouldPipe: false,
|
||||
distance:
|
||||
'variableName' in distance
|
||||
? distance.variableIdentifierAst
|
||||
: distance.valueAst,
|
||||
extrudeName,
|
||||
})
|
||||
if (err(extrudeSketchRes)) return extrudeSketchRes
|
||||
const { modifiedAst, pathToExtrudeArg } = extrudeSketchRes
|
||||
|
||||
// Insert the distance variable if the user has provided a variable name
|
||||
@ -1513,30 +1539,37 @@ export const modelingMachine = setup({
|
||||
if (!input) return new Error('No input provided')
|
||||
// Extract inputs
|
||||
const ast = kclManager.ast
|
||||
const { plane: selection, distance } = input
|
||||
const { plane: selection, distance, nodeToEdit } = input
|
||||
|
||||
let insertIndex: number | undefined = undefined
|
||||
let planeName: string | undefined = undefined
|
||||
|
||||
// If this is an edit flow, first we're going to remove the old plane
|
||||
if (nodeToEdit && typeof nodeToEdit[1][0] === 'number') {
|
||||
// Extract the plane name from the node to edit
|
||||
const planeNameNode = getNodeFromPath<VariableDeclaration>(
|
||||
ast,
|
||||
nodeToEdit,
|
||||
'VariableDeclaration'
|
||||
)
|
||||
if (err(planeNameNode)) {
|
||||
console.error('Error extracting plane name')
|
||||
} else {
|
||||
planeName = planeNameNode.node.declaration.id.name
|
||||
}
|
||||
|
||||
const newBody = [...ast.body]
|
||||
newBody.splice(nodeToEdit[1][0], 1)
|
||||
ast.body = newBody
|
||||
insertIndex = nodeToEdit[1][0]
|
||||
}
|
||||
|
||||
// Extract the default plane from selection
|
||||
const plane = selection.otherSelections[0]
|
||||
if (!(plane && plane instanceof Object && 'name' in plane))
|
||||
return trap('No plane selected')
|
||||
|
||||
// Insert the distance variable if it exists
|
||||
if (
|
||||
'variableName' in distance &&
|
||||
distance.variableName &&
|
||||
distance.insertIndex !== undefined
|
||||
) {
|
||||
const newBody = [...ast.body]
|
||||
newBody.splice(
|
||||
distance.insertIndex,
|
||||
0,
|
||||
distance.variableDeclarationAst
|
||||
)
|
||||
ast.body = newBody
|
||||
}
|
||||
|
||||
// Get the default plane name from the selection
|
||||
|
||||
const offsetPlaneResult = addOffsetPlane({
|
||||
node: ast,
|
||||
defaultPlane: plane.name,
|
||||
@ -1544,8 +1577,27 @@ export const modelingMachine = setup({
|
||||
'variableName' in distance
|
||||
? distance.variableIdentifierAst
|
||||
: distance.valueAst,
|
||||
insertIndex,
|
||||
planeName,
|
||||
})
|
||||
|
||||
// Insert the distance variable if the user has provided a variable name
|
||||
if (
|
||||
'variableName' in distance &&
|
||||
distance.variableName &&
|
||||
typeof offsetPlaneResult.pathToNode[1][0] === 'number'
|
||||
) {
|
||||
const insertIndex = Math.min(
|
||||
offsetPlaneResult.pathToNode[1][0],
|
||||
distance.insertIndex
|
||||
)
|
||||
const newBody = [...offsetPlaneResult.modifiedAst.body]
|
||||
newBody.splice(insertIndex, 0, distance.variableDeclarationAst)
|
||||
offsetPlaneResult.modifiedAst.body = newBody
|
||||
// Since we inserted a new variable, we need to update the path to the extrude argument
|
||||
offsetPlaneResult.pathToNode[1][0]++
|
||||
}
|
||||
|
||||
const updateAstResult = await kclManager.updateAst(
|
||||
offsetPlaneResult.modifiedAst,
|
||||
true,
|
||||
|
Reference in New Issue
Block a user