WIP: global optional arg for all point-and-click transforms and add Scale
Closes #7615 and #7634
This commit is contained in:
@ -409,6 +409,18 @@ const OperationItem = (props: {
|
||||
}
|
||||
}
|
||||
|
||||
function enterScaleFlow() {
|
||||
if (props.item.type === 'StdLibCall' || props.item.type === 'GroupBegin') {
|
||||
props.send({
|
||||
type: 'enterScaleFlow',
|
||||
data: {
|
||||
targetSourceRange: sourceRangeFromRust(props.item.sourceRange),
|
||||
currentOperation: props.item,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function enterCloneFlow() {
|
||||
if (props.item.type === 'StdLibCall' || props.item.type === 'GroupBegin') {
|
||||
props.send({
|
||||
@ -527,6 +539,16 @@ const OperationItem = (props: {
|
||||
>
|
||||
Set rotate
|
||||
</ContextMenuItem>,
|
||||
<ContextMenuItem
|
||||
onClick={enterScaleFlow}
|
||||
data-testid="context-menu-set-scale"
|
||||
disabled={
|
||||
props.item.type !== 'GroupBegin' &&
|
||||
!stdLibMap[props.item.name]?.supportsTransform
|
||||
}
|
||||
>
|
||||
Set scale
|
||||
</ContextMenuItem>,
|
||||
<ContextMenuItem
|
||||
onClick={enterCloneFlow}
|
||||
data-testid="context-menu-clone"
|
||||
|
||||
@ -4,6 +4,7 @@ import {
|
||||
createCallExpressionStdLibKw,
|
||||
createExpressionStatement,
|
||||
createLabeledArg,
|
||||
createLiteral,
|
||||
createLocalName,
|
||||
createPipeExpression,
|
||||
} from '@src/lang/create'
|
||||
@ -31,18 +32,25 @@ export function setTranslate({
|
||||
x,
|
||||
y,
|
||||
z,
|
||||
global,
|
||||
}: {
|
||||
modifiedAst: Node<Program>
|
||||
pathToNode: PathToNode
|
||||
x: Expr
|
||||
y: Expr
|
||||
z: Expr
|
||||
global?: boolean
|
||||
}): Error | { modifiedAst: Node<Program>; pathToNode: PathToNode } {
|
||||
// Extra labeled args expression
|
||||
const globalExpr = global
|
||||
? [createLabeledArg('global', createLiteral(global))]
|
||||
: []
|
||||
const noPercentSign = null
|
||||
const call = createCallExpressionStdLibKw('translate', noPercentSign, [
|
||||
createLabeledArg('x', x),
|
||||
createLabeledArg('y', y),
|
||||
createLabeledArg('z', z),
|
||||
...globalExpr,
|
||||
])
|
||||
|
||||
const potentialPipe = getNodeFromPath<PipeExpression>(
|
||||
@ -71,18 +79,72 @@ export function setRotate({
|
||||
roll,
|
||||
pitch,
|
||||
yaw,
|
||||
global,
|
||||
}: {
|
||||
modifiedAst: Node<Program>
|
||||
pathToNode: PathToNode
|
||||
roll: Expr
|
||||
pitch: Expr
|
||||
yaw: Expr
|
||||
global?: boolean
|
||||
}): Error | { modifiedAst: Node<Program>; pathToNode: PathToNode } {
|
||||
// Extra labeled args expression
|
||||
const globalExpr = global
|
||||
? [createLabeledArg('global', createLiteral(global))]
|
||||
: []
|
||||
const noPercentSign = null
|
||||
const call = createCallExpressionStdLibKw('rotate', noPercentSign, [
|
||||
createLabeledArg('roll', roll),
|
||||
createLabeledArg('pitch', pitch),
|
||||
createLabeledArg('yaw', yaw),
|
||||
...globalExpr,
|
||||
])
|
||||
|
||||
const potentialPipe = getNodeFromPath<PipeExpression>(
|
||||
modifiedAst,
|
||||
pathToNode,
|
||||
['PipeExpression']
|
||||
)
|
||||
if (!err(potentialPipe) && potentialPipe.node.type === 'PipeExpression') {
|
||||
setTransformInPipe(potentialPipe.node, call)
|
||||
} else {
|
||||
const error = createPipeWithTransform(modifiedAst, pathToNode, call)
|
||||
if (err(error)) {
|
||||
return error
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
modifiedAst,
|
||||
pathToNode,
|
||||
}
|
||||
}
|
||||
|
||||
export function setScale({
|
||||
modifiedAst,
|
||||
pathToNode,
|
||||
x,
|
||||
y,
|
||||
z,
|
||||
global,
|
||||
}: {
|
||||
modifiedAst: Node<Program>
|
||||
pathToNode: PathToNode
|
||||
x: Expr
|
||||
y: Expr
|
||||
z: Expr
|
||||
global?: boolean
|
||||
}): Error | { modifiedAst: Node<Program>; pathToNode: PathToNode } {
|
||||
// Extra labeled args expression
|
||||
const globalExpr = global
|
||||
? [createLabeledArg('global', createLiteral(global))]
|
||||
: []
|
||||
const noPercentSign = null
|
||||
const call = createCallExpressionStdLibKw('scale', noPercentSign, [
|
||||
createLabeledArg('x', x),
|
||||
createLabeledArg('y', y),
|
||||
createLabeledArg('z', z),
|
||||
...globalExpr,
|
||||
])
|
||||
|
||||
const potentialPipe = getNodeFromPath<PipeExpression>(
|
||||
|
||||
@ -190,6 +190,7 @@ export type ModelingCommandSchema = {
|
||||
x: KclCommandValue
|
||||
y: KclCommandValue
|
||||
z: KclCommandValue
|
||||
global?: boolean
|
||||
}
|
||||
Rotate: {
|
||||
nodeToEdit?: PathToNode
|
||||
@ -197,6 +198,15 @@ export type ModelingCommandSchema = {
|
||||
roll: KclCommandValue
|
||||
pitch: KclCommandValue
|
||||
yaw: KclCommandValue
|
||||
global?: boolean
|
||||
}
|
||||
Scale: {
|
||||
nodeToEdit?: PathToNode
|
||||
selection: Selections
|
||||
x: KclCommandValue
|
||||
y: KclCommandValue
|
||||
z: KclCommandValue
|
||||
global?: boolean
|
||||
}
|
||||
Clone: {
|
||||
nodeToEdit?: PathToNode
|
||||
@ -750,14 +760,8 @@ export const modelingMachineCommandConfig: StateMachineCommandSetConfig<
|
||||
required: false,
|
||||
displayName: 'CounterClockWise',
|
||||
options: [
|
||||
{
|
||||
name: 'False',
|
||||
value: false,
|
||||
},
|
||||
{
|
||||
name: 'True',
|
||||
value: true,
|
||||
},
|
||||
{ name: 'False', value: false },
|
||||
{ name: 'True', value: true },
|
||||
],
|
||||
},
|
||||
},
|
||||
@ -1104,6 +1108,14 @@ export const modelingMachineCommandConfig: StateMachineCommandSetConfig<
|
||||
defaultValue: KCL_DEFAULT_TRANSFORM,
|
||||
required: true,
|
||||
},
|
||||
global: {
|
||||
inputType: 'options',
|
||||
required: false,
|
||||
options: [
|
||||
{ name: 'False', value: false },
|
||||
{ name: 'True', value: true },
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
Rotate: {
|
||||
@ -1139,6 +1151,57 @@ export const modelingMachineCommandConfig: StateMachineCommandSetConfig<
|
||||
defaultValue: KCL_DEFAULT_TRANSFORM,
|
||||
required: true,
|
||||
},
|
||||
global: {
|
||||
inputType: 'options',
|
||||
required: false,
|
||||
options: [
|
||||
{ name: 'False', value: false },
|
||||
{ name: 'True', value: true },
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
Scale: {
|
||||
description: 'Set scale on solid or sketch.',
|
||||
icon: 'scale',
|
||||
needsReview: true,
|
||||
args: {
|
||||
nodeToEdit: {
|
||||
...nodeToEditProps,
|
||||
},
|
||||
selection: {
|
||||
// selectionMixed allows for feature tree selection of module imports
|
||||
inputType: 'selectionMixed',
|
||||
multiple: false,
|
||||
required: true,
|
||||
skip: true,
|
||||
selectionTypes: ['path'],
|
||||
selectionFilter: ['object'],
|
||||
hidden: (context) => Boolean(context.argumentsToSubmit.nodeToEdit),
|
||||
},
|
||||
x: {
|
||||
inputType: 'kcl',
|
||||
defaultValue: KCL_DEFAULT_TRANSFORM,
|
||||
required: true,
|
||||
},
|
||||
y: {
|
||||
inputType: 'kcl',
|
||||
defaultValue: KCL_DEFAULT_TRANSFORM,
|
||||
required: true,
|
||||
},
|
||||
z: {
|
||||
inputType: 'kcl',
|
||||
defaultValue: KCL_DEFAULT_TRANSFORM,
|
||||
required: true,
|
||||
},
|
||||
global: {
|
||||
inputType: 'options',
|
||||
required: false,
|
||||
options: [
|
||||
{ name: 'False', value: false },
|
||||
{ name: 'True', value: true },
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
Clone: {
|
||||
|
||||
@ -1179,6 +1179,8 @@ export const stdLibMap: Record<string, StdLibCallInfo> = {
|
||||
scale: {
|
||||
label: 'Scale',
|
||||
icon: 'scale',
|
||||
prepareToEdit: prepareToEditScale,
|
||||
supportsTransform: true,
|
||||
},
|
||||
shell: {
|
||||
label: 'Shell',
|
||||
@ -1540,6 +1542,7 @@ async function prepareToEditTranslate({ operation }: EnterEditFlowProps) {
|
||||
let x: KclExpression | undefined = undefined
|
||||
let y: KclExpression | undefined = undefined
|
||||
let z: KclExpression | undefined = undefined
|
||||
let global: boolean | undefined
|
||||
const pipeLookupFromOperation = getNodeFromPath<PipeExpression>(
|
||||
kclManager.ast,
|
||||
nodeToEdit,
|
||||
@ -1566,12 +1569,21 @@ async function prepareToEditTranslate({ operation }: EnterEditFlowProps) {
|
||||
x = await retrieveArgFromPipedCallExpression(translate, 'x')
|
||||
y = await retrieveArgFromPipedCallExpression(translate, 'y')
|
||||
z = await retrieveArgFromPipedCallExpression(translate, 'z')
|
||||
|
||||
// optional global argument
|
||||
const result = await retrieveArgFromPipedCallExpression(
|
||||
translate,
|
||||
'global'
|
||||
)
|
||||
if (result) {
|
||||
global = result.valueText === 'true'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Won't be used since we provide nodeToEdit
|
||||
const selection: Selections = { graphSelections: [], otherSelections: [] }
|
||||
const argDefaultValues = { nodeToEdit, selection, x, y, z }
|
||||
const argDefaultValues = { nodeToEdit, selection, x, y, z, global }
|
||||
return {
|
||||
...baseCommand,
|
||||
argDefaultValues,
|
||||
@ -1592,6 +1604,84 @@ export async function enterTranslateFlow({
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
return {
|
||||
reason: 'Unsupported operation type. Please edit in the code editor.',
|
||||
}
|
||||
}
|
||||
|
||||
const nodeToEdit = pathToNodeFromRustNodePath(operation.nodePath)
|
||||
let x: KclExpression | undefined = undefined
|
||||
let y: KclExpression | undefined = undefined
|
||||
let z: KclExpression | undefined = undefined
|
||||
let global: boolean | undefined
|
||||
const pipeLookupFromOperation = getNodeFromPath<PipeExpression>(
|
||||
kclManager.ast,
|
||||
nodeToEdit,
|
||||
'PipeExpression'
|
||||
)
|
||||
let pipe: PipeExpression | undefined
|
||||
const ast = kclManager.ast
|
||||
if (
|
||||
err(pipeLookupFromOperation) ||
|
||||
pipeLookupFromOperation.node.type !== 'PipeExpression'
|
||||
) {
|
||||
// Look for the last pipe with the import alias and a call to scale
|
||||
const pipes = findPipesWithImportAlias(ast, nodeToEdit, 'scale')
|
||||
pipe = pipes.at(-1)?.expression
|
||||
} else {
|
||||
pipe = pipeLookupFromOperation.node
|
||||
}
|
||||
|
||||
if (pipe) {
|
||||
const scale = pipe.body.find(
|
||||
(n) => n.type === 'CallExpressionKw' && n.callee.name.name === 'scale'
|
||||
)
|
||||
if (scale?.type === 'CallExpressionKw') {
|
||||
x = await retrieveArgFromPipedCallExpression(scale, 'x')
|
||||
y = await retrieveArgFromPipedCallExpression(scale, 'y')
|
||||
z = await retrieveArgFromPipedCallExpression(scale, 'z')
|
||||
|
||||
// optional global argument
|
||||
const result = await retrieveArgFromPipedCallExpression(scale, 'global')
|
||||
if (result) {
|
||||
global = result.valueText === 'true'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Won't be used since we provide nodeToEdit
|
||||
const selection: Selections = { graphSelections: [], otherSelections: [] }
|
||||
const argDefaultValues = { nodeToEdit, selection, x, y, z, global }
|
||||
return {
|
||||
...baseCommand,
|
||||
argDefaultValues,
|
||||
}
|
||||
}
|
||||
|
||||
export async function enterScaleFlow({
|
||||
operation,
|
||||
}: EnterEditFlowProps): Promise<Error | CommandBarMachineEvent> {
|
||||
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',
|
||||
|
||||
@ -432,6 +432,24 @@ export const toolbarConfig: Record<ToolbarModeName, ToolbarMode> = {
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'scale',
|
||||
onClick: () =>
|
||||
commandBarActor.send({
|
||||
type: 'Find and select command',
|
||||
data: { name: 'Scale', groupId: 'modeling' },
|
||||
}),
|
||||
icon: 'scale',
|
||||
status: 'available',
|
||||
title: 'Scale',
|
||||
description: 'Apply scaling to a solid or sketch.',
|
||||
links: [
|
||||
{
|
||||
label: 'API docs',
|
||||
url: 'https://zoo.dev/docs/kcl-std/functions/std-transform-scale',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'clone',
|
||||
onClick: () =>
|
||||
|
||||
@ -18,6 +18,7 @@ import {
|
||||
enterEditFlow,
|
||||
enterTranslateFlow,
|
||||
enterRotateFlow,
|
||||
enterScaleFlow,
|
||||
} from '@src/lib/operations'
|
||||
import { kclManager } from '@src/lib/singletons'
|
||||
import { err } from '@src/lib/trap'
|
||||
@ -52,6 +53,10 @@ type FeatureTreeEvent =
|
||||
type: 'enterRotateFlow'
|
||||
data: { targetSourceRange: SourceRange; currentOperation: Operation }
|
||||
}
|
||||
| {
|
||||
type: 'enterScaleFlow'
|
||||
data: { targetSourceRange: SourceRange; currentOperation: Operation }
|
||||
}
|
||||
| {
|
||||
type: 'enterCloneFlow'
|
||||
data: { targetSourceRange: SourceRange; currentOperation: Operation }
|
||||
@ -172,6 +177,29 @@ export const featureTreeMachine = setup({
|
||||
})
|
||||
}
|
||||
),
|
||||
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,
|
||||
@ -293,6 +321,11 @@ export const featureTreeMachine = setup({
|
||||
actions: ['saveTargetSourceRange', 'saveCurrentOperation'],
|
||||
},
|
||||
|
||||
enterScaleFlow: {
|
||||
target: 'enteringScaleFlow',
|
||||
actions: ['saveTargetSourceRange', 'saveCurrentOperation'],
|
||||
},
|
||||
|
||||
enterCloneFlow: {
|
||||
target: 'enteringCloneFlow',
|
||||
actions: ['saveTargetSourceRange', 'saveCurrentOperation'],
|
||||
@ -571,6 +604,60 @@ export const featureTreeMachine = setup({
|
||||
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: {
|
||||
|
||||
@ -88,6 +88,7 @@ import {
|
||||
setRotate,
|
||||
insertExpressionNode,
|
||||
retrievePathToNodeFromTransformSelection,
|
||||
setScale,
|
||||
} from '@src/lang/modifyAst/setTransform'
|
||||
import {
|
||||
getNodeFromPath,
|
||||
@ -403,6 +404,7 @@ export type ModelingMachineEvent =
|
||||
| { type: 'Appearance'; data: ModelingCommandSchema['Appearance'] }
|
||||
| { type: 'Translate'; data: ModelingCommandSchema['Translate'] }
|
||||
| { type: 'Rotate'; data: ModelingCommandSchema['Rotate'] }
|
||||
| { type: 'Scale'; data: ModelingCommandSchema['Scale'] }
|
||||
| { type: 'Clone'; data: ModelingCommandSchema['Clone'] }
|
||||
| {
|
||||
type:
|
||||
@ -3318,7 +3320,7 @@ export const modelingMachine = setup({
|
||||
|
||||
const ast = kclManager.ast
|
||||
const modifiedAst = structuredClone(ast)
|
||||
const { x, y, z, nodeToEdit, selection } = input
|
||||
const { x, y, z, global, nodeToEdit, selection } = input
|
||||
let pathToNode = nodeToEdit
|
||||
if (!(pathToNode && typeof pathToNode[1][0] === 'number')) {
|
||||
const result = retrievePathToNodeFromTransformSelection(
|
||||
@ -3368,6 +3370,7 @@ export const modelingMachine = setup({
|
||||
x: valueOrVariable(x),
|
||||
y: valueOrVariable(y),
|
||||
z: valueOrVariable(z),
|
||||
global,
|
||||
})
|
||||
if (err(result)) {
|
||||
return Promise.reject(result)
|
||||
@ -3399,7 +3402,7 @@ export const modelingMachine = setup({
|
||||
|
||||
const ast = kclManager.ast
|
||||
const modifiedAst = structuredClone(ast)
|
||||
const { roll, pitch, yaw, nodeToEdit, selection } = input
|
||||
const { roll, pitch, yaw, global, nodeToEdit, selection } = input
|
||||
let pathToNode = nodeToEdit
|
||||
if (!(pathToNode && typeof pathToNode[1][0] === 'number')) {
|
||||
const result = retrievePathToNodeFromTransformSelection(
|
||||
@ -3449,6 +3452,89 @@ export const modelingMachine = setup({
|
||||
roll: valueOrVariable(roll),
|
||||
pitch: valueOrVariable(pitch),
|
||||
yaw: valueOrVariable(yaw),
|
||||
global,
|
||||
})
|
||||
if (err(result)) {
|
||||
return Promise.reject(result)
|
||||
}
|
||||
|
||||
await updateModelingState(
|
||||
result.modifiedAst,
|
||||
EXECUTION_TYPE_REAL,
|
||||
{
|
||||
kclManager,
|
||||
editorManager,
|
||||
codeManager,
|
||||
},
|
||||
{
|
||||
focusPath: [result.pathToNode],
|
||||
}
|
||||
)
|
||||
}
|
||||
),
|
||||
scaleAstMod: fromPromise(
|
||||
async ({
|
||||
input,
|
||||
}: {
|
||||
input: ModelingCommandSchema['Scale'] | undefined
|
||||
}) => {
|
||||
if (!input) {
|
||||
return Promise.reject(new Error(NO_INPUT_PROVIDED_MESSAGE))
|
||||
}
|
||||
|
||||
const ast = kclManager.ast
|
||||
const modifiedAst = structuredClone(ast)
|
||||
const { x, y, z, global, nodeToEdit, selection } = 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
|
||||
}
|
||||
|
||||
// Look for the last pipe with the import alias and a call to translate, with a fallback to rotate.
|
||||
// Otherwise create one
|
||||
const importNodeAndAlias = findImportNodeAndAlias(ast, pathToNode)
|
||||
if (importNodeAndAlias) {
|
||||
const pipes = findPipesWithImportAlias(ast, pathToNode, 'translate')
|
||||
const lastPipe = pipes.at(-1)
|
||||
if (lastPipe && lastPipe.pathToNode) {
|
||||
pathToNode = lastPipe.pathToNode
|
||||
} else {
|
||||
const otherRelevantPipes = findPipesWithImportAlias(
|
||||
ast,
|
||||
pathToNode,
|
||||
'rotate'
|
||||
)
|
||||
const lastRelevantPipe = otherRelevantPipes.at(-1)
|
||||
if (lastRelevantPipe && lastRelevantPipe.pathToNode) {
|
||||
pathToNode = lastRelevantPipe.pathToNode
|
||||
} else {
|
||||
pathToNode = insertExpressionNode(
|
||||
modifiedAst,
|
||||
importNodeAndAlias.alias
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
insertVariableAndOffsetPathToNode(x, modifiedAst, pathToNode)
|
||||
insertVariableAndOffsetPathToNode(y, modifiedAst, pathToNode)
|
||||
insertVariableAndOffsetPathToNode(z, modifiedAst, pathToNode)
|
||||
const result = setScale({
|
||||
pathToNode,
|
||||
modifiedAst,
|
||||
x: valueOrVariable(x),
|
||||
y: valueOrVariable(y),
|
||||
z: valueOrVariable(z),
|
||||
global,
|
||||
})
|
||||
if (err(result)) {
|
||||
return Promise.reject(result)
|
||||
@ -3863,6 +3949,12 @@ export const modelingMachine = setup({
|
||||
guard: 'no kcl errors',
|
||||
},
|
||||
|
||||
Scale: {
|
||||
target: 'Applying scale',
|
||||
reenter: true,
|
||||
guard: 'no kcl errors',
|
||||
},
|
||||
|
||||
Clone: {
|
||||
target: 'Applying clone',
|
||||
reenter: true,
|
||||
@ -5345,6 +5437,22 @@ export const modelingMachine = setup({
|
||||
},
|
||||
},
|
||||
|
||||
'Applying scale': {
|
||||
invoke: {
|
||||
src: 'scaleAstMod',
|
||||
id: 'scaleAstMod',
|
||||
input: ({ event }) => {
|
||||
if (event.type !== 'Scale') return undefined
|
||||
return event.data
|
||||
},
|
||||
onDone: ['idle'],
|
||||
onError: {
|
||||
target: 'idle',
|
||||
actions: 'toastError',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
'Applying clone': {
|
||||
invoke: {
|
||||
src: 'cloneAstMod',
|
||||
|
||||
Reference in New Issue
Block a user