diff --git a/src/components/ModelingSidebar/ModelingPanes/FeatureTreePane.tsx b/src/components/ModelingSidebar/ModelingPanes/FeatureTreePane.tsx index 9a29f50d6..99bc23527 100644 --- a/src/components/ModelingSidebar/ModelingPanes/FeatureTreePane.tsx +++ b/src/components/ModelingSidebar/ModelingPanes/FeatureTreePane.tsx @@ -64,13 +64,28 @@ export const FeatureTreePane = () => { scrollToError: () => { editorManager.scrollToFirstErrorDiagnosticIfExists() }, - sendTranslateCommand: ({ context }) => { + sendTranslateCommand: () => { commandBarActor.send({ type: 'Find and select command', - data: { - name: 'Translate', - groupId: 'modeling', - }, + data: { name: 'Translate', groupId: 'modeling' }, + }) + }, + sendRotateCommand: () => { + commandBarActor.send({ + type: 'Find and select command', + data: { name: 'Rotate', groupId: 'modeling' }, + }) + }, + sendScaleCommand: () => { + commandBarActor.send({ + type: 'Find and select command', + data: { name: 'Scale', groupId: 'modeling' }, + }) + }, + sendCloneCommand: () => { + commandBarActor.send({ + type: 'Find and select command', + data: { name: 'Clone', groupId: 'modeling' }, }) }, sendSelectionEvent: ({ context }) => { @@ -537,7 +552,7 @@ const OperationItem = (props: { !stdLibMap[props.item.name]?.supportsTransform } > - Set translate + Translate , - Set rotate + Rotate , - Set scale + Scale , - geometryName: string - variableName: string -}): { modifiedAst: Node; pathToNode: PathToNode } { - const modifiedAst = structuredClone(ast) - const variable = createVariableDeclaration( - variableName, - createCallExpressionStdLibKw('clone', createLocalName(geometryName), []) - ) - - modifiedAst.body.push(variable) - const insertAt = modifiedAst.body.length - 1 - const pathToNode: PathToNode = [ - ['body', ''], - [insertAt, 'index'], - ['declaration', 'VariableDeclaration'], - ['init', 'VariableDeclarator'], - ] - - return { - modifiedAst, - pathToNode, - } -} - /** * Return a modified clone of an AST with a named constant inserted into the body */ @@ -1252,7 +1219,8 @@ export function setCallInAst( ast: Node, call: Node, nodeToEdit?: PathToNode, - lastPathToNode?: PathToNode + lastPathToNode?: PathToNode, + toFirstKwarg?: boolean ): Error | PathToNode { let pathToNode: PathToNode | undefined if (nodeToEdit) { @@ -1283,7 +1251,7 @@ export function setCallInAst( const name = findUniqueName(ast, call.callee.name.name) const declaration = createVariableDeclaration(name, call) ast.body.push(declaration) - pathToNode = createPathToNodeForLastVariable(ast) + pathToNode = createPathToNodeForLastVariable(ast, toFirstKwarg) } } diff --git a/src/lang/modifyAst/transforms.ts b/src/lang/modifyAst/transforms.ts index 3f4d8584c..ccee81046 100644 --- a/src/lang/modifyAst/transforms.ts +++ b/src/lang/modifyAst/transforms.ts @@ -11,10 +11,6 @@ import { } from '@src/lang/queryAst' import type { ArtifactGraph, PathToNode, Program } from '@src/lang/wasm' import { err } from '@src/lib/trap' -import { - findAllChildrenAndOrderByPlaceInCode, - getLastVariable, -} from '@src/lang/modifyAst/boolean' import type { Selections } from '@src/lib/selections' import type { KclCommandValue } from '@src/lib/commandTypes' import { @@ -208,33 +204,53 @@ export function addScale({ }) } -export function retrievePathToNodeFromTransformSelection( - selection: Selections, - artifactGraph: ArtifactGraph, +export function addClone({ + ast, + artifactGraph, + objects, + nodeToEdit, +}: { ast: Node -): PathToNode | Error { - const error = new Error( - "Couldn't retrieve selection. If you're trying to transform an import, use the feature tree." - ) - const hasPathToNode = !!selection.graphSelections[0].codeRef.pathToNode.length - const artifact = selection.graphSelections[0].artifact - let pathToNode: PathToNode | undefined - if (hasPathToNode && artifact) { - const children = findAllChildrenAndOrderByPlaceInCode( - artifact, - artifactGraph - ) - const variable = getLastVariable(children, ast) - if (!variable) { - return error - } + artifactGraph: ArtifactGraph + objects: Selections + nodeToEdit?: PathToNode +}): Error | { modifiedAst: Node; pathToNode: PathToNode } { + // 1. Clone the ast so we can edit it + const modifiedAst = structuredClone(ast) - pathToNode = variable.pathToNode - } else if (hasPathToNode) { - pathToNode = selection.graphSelections[0].codeRef.pathToNode - } else { - return error + // 2. Prepare unlabeled arguments + // Map the sketches selection into a list of kcl expressions to be passed as unlabelled argument + const variableExpressions = getVariableExprsFromSelection( + objects, + modifiedAst, + nodeToEdit, + true, + artifactGraph + ) + if (err(variableExpressions)) { + return variableExpressions } - return pathToNode + const objectsExpr = createVariableExpressionsArray(variableExpressions.exprs) + const call = createCallExpressionStdLibKw('clone', objectsExpr, []) + + // 3. If edit, we assign the new function call declaration to the existing node, + // otherwise just push to the end + const lastPath = variableExpressions.paths.pop() // TODO: check if this is correct + const toFirstKwarg = false + const pathToNode = setCallInAst( + modifiedAst, + call, + nodeToEdit, + lastPath, + toFirstKwarg + ) + if (err(pathToNode)) { + return pathToNode + } + + return { + modifiedAst, + pathToNode, + } } diff --git a/src/lib/commandBarConfigs/modelingCommandConfig.ts b/src/lib/commandBarConfigs/modelingCommandConfig.ts index a8744a485..ea7c225a4 100644 --- a/src/lib/commandBarConfigs/modelingCommandConfig.ts +++ b/src/lib/commandBarConfigs/modelingCommandConfig.ts @@ -1,7 +1,6 @@ import type { Models } from '@kittycad/lib' import { angleLengthInfo } from '@src/components/Toolbar/angleLengthInfo' -import { findUniqueName } from '@src/lang/create' import { getNodeFromPath } from '@src/lang/queryAst' import { getVariableDeclaration } from '@src/lang/queryAst/getVariableDeclaration' import { getNodePathFromSourceRange } from '@src/lang/queryAstNodePathUtils' @@ -19,7 +18,6 @@ import type { } from '@src/lib/commandTypes' import { IS_ML_EXPERIMENTAL, - KCL_DEFAULT_CONSTANT_PREFIXES, KCL_DEFAULT_DEGREE, KCL_DEFAULT_LENGTH, KCL_DEFAULT_TRANSFORM, @@ -210,8 +208,7 @@ export type ModelingCommandSchema = { } Clone: { nodeToEdit?: PathToNode - selection: Selections - variableName: string + objects: Selections } 'Boolean Subtract': { solids: Selections @@ -1211,39 +1208,14 @@ export const modelingMachineCommandConfig: StateMachineCommandSetConfig< nodeToEdit: { ...nodeToEditProps, }, - selection: { + objects: { // selectionMixed allows for feature tree selection of module imports inputType: 'selectionMixed', - multiple: false, - required: true, - skip: true, - selectionTypes: ['path'], + selectionTypes: ['path', 'sweep'], selectionFilter: ['object'], - hidden: (context) => Boolean(context.argumentsToSubmit.nodeToEdit), - }, - variableName: { - inputType: 'string', + multiple: true, required: true, - defaultValue: () => { - return findUniqueName( - kclManager.ast, - KCL_DEFAULT_CONSTANT_PREFIXES.CLONE - ) - }, - validation: async ({ - data, - }: { - data: string - }) => { - // Be conservative and error out if there is an item or module with the same name. - const variableExists = - kclManager.variables[data] || kclManager.variables['__mod_' + data] - if (variableExists) { - return 'This variable name is already in use.' - } - - return true - }, + hidden: (context) => Boolean(context.argumentsToSubmit.nodeToEdit), }, }, }, diff --git a/src/lib/kclHelpers.ts b/src/lib/kclHelpers.ts index aaec329c8..a62fd7573 100644 --- a/src/lib/kclHelpers.ts +++ b/src/lib/kclHelpers.ts @@ -1,11 +1,6 @@ import { executeAstMock } from '@src/lang/langHelpers' -import { - type CallExpressionKw, - formatNumberValue, - parse, - resultIsOk, -} from '@src/lang/wasm' -import type { KclCommandValue, KclExpression } from '@src/lib/commandTypes' +import { formatNumberValue, parse, resultIsOk } from '@src/lang/wasm' +import type { KclExpression } from '@src/lib/commandTypes' import { rustContext } from '@src/lib/singletons' import { err } from '@src/lib/trap' diff --git a/src/lib/operations.ts b/src/lib/operations.ts index b07fc061b..147a0d89a 100644 --- a/src/lib/operations.ts +++ b/src/lib/operations.ts @@ -1525,11 +1525,10 @@ async function prepareToEditTranslate({ operation }: EnterEditFlowProps) { name: 'Translate', groupId: 'modeling', } - const isModuleImport = operation.type === 'GroupBegin' const isSupportedStdLibCall = operation.type === 'StdLibCall' && stdLibMap[operation.name]?.supportsTransform - if (!isModuleImport && !isSupportedStdLibCall) { + if (!isSupportedStdLibCall) { return { reason: 'Unsupported operation type. Please edit in the code editor.', } @@ -1549,53 +1548,51 @@ async function prepareToEditTranslate({ operation }: EnterEditFlowProps) { let y: KclCommandValue | undefined = undefined let z: KclCommandValue | undefined = undefined let global: boolean | undefined - if (isSupportedStdLibCall) { - if (operation.labeledArgs.x) { - const result = await stringToKclExpression( - codeManager.code.slice( - operation.labeledArgs.x.sourceRange[0], - operation.labeledArgs.x.sourceRange[1] - ) + if (operation.labeledArgs.x) { + const result = await stringToKclExpression( + codeManager.code.slice( + operation.labeledArgs.x.sourceRange[0], + operation.labeledArgs.x.sourceRange[1] ) - if (err(result) || 'errors' in result) { - return { reason: "Couldn't retrieve x argument" } - } - x = result + ) + if (err(result) || 'errors' in result) { + return { reason: "Couldn't retrieve x argument" } } + x = result + } - if (operation.labeledArgs.y) { - const result = await stringToKclExpression( - codeManager.code.slice( - operation.labeledArgs.y.sourceRange[0], - operation.labeledArgs.y.sourceRange[1] - ) + if (operation.labeledArgs.y) { + const result = await stringToKclExpression( + codeManager.code.slice( + operation.labeledArgs.y.sourceRange[0], + operation.labeledArgs.y.sourceRange[1] ) - if (err(result) || 'errors' in result) { - return { reason: "Couldn't retrieve y argument" } - } - y = result + ) + if (err(result) || 'errors' in result) { + return { reason: "Couldn't retrieve y argument" } } + y = result + } - if (operation.labeledArgs.z) { - const result = await stringToKclExpression( - codeManager.code.slice( - operation.labeledArgs.z.sourceRange[0], - operation.labeledArgs.z.sourceRange[1] - ) + if (operation.labeledArgs.z) { + const result = await stringToKclExpression( + codeManager.code.slice( + operation.labeledArgs.z.sourceRange[0], + operation.labeledArgs.z.sourceRange[1] ) - if (err(result) || 'errors' in result) { - return { reason: "Couldn't retrieve z argument" } - } - z = result + ) + if (err(result) || 'errors' in result) { + return { reason: "Couldn't retrieve z argument" } } + z = result + } - if (operation.labeledArgs.global) { - global = - codeManager.code.slice( - operation.labeledArgs.global.sourceRange[0], - operation.labeledArgs.global.sourceRange[1] - ) === 'true' - } + if (operation.labeledArgs.global) { + global = + codeManager.code.slice( + operation.labeledArgs.global.sourceRange[0], + operation.labeledArgs.global.sourceRange[1] + ) === 'true' } // 3. Assemble the default argument values for the command, @@ -1615,30 +1612,15 @@ async function prepareToEditTranslate({ operation }: EnterEditFlowProps) { } } -export async function enterTranslateFlow({ - operation, -}: EnterEditFlowProps): Promise { - const data = await prepareToEditTranslate({ operation }) - if ('reason' in data) { - return new Error(data.reason) - } - - return { - type: 'Find and select command', - data, - } -} - async function prepareToEditScale({ operation }: EnterEditFlowProps) { const baseCommand = { name: 'Scale', groupId: 'modeling', } - const isModuleImport = operation.type === 'GroupBegin' const isSupportedStdLibCall = operation.type === 'StdLibCall' && stdLibMap[operation.name]?.supportsTransform - if (!isModuleImport && !isSupportedStdLibCall) { + if (!isSupportedStdLibCall) { return { reason: 'Unsupported operation type. Please edit in the code editor.', } @@ -1658,53 +1640,51 @@ async function prepareToEditScale({ operation }: EnterEditFlowProps) { let y: KclCommandValue | undefined = undefined let z: KclCommandValue | undefined = undefined let global: boolean | undefined - if (isSupportedStdLibCall) { - if (operation.labeledArgs.x) { - const result = await stringToKclExpression( - codeManager.code.slice( - operation.labeledArgs.x.sourceRange[0], - operation.labeledArgs.x.sourceRange[1] - ) + if (operation.labeledArgs.x) { + const result = await stringToKclExpression( + codeManager.code.slice( + operation.labeledArgs.x.sourceRange[0], + operation.labeledArgs.x.sourceRange[1] ) - if (err(result) || 'errors' in result) { - return { reason: "Couldn't retrieve x argument" } - } - x = result + ) + if (err(result) || 'errors' in result) { + return { reason: "Couldn't retrieve x argument" } } + x = result + } - if (operation.labeledArgs.y) { - const result = await stringToKclExpression( - codeManager.code.slice( - operation.labeledArgs.y.sourceRange[0], - operation.labeledArgs.y.sourceRange[1] - ) + if (operation.labeledArgs.y) { + const result = await stringToKclExpression( + codeManager.code.slice( + operation.labeledArgs.y.sourceRange[0], + operation.labeledArgs.y.sourceRange[1] ) - if (err(result) || 'errors' in result) { - return { reason: "Couldn't retrieve y argument" } - } - y = result + ) + if (err(result) || 'errors' in result) { + return { reason: "Couldn't retrieve y argument" } } + y = result + } - if (operation.labeledArgs.z) { - const result = await stringToKclExpression( - codeManager.code.slice( - operation.labeledArgs.z.sourceRange[0], - operation.labeledArgs.z.sourceRange[1] - ) + if (operation.labeledArgs.z) { + const result = await stringToKclExpression( + codeManager.code.slice( + operation.labeledArgs.z.sourceRange[0], + operation.labeledArgs.z.sourceRange[1] ) - if (err(result) || 'errors' in result) { - return { reason: "Couldn't retrieve z argument" } - } - z = result + ) + if (err(result) || 'errors' in result) { + return { reason: "Couldn't retrieve z argument" } } + z = result + } - if (operation.labeledArgs.global) { - global = - codeManager.code.slice( - operation.labeledArgs.global.sourceRange[0], - operation.labeledArgs.global.sourceRange[1] - ) === 'true' - } + if (operation.labeledArgs.global) { + global = + codeManager.code.slice( + operation.labeledArgs.global.sourceRange[0], + operation.labeledArgs.global.sourceRange[1] + ) === 'true' } // 3. Assemble the default argument values for the command, @@ -1724,30 +1704,15 @@ async function prepareToEditScale({ operation }: EnterEditFlowProps) { } } -export async function enterScaleFlow({ - operation, -}: EnterEditFlowProps): Promise { - const data = await prepareToEditScale({ operation }) - if ('reason' in data) { - return new Error(data.reason) - } - - return { - type: 'Find and select command', - data, - } -} - async function prepareToEditRotate({ operation }: EnterEditFlowProps) { const baseCommand = { name: 'Rotate', groupId: 'modeling', } - const isModuleImport = operation.type === 'GroupBegin' const isSupportedStdLibCall = operation.type === 'StdLibCall' && stdLibMap[operation.name]?.supportsTransform - if (!isModuleImport && !isSupportedStdLibCall) { + if (!isSupportedStdLibCall) { return { reason: 'Unsupported operation type. Please edit in the code editor.', } @@ -1767,53 +1732,51 @@ async function prepareToEditRotate({ operation }: EnterEditFlowProps) { let pitch: KclCommandValue | undefined = undefined let yaw: KclCommandValue | undefined = undefined let global: boolean | undefined - if (isSupportedStdLibCall) { - if (operation.labeledArgs.roll) { - const result = await stringToKclExpression( - codeManager.code.slice( - operation.labeledArgs.roll.sourceRange[0], - operation.labeledArgs.roll.sourceRange[1] - ) + if (operation.labeledArgs.roll) { + const result = await stringToKclExpression( + codeManager.code.slice( + operation.labeledArgs.roll.sourceRange[0], + operation.labeledArgs.roll.sourceRange[1] ) - if (err(result) || 'errors' in result) { - return { reason: "Couldn't retrieve roll argument" } - } - roll = result + ) + if (err(result) || 'errors' in result) { + return { reason: "Couldn't retrieve roll argument" } } + roll = result + } - if (operation.labeledArgs.pitch) { - const result = await stringToKclExpression( - codeManager.code.slice( - operation.labeledArgs.pitch.sourceRange[0], - operation.labeledArgs.pitch.sourceRange[1] - ) + if (operation.labeledArgs.pitch) { + const result = await stringToKclExpression( + codeManager.code.slice( + operation.labeledArgs.pitch.sourceRange[0], + operation.labeledArgs.pitch.sourceRange[1] ) - if (err(result) || 'errors' in result) { - return { reason: "Couldn't retrieve pitch argument" } - } - pitch = result + ) + if (err(result) || 'errors' in result) { + return { reason: "Couldn't retrieve pitch argument" } } + pitch = result + } - if (operation.labeledArgs.yaw) { - const result = await stringToKclExpression( - codeManager.code.slice( - operation.labeledArgs.yaw.sourceRange[0], - operation.labeledArgs.yaw.sourceRange[1] - ) + if (operation.labeledArgs.yaw) { + const result = await stringToKclExpression( + codeManager.code.slice( + operation.labeledArgs.yaw.sourceRange[0], + operation.labeledArgs.yaw.sourceRange[1] ) - if (err(result) || 'errors' in result) { - return { reason: "Couldn't retrieve yaw argument" } - } - yaw = result + ) + if (err(result) || 'errors' in result) { + return { reason: "Couldn't retrieve yaw argument" } } + yaw = result + } - if (operation.labeledArgs.global) { - global = - codeManager.code.slice( - operation.labeledArgs.global.sourceRange[0], - operation.labeledArgs.global.sourceRange[1] - ) === 'true' - } + if (operation.labeledArgs.global) { + global = + codeManager.code.slice( + operation.labeledArgs.global.sourceRange[0], + operation.labeledArgs.global.sourceRange[1] + ) === 'true' } // 3. Assemble the default argument values for the command, @@ -1832,45 +1795,3 @@ async function prepareToEditRotate({ operation }: EnterEditFlowProps) { argDefaultValues, } } - -export async function enterRotateFlow({ - operation, -}: EnterEditFlowProps): Promise { - const data = await prepareToEditRotate({ operation }) - if ('reason' in data) { - return new Error(data.reason) - } - - return { - type: 'Find and select command', - data, - } -} - -export async function enterCloneFlow({ - operation, -}: EnterEditFlowProps): Promise { - const isModuleImport = operation.type === 'GroupBegin' - const isSupportedStdLibCall = - operation.type === 'StdLibCall' && - stdLibMap[operation.name]?.supportsTransform - if (!isModuleImport && !isSupportedStdLibCall) { - return new Error( - 'Unsupported operation type. Please edit in the code editor.' - ) - } - - const nodeToEdit = pathToNodeFromRustNodePath(operation.nodePath) - - // Won't be used since we provide nodeToEdit - const selection: Selections = { graphSelections: [], otherSelections: [] } - const argDefaultValues = { nodeToEdit, selection } - return { - type: 'Find and select command', - data: { - name: 'Clone', - groupId: 'modeling', - argDefaultValues, - }, - } -} diff --git a/src/machines/featureTreeMachine.ts b/src/machines/featureTreeMachine.ts index 42f17ce1b..0320c9207 100644 --- a/src/machines/featureTreeMachine.ts +++ b/src/machines/featureTreeMachine.ts @@ -12,14 +12,7 @@ import type { Artifact } from '@src/lang/std/artifactGraph' import { getArtifactFromRange } from '@src/lang/std/artifactGraph' import type { SourceRange } from '@src/lang/wasm' import type { EnterEditFlowProps } from '@src/lib/operations' -import { - enterAppearanceFlow, - enterCloneFlow, - enterEditFlow, - enterTranslateFlow, - enterRotateFlow, - enterScaleFlow, -} from '@src/lib/operations' +import { enterAppearanceFlow, enterEditFlow } from '@src/lib/operations' import { kclManager } from '@src/lib/singletons' import { err } from '@src/lib/trap' import { commandBarActor } from '@src/lib/singletons' @@ -131,98 +124,6 @@ export const featureTreeMachine = setup({ }) } ), - prepareTranslateCommand: fromPromise( - ({ - input, - }: { - input: EnterEditFlowProps & { - commandBarSend: (typeof commandBarActor)['send'] - } - }) => { - return new Promise((resolve, reject) => { - const { commandBarSend, ...editFlowProps } = input - enterTranslateFlow(editFlowProps) - .then((result) => { - if (err(result)) { - reject(result) - return - } - input.commandBarSend(result) - resolve(result) - }) - .catch(reject) - }) - } - ), - prepareRotateCommand: fromPromise( - ({ - input, - }: { - input: EnterEditFlowProps & { - commandBarSend: (typeof commandBarActor)['send'] - } - }) => { - return new Promise((resolve, reject) => { - const { commandBarSend, ...editFlowProps } = input - enterRotateFlow(editFlowProps) - .then((result) => { - if (err(result)) { - reject(result) - return - } - input.commandBarSend(result) - resolve(result) - }) - .catch(reject) - }) - } - ), - prepareScaleCommand: fromPromise( - ({ - input, - }: { - input: EnterEditFlowProps & { - commandBarSend: (typeof commandBarActor)['send'] - } - }) => { - return new Promise((resolve, reject) => { - const { commandBarSend, ...editFlowProps } = input - enterScaleFlow(editFlowProps) - .then((result) => { - if (err(result)) { - reject(result) - return - } - input.commandBarSend(result) - resolve(result) - }) - .catch(reject) - }) - } - ), - prepareCloneCommand: fromPromise( - ({ - input, - }: { - input: EnterEditFlowProps & { - commandBarSend: (typeof commandBarActor)['send'] - } - }) => { - return new Promise((resolve, reject) => { - const { commandBarSend, ...editFlowProps } = input - enterCloneFlow(editFlowProps) - .then((result) => { - if (err(result)) { - reject(result) - return - } - input.commandBarSend(result) - resolve(result) - }) - .catch(reject) - }) - } - ), sendDeleteCommand: fromPromise( ({ input, @@ -281,6 +182,9 @@ export const featureTreeMachine = setup({ }), sendSelectionEvent: () => {}, sendTranslateCommand: () => {}, + sendRotateCommand: () => {}, + sendScaleCommand: () => {}, + sendCloneCommand: () => {}, openCodePane: () => {}, scrollToError: () => {}, }, @@ -313,7 +217,7 @@ export const featureTreeMachine = setup({ }, enterTranslateFlow: { - target: 'enteringTranslateFlow2', + target: 'enteringTranslateFlow', actions: [ 'saveTargetSourceRange', 'saveCurrentOperation', @@ -323,17 +227,29 @@ export const featureTreeMachine = setup({ enterRotateFlow: { target: 'enteringRotateFlow', - actions: ['saveTargetSourceRange', 'saveCurrentOperation'], + actions: [ + 'saveTargetSourceRange', + 'saveCurrentOperation', + 'sendSelectionEvent', + ], }, enterScaleFlow: { target: 'enteringScaleFlow', - actions: ['saveTargetSourceRange', 'saveCurrentOperation'], + actions: [ + 'saveTargetSourceRange', + 'saveCurrentOperation', + 'sendSelectionEvent', + ], }, enterCloneFlow: { target: 'enteringCloneFlow', - actions: ['saveTargetSourceRange', 'saveCurrentOperation'], + actions: [ + 'saveTargetSourceRange', + 'saveCurrentOperation', + 'sendSelectionEvent', + ], }, deleteOperation: { @@ -393,9 +309,9 @@ export const featureTreeMachine = setup({ initial: 'selecting', }, - enteringTranslateFlow2: { + enteringTranslateFlow: { states: { - enteringTranslateFlow2: { + enteringTranslateFlow: { on: { selected: 'done', }, @@ -409,7 +325,64 @@ export const featureTreeMachine = setup({ }, }, - initial: 'enteringTranslateFlow2', + initial: 'enteringTranslateFlow', + }, + + enteringRotateFlow: { + states: { + enteringRotateFlow: { + on: { + selected: 'done', + }, + + entry: 'sendRotateCommand', + }, + + done: { + always: '#featureTree.idle', + entry: 'clearContext', + }, + }, + + initial: 'enteringRotateFlow', + }, + + enteringScaleFlow: { + states: { + enteringScaleFlow: { + on: { + selected: 'done', + }, + + entry: 'sendScaleCommand', + }, + + done: { + always: '#featureTree.idle', + entry: 'clearContext', + }, + }, + + initial: 'enteringScaleFlow', + }, + + enteringCloneFlow: { + states: { + enteringCloneFlow: { + on: { + selected: 'done', + }, + + entry: 'sendCloneCommand', + }, + + done: { + always: '#featureTree.idle', + entry: 'clearContext', + }, + }, + + initial: 'enteringCloneFlow', }, enteringEditFlow: { @@ -520,222 +493,6 @@ export const featureTreeMachine = setup({ exit: ['clearContext'], }, - enteringTranslateFlow: { - states: { - selecting: { - on: { - selected: { - target: 'prepareTranslateCommand', - reenter: true, - }, - }, - }, - - done: { - always: '#featureTree.idle', - }, - - prepareTranslateCommand: { - invoke: { - src: 'prepareTranslateCommand', - input: ({ context }) => { - const artifact = context.targetSourceRange - ? (getArtifactFromRange( - context.targetSourceRange, - kclManager.artifactGraph - ) ?? undefined) - : undefined - return { - // currentOperation is guaranteed to be defined here - operation: context.currentOperation!, - artifact, - commandBarSend: commandBarActor.send, - } - }, - onDone: { - target: 'done', - reenter: true, - }, - onError: { - target: 'done', - reenter: true, - actions: ({ event }) => { - if ('error' in event && err(event.error)) { - toast.error(event.error.message) - } - }, - }, - }, - }, - }, - - initial: 'selecting', - entry: 'sendSelectionEvent', - exit: ['clearContext'], - }, - - enteringRotateFlow: { - states: { - selecting: { - on: { - selected: { - target: 'prepareRotateCommand', - reenter: true, - }, - }, - }, - - done: { - always: '#featureTree.idle', - }, - - prepareRotateCommand: { - invoke: { - src: 'prepareRotateCommand', - input: ({ context }) => { - const artifact = context.targetSourceRange - ? (getArtifactFromRange( - context.targetSourceRange, - kclManager.artifactGraph - ) ?? undefined) - : undefined - return { - // currentOperation is guaranteed to be defined here - operation: context.currentOperation!, - artifact, - commandBarSend: commandBarActor.send, - } - }, - onDone: { - target: 'done', - reenter: true, - }, - onError: { - target: 'done', - reenter: true, - actions: ({ event }) => { - if ('error' in event && err(event.error)) { - toast.error(event.error.message) - } - }, - }, - }, - }, - }, - - initial: 'selecting', - entry: 'sendSelectionEvent', - exit: ['clearContext'], - }, - - enteringScaleFlow: { - states: { - selecting: { - on: { - selected: { - target: 'prepareScaleCommand', - reenter: true, - }, - }, - }, - - done: { - always: '#featureTree.idle', - }, - - prepareScaleCommand: { - invoke: { - src: 'prepareScaleCommand', - input: ({ context }) => { - const artifact = context.targetSourceRange - ? (getArtifactFromRange( - context.targetSourceRange, - kclManager.artifactGraph - ) ?? undefined) - : undefined - return { - // currentOperation is guaranteed to be defined here - operation: context.currentOperation!, - artifact, - commandBarSend: commandBarActor.send, - } - }, - onDone: { - target: 'done', - reenter: true, - }, - onError: { - target: 'done', - reenter: true, - actions: ({ event }) => { - if ('error' in event && err(event.error)) { - toast.error(event.error.message) - } - }, - }, - }, - }, - }, - - initial: 'selecting', - entry: 'sendSelectionEvent', - exit: ['clearContext'], - }, - - enteringCloneFlow: { - states: { - selecting: { - on: { - selected: { - target: 'prepareCloneCommand', - reenter: true, - }, - }, - }, - - done: { - always: '#featureTree.idle', - }, - - prepareCloneCommand: { - invoke: { - src: 'prepareCloneCommand', - input: ({ context }) => { - const artifact = context.targetSourceRange - ? (getArtifactFromRange( - context.targetSourceRange, - kclManager.artifactGraph - ) ?? undefined) - : undefined - return { - // currentOperation is guaranteed to be defined here - operation: context.currentOperation!, - artifact, - commandBarSend: commandBarActor.send, - } - }, - onDone: { - target: 'done', - reenter: true, - }, - onError: { - target: 'done', - reenter: true, - actions: ({ event }) => { - if ('error' in event && err(event.error)) { - toast.error(event.error.message) - } - }, - }, - }, - }, - }, - - initial: 'selecting', - entry: 'sendSelectionEvent', - exit: ['clearContext'], - }, - deletingOperation: { states: { selecting: { diff --git a/src/machines/modelingMachine.ts b/src/machines/modelingMachine.ts index 710b53d33..eedfcd5af 100644 --- a/src/machines/modelingMachine.ts +++ b/src/machines/modelingMachine.ts @@ -47,7 +47,6 @@ import { angleLengthInfo } from '@src/components/Toolbar/angleLengthInfo' import { createLiteral, createLocalName } from '@src/lang/create' import { updateModelingState } from '@src/lang/modelingWorkflows' import { - addClone, addHelix, addOffsetPlane, addShell, @@ -86,7 +85,7 @@ import { addTranslate, addRotate, addScale, - retrievePathToNodeFromTransformSelection, + addClone, } from '@src/lang/modifyAst/transforms' import { getNodeFromPath, @@ -112,7 +111,6 @@ import type { Literal, Name, PathToNode, - PipeExpression, Program, VariableDeclaration, VariableDeclarator, @@ -140,7 +138,6 @@ import { import type { ToolbarModeName } from '@src/lib/toolbar' import { err, reportRejection, trap } from '@src/lib/trap' import { uuidv4 } from '@src/lib/utils' -import type { ImportStatement } from '@rust/kcl-lib/bindings/ImportStatement' import { isDesktop } from '@src/lib/isDesktop' import { crossProduct, @@ -3420,58 +3417,14 @@ export const modelingMachine = setup({ } const ast = kclManager.ast - const { nodeToEdit, selection, variableName } = input - let pathToNode = nodeToEdit - if (!(pathToNode && typeof pathToNode[1][0] === 'number')) { - const result = retrievePathToNodeFromTransformSelection( - selection, - kclManager.artifactGraph, - ast - ) - if (err(result)) { - return Promise.reject(result) - } - - pathToNode = result - } - - const returnEarly = true - const geometryNode = getNodeFromPath< - VariableDeclaration | ImportStatement | PipeExpression - >( - ast, - pathToNode, - ['VariableDeclaration', 'ImportStatement', 'PipeExpression'], - returnEarly - ) - if (err(geometryNode)) { - return Promise.reject( - new Error("Couldn't find corresponding path to node") - ) - } - - let geometryName: string | undefined - if (geometryNode.node.type === 'VariableDeclaration') { - geometryName = geometryNode.node.declaration.id.name - } else if ( - geometryNode.node.type === 'ImportStatement' && - geometryNode.node.selector.type === 'None' && - geometryNode.node.selector.alias - ) { - geometryName = geometryNode.node.selector.alias?.name - } else { - return Promise.reject( - new Error("Couldn't find corresponding geometry") - ) - } - + const artifactGraph = kclManager.artifactGraph const result = addClone({ + ...input, ast, - geometryName, - variableName, + artifactGraph, }) if (err(result)) { - return Promise.reject(err(result)) + return Promise.reject(result) } await updateModelingState(