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:
Pierre Jacquier
2025-04-17 11:44:31 -04:00
committed by GitHub
parent 056a4d4a22
commit 6f2d127c4f
17 changed files with 1496 additions and 48 deletions

View File

@ -12,7 +12,12 @@ 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, enterEditFlow } from '@src/lib/operations'
import {
enterAppearanceFlow,
enterEditFlow,
enterTranslateFlow,
enterRotateFlow,
} from '@src/lib/operations'
import { kclManager } from '@src/lib/singletons'
import { err } from '@src/lib/trap'
import { commandBarActor } from '@src/machines/commandBarMachine'
@ -38,6 +43,14 @@ type FeatureTreeEvent =
type: 'enterAppearanceFlow'
data: { targetSourceRange: SourceRange; currentOperation: Operation }
}
| {
type: 'enterTranslateFlow'
data: { targetSourceRange: SourceRange; currentOperation: Operation }
}
| {
type: 'enterRotateFlow'
data: { targetSourceRange: SourceRange; currentOperation: Operation }
}
| { type: 'goToError' }
| { type: 'codePaneOpened' }
| { type: 'selected' }
@ -108,6 +121,52 @@ 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)
})
}
),
sendDeleteCommand: fromPromise(
({
input,
@ -198,6 +257,16 @@ export const featureTreeMachine = setup({
actions: ['saveTargetSourceRange', 'saveCurrentOperation'],
},
enterTranslateFlow: {
target: 'enteringTranslateFlow',
actions: ['saveTargetSourceRange', 'saveCurrentOperation'],
},
enterRotateFlow: {
target: 'enteringRotateFlow',
actions: ['saveTargetSourceRange', 'saveCurrentOperation'],
},
deleteOperation: {
target: 'deletingOperation',
actions: ['saveTargetSourceRange'],
@ -363,6 +432,114 @@ 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'],
},
deletingOperation: {
states: {
selecting: {