Assemblies: Set translate and rotate via point-and-click (#6167)
* WIP: Add point-and-click Import for geometry Will eventually fix #6120 Right now the whole loop is there but the codemod doesn't work yet * Better pathToNOde, log on non-working cm dispatch call * Add workaround to updateModelingState not working * Back to updateModelingState with a skip flag * Better todo * Change working from Import to Insert, cleanups * Sister command in kclCommands to populate file options * Improve path selector * Unsure: move importAstMod to kclCommands onSubmit 😶 * Add e2e test * Clean up for review * Add native file menu entry and test * No await yo lint said so * WIP: UX improvements around foreign file imports Fixes #6152 * WIP: Set translate and rotate via point-and-click on imports. Boilerplate code Will eventually close #6020 * Full working loop of rotate and translate pipe mutation, including edits, only on module imports. VERY VERBOSE * Add first e2e test for set transform. Bunch of caveats listed as TODOs * @lrev-Dev's suggestion to remove a comment Co-authored-by: Kurt Hutten <k.hutten@protonmail.ch> * Update to scene.settled(cmdBar) * Add partNNN default name for alias * Lint * Lint * Fix unit tests * Add sad path insert test Thanks @Irev-Dev for the suggestion * Add step insert test * Lint * Add test for second foreign import thru file tree click * WIP: Add point-and-click Load to copy files from outside the project into the project Towards #6210 * Move Insert button to modeling toolbar, update menus and toolbars * Add default value for local name alias * Aligning tests * Fix tests * Add padding for filenames starting with a digit * Lint * Lint * Update snapshots * Merge branch 'main' into pierremtb/issue6210-Add-point-and-click-Load-to-copy-files-from-outside-the-project-into-the-project * Add disabled transform subbutton * Allow start of Transform flow from toolbar with selection * Merge kcl-samples and local disk load into one 'Load external model' command * Fix em tests * Fix test * Add test for file pick import, better input * Fix non .kcl loading * Lint * Update snapshots * Fix issue leading to test failure * Fix clone test * Add note * Fix nested clone issue * Clean up for review * Add valueSummary for path * Fix test after path change * Clean up for review * Support much wider range for transform * Set display names * Bug fixed itself moment... * Add test for extrude tranform * Oops missed a thing * Clean up selection arg * More tests incl for variable stuff * Fix imports * Add supportsTransform: true on all solids returning operations * Fix edit flow on variables, add test * Split transform command into translate and rotate * Clean up and comment * Clean up operations.ts * Add comment * Improve assemblies test * Support more things * Typo * Fix test after unit change on import * Last clean up for review * Fix remaining test --------- Co-authored-by: Kurt Hutten <k.hutten@protonmail.ch>
This commit is contained in:
@ -52,6 +52,7 @@ import {
|
||||
deleteNodeInExtrudePipe,
|
||||
extrudeSketch,
|
||||
insertNamedConstant,
|
||||
insertVariableAndOffsetPathToNode,
|
||||
loftSketches,
|
||||
} from '@src/lang/modifyAst'
|
||||
import type {
|
||||
@ -72,17 +73,21 @@ import {
|
||||
applyIntersectFromTargetOperatorSelections,
|
||||
applySubtractFromTargetOperatorSelections,
|
||||
applyUnionFromTargetOperatorSelections,
|
||||
findAllChildrenAndOrderByPlaceInCode,
|
||||
getLastVariable,
|
||||
} from '@src/lang/modifyAst/boolean'
|
||||
import {
|
||||
deleteSelectionPromise,
|
||||
deletionErrorMessage,
|
||||
} from '@src/lang/modifyAst/deleteSelection'
|
||||
import { setAppearance } from '@src/lang/modifyAst/setAppearance'
|
||||
import { setTranslate, setRotate } from '@src/lang/modifyAst/setTransform'
|
||||
import {
|
||||
getNodeFromPath,
|
||||
isNodeSafeToReplacePath,
|
||||
stringifyPathToNode,
|
||||
updatePathToNodesAfterEdit,
|
||||
valueOrVariable,
|
||||
} from '@src/lang/queryAst'
|
||||
import { getNodePathFromSourceRange } from '@src/lang/queryAstNodePathUtils'
|
||||
import {
|
||||
@ -373,6 +378,8 @@ export type ModelingMachineEvent =
|
||||
data: ModelingCommandSchema['Delete selection']
|
||||
}
|
||||
| { type: 'Appearance'; data: ModelingCommandSchema['Appearance'] }
|
||||
| { type: 'Translate'; data: ModelingCommandSchema['Translate'] }
|
||||
| { type: 'Rotate'; data: ModelingCommandSchema['Rotate'] }
|
||||
| {
|
||||
type:
|
||||
| 'Add circle origin'
|
||||
@ -2031,12 +2038,6 @@ export const modelingMachine = setup({
|
||||
}
|
||||
}
|
||||
|
||||
const valueOrVariable = (variable: KclCommandValue) => {
|
||||
return 'variableName' in variable
|
||||
? variable.variableIdentifierAst
|
||||
: variable.valueAst
|
||||
}
|
||||
|
||||
const { modifiedAst, pathToNode } = addHelix({
|
||||
node: ast,
|
||||
revolutions: valueOrVariable(revolutions),
|
||||
@ -2651,6 +2652,120 @@ export const modelingMachine = setup({
|
||||
)
|
||||
}
|
||||
),
|
||||
translateAstMod: fromPromise(
|
||||
async ({
|
||||
input,
|
||||
}: {
|
||||
input: ModelingCommandSchema['Translate'] | undefined
|
||||
}) => {
|
||||
if (!input) return new Error('No input provided')
|
||||
const ast = kclManager.ast
|
||||
const modifiedAst = structuredClone(ast)
|
||||
const { x, y, z, nodeToEdit, selection } = input
|
||||
let pathToNode = nodeToEdit
|
||||
if (!(pathToNode && typeof pathToNode[1][0] === 'number')) {
|
||||
if (selection?.graphSelections[0].artifact) {
|
||||
const children = findAllChildrenAndOrderByPlaceInCode(
|
||||
selection?.graphSelections[0].artifact,
|
||||
kclManager.artifactGraph
|
||||
)
|
||||
const variable = getLastVariable(children, modifiedAst)
|
||||
if (!variable) {
|
||||
return new Error("Couldn't find corresponding path to node")
|
||||
}
|
||||
pathToNode = variable.pathToNode
|
||||
} else if (selection?.graphSelections[0].codeRef.pathToNode) {
|
||||
pathToNode = selection?.graphSelections[0].codeRef.pathToNode
|
||||
} else {
|
||||
return new Error("Couldn't find corresponding path to node")
|
||||
}
|
||||
}
|
||||
|
||||
insertVariableAndOffsetPathToNode(x, modifiedAst, pathToNode)
|
||||
insertVariableAndOffsetPathToNode(y, modifiedAst, pathToNode)
|
||||
insertVariableAndOffsetPathToNode(z, modifiedAst, pathToNode)
|
||||
const result = setTranslate({
|
||||
pathToNode,
|
||||
modifiedAst,
|
||||
x: valueOrVariable(x),
|
||||
y: valueOrVariable(y),
|
||||
z: valueOrVariable(z),
|
||||
})
|
||||
if (err(result)) {
|
||||
return err(result)
|
||||
}
|
||||
|
||||
await updateModelingState(
|
||||
result.modifiedAst,
|
||||
EXECUTION_TYPE_REAL,
|
||||
{
|
||||
kclManager,
|
||||
editorManager,
|
||||
codeManager,
|
||||
},
|
||||
{
|
||||
focusPath: [result.pathToNode],
|
||||
}
|
||||
)
|
||||
}
|
||||
),
|
||||
rotateAstMod: fromPromise(
|
||||
async ({
|
||||
input,
|
||||
}: {
|
||||
input: ModelingCommandSchema['Rotate'] | undefined
|
||||
}) => {
|
||||
if (!input) return new Error('No input provided')
|
||||
const ast = kclManager.ast
|
||||
const modifiedAst = structuredClone(ast)
|
||||
const { roll, pitch, yaw, nodeToEdit, selection } = input
|
||||
let pathToNode = nodeToEdit
|
||||
if (!(pathToNode && typeof pathToNode[1][0] === 'number')) {
|
||||
if (selection?.graphSelections[0].artifact) {
|
||||
const children = findAllChildrenAndOrderByPlaceInCode(
|
||||
selection?.graphSelections[0].artifact,
|
||||
kclManager.artifactGraph
|
||||
)
|
||||
const variable = getLastVariable(children, modifiedAst)
|
||||
if (!variable) {
|
||||
return new Error("Couldn't find corresponding path to node")
|
||||
}
|
||||
pathToNode = variable.pathToNode
|
||||
} else if (selection?.graphSelections[0].codeRef.pathToNode) {
|
||||
pathToNode = selection?.graphSelections[0].codeRef.pathToNode
|
||||
} else {
|
||||
return new Error("Couldn't find corresponding path to node")
|
||||
}
|
||||
}
|
||||
|
||||
insertVariableAndOffsetPathToNode(roll, modifiedAst, pathToNode)
|
||||
insertVariableAndOffsetPathToNode(pitch, modifiedAst, pathToNode)
|
||||
insertVariableAndOffsetPathToNode(yaw, modifiedAst, pathToNode)
|
||||
const result = setRotate({
|
||||
pathToNode,
|
||||
modifiedAst,
|
||||
roll: valueOrVariable(roll),
|
||||
pitch: valueOrVariable(pitch),
|
||||
yaw: valueOrVariable(yaw),
|
||||
})
|
||||
if (err(result)) {
|
||||
return err(result)
|
||||
}
|
||||
|
||||
await updateModelingState(
|
||||
result.modifiedAst,
|
||||
EXECUTION_TYPE_REAL,
|
||||
{
|
||||
kclManager,
|
||||
editorManager,
|
||||
codeManager,
|
||||
},
|
||||
{
|
||||
focusPath: [result.pathToNode],
|
||||
}
|
||||
)
|
||||
}
|
||||
),
|
||||
exportFromEngine: fromPromise(
|
||||
async ({}: { input?: ModelingCommandSchema['Export'] }) => {
|
||||
return undefined as Error | undefined
|
||||
@ -2919,6 +3034,16 @@ export const modelingMachine = setup({
|
||||
reenter: true,
|
||||
},
|
||||
|
||||
Translate: {
|
||||
target: 'Applying translate',
|
||||
reenter: true,
|
||||
},
|
||||
|
||||
Rotate: {
|
||||
target: 'Applying rotate',
|
||||
reenter: true,
|
||||
},
|
||||
|
||||
'Boolean Subtract': 'Boolean subtracting',
|
||||
'Boolean Union': 'Boolean uniting',
|
||||
'Boolean Intersect': 'Boolean intersecting',
|
||||
@ -4325,6 +4450,32 @@ export const modelingMachine = setup({
|
||||
},
|
||||
},
|
||||
|
||||
'Applying translate': {
|
||||
invoke: {
|
||||
src: 'translateAstMod',
|
||||
id: 'translateAstMod',
|
||||
input: ({ event }) => {
|
||||
if (event.type !== 'Translate') return undefined
|
||||
return event.data
|
||||
},
|
||||
onDone: ['idle'],
|
||||
onError: ['idle'],
|
||||
},
|
||||
},
|
||||
|
||||
'Applying rotate': {
|
||||
invoke: {
|
||||
src: 'rotateAstMod',
|
||||
id: 'rotateAstMod',
|
||||
input: ({ event }) => {
|
||||
if (event.type !== 'Rotate') return undefined
|
||||
return event.data
|
||||
},
|
||||
onDone: ['idle'],
|
||||
onError: ['idle'],
|
||||
},
|
||||
},
|
||||
|
||||
Exporting: {
|
||||
invoke: {
|
||||
src: 'exportFromEngine',
|
||||
|
Reference in New Issue
Block a user