Update from main, add proper error returns
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 75 KiB |
|
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 69 KiB |
|
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 68 KiB |
@ -405,7 +405,6 @@ const ToolbarItemTooltip = memo(function ToolbarItemContents({
|
||||
position="bottom"
|
||||
wrapperClassName={'!p-4 !pointer-events-auto ' + wrapperClassName}
|
||||
contentClassName={contentClassName}
|
||||
delay={0}
|
||||
>
|
||||
{children}
|
||||
</Tooltip>
|
||||
|
||||
@ -123,6 +123,8 @@ import { Node } from '@rust/kcl-lib/bindings/Node'
|
||||
import { radToDeg } from 'three/src/math/MathUtils'
|
||||
import toast from 'react-hot-toast'
|
||||
import { getArtifactFromRange, codeRefFromRange } from 'lang/std/artifactGraph'
|
||||
import { updateModelingState } from 'lang/modelingWorkflows'
|
||||
import { EXECUTION_TYPE_MOCK } from 'lib/constants'
|
||||
|
||||
type DraftSegment = 'line' | 'tangentialArcTo'
|
||||
|
||||
@ -1075,7 +1077,11 @@ export class SceneEntities {
|
||||
return
|
||||
}
|
||||
|
||||
await kclManager.executeAstMock(modifiedAst)
|
||||
await updateModelingState(modifiedAst, EXECUTION_TYPE_MOCK, {
|
||||
kclManager,
|
||||
editorManager,
|
||||
codeManager,
|
||||
})
|
||||
|
||||
if (intersectsProfileStart) {
|
||||
sceneInfra.modelingSend({ type: 'Close sketch' })
|
||||
@ -1090,8 +1096,6 @@ export class SceneEntities {
|
||||
segmentName
|
||||
)
|
||||
}
|
||||
|
||||
await codeManager.updateEditorWithAstAndWriteToFile(modifiedAst)
|
||||
},
|
||||
onMove: (args) => {
|
||||
const expressionIndex = Number(sketchEntryNodePath[1][0])
|
||||
@ -1303,13 +1307,16 @@ export class SceneEntities {
|
||||
_ast = pResult.program
|
||||
|
||||
// Update the primary AST and unequip the rectangle tool
|
||||
await kclManager.executeAstMock(_ast)
|
||||
sceneInfra.modelingSend({ type: 'Finish rectangle' })
|
||||
|
||||
//
|
||||
// lee: I had this at the bottom of the function, but it's
|
||||
// possible sketchFromKclValue "fails" when sketching on a face,
|
||||
// and this couldn't wouldn't run.
|
||||
await codeManager.updateEditorWithAstAndWriteToFile(_ast)
|
||||
await updateModelingState(_ast, EXECUTION_TYPE_MOCK, {
|
||||
kclManager,
|
||||
editorManager,
|
||||
codeManager,
|
||||
})
|
||||
sceneInfra.modelingSend({ type: 'Finish rectangle' })
|
||||
},
|
||||
})
|
||||
return {
|
||||
@ -1493,13 +1500,16 @@ export class SceneEntities {
|
||||
_ast = pResult.program
|
||||
|
||||
// Update the primary AST and unequip the rectangle tool
|
||||
await kclManager.executeAstMock(_ast)
|
||||
sceneInfra.modelingSend({ type: 'Finish center rectangle' })
|
||||
|
||||
//
|
||||
// lee: I had this at the bottom of the function, but it's
|
||||
// possible sketchFromKclValue "fails" when sketching on a face,
|
||||
// and this couldn't wouldn't run.
|
||||
await codeManager.updateEditorWithAstAndWriteToFile(_ast)
|
||||
await updateModelingState(_ast, EXECUTION_TYPE_MOCK, {
|
||||
kclManager,
|
||||
editorManager,
|
||||
codeManager,
|
||||
})
|
||||
sceneInfra.modelingSend({ type: 'Finish center rectangle' })
|
||||
}
|
||||
},
|
||||
})
|
||||
@ -1678,9 +1688,12 @@ export class SceneEntities {
|
||||
_ast = pResult.program
|
||||
|
||||
// Update the primary AST and unequip the rectangle tool
|
||||
await kclManager.executeAstMock(_ast)
|
||||
await updateModelingState(_ast, EXECUTION_TYPE_MOCK, {
|
||||
kclManager,
|
||||
editorManager,
|
||||
codeManager,
|
||||
})
|
||||
sceneInfra.modelingSend({ type: 'Finish circle three point' })
|
||||
await codeManager.updateEditorWithAstAndWriteToFile(_ast)
|
||||
}
|
||||
},
|
||||
})
|
||||
@ -1912,9 +1925,12 @@ export class SceneEntities {
|
||||
_ast = pResult.program
|
||||
|
||||
// Update the primary AST and unequip the arc tool
|
||||
await kclManager.executeAstMock(_ast)
|
||||
await updateModelingState(_ast, EXECUTION_TYPE_MOCK, {
|
||||
kclManager,
|
||||
editorManager,
|
||||
codeManager,
|
||||
})
|
||||
sceneInfra.modelingSend({ type: 'Finish arc' })
|
||||
await codeManager.updateEditorWithAstAndWriteToFile(_ast)
|
||||
}
|
||||
},
|
||||
})
|
||||
@ -2166,13 +2182,16 @@ export class SceneEntities {
|
||||
_ast = pResult.program
|
||||
|
||||
// Update the primary AST and unequip the arc tool
|
||||
await kclManager.executeAstMock(_ast)
|
||||
await updateModelingState(_ast, EXECUTION_TYPE_MOCK, {
|
||||
kclManager,
|
||||
editorManager,
|
||||
codeManager,
|
||||
})
|
||||
if (intersectsProfileStart) {
|
||||
sceneInfra.modelingSend({ type: 'Close sketch' })
|
||||
} else {
|
||||
sceneInfra.modelingSend({ type: 'Finish arc' })
|
||||
}
|
||||
await codeManager.updateEditorWithAstAndWriteToFile(_ast)
|
||||
}
|
||||
},
|
||||
})
|
||||
@ -2364,9 +2383,12 @@ export class SceneEntities {
|
||||
_ast = pResult.program
|
||||
|
||||
// Update the primary AST and unequip the rectangle tool
|
||||
await kclManager.executeAstMock(_ast)
|
||||
await updateModelingState(_ast, EXECUTION_TYPE_MOCK, {
|
||||
kclManager,
|
||||
editorManager,
|
||||
codeManager,
|
||||
})
|
||||
sceneInfra.modelingSend({ type: 'Finish circle' })
|
||||
await codeManager.updateEditorWithAstAndWriteToFile(_ast)
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
@ -48,7 +48,6 @@ export function ActionButtonDropdown({
|
||||
{props.name ? props.name + ': ' : ''}open menu
|
||||
</span>
|
||||
<Tooltip
|
||||
delay={0}
|
||||
position="bottom"
|
||||
hoverOnly
|
||||
wrapperClassName="ui-open:!hidden"
|
||||
|
||||
@ -136,7 +136,7 @@ export const CommandBar = () => {
|
||||
name="close"
|
||||
className="w-5 h-5 rounded-sm bg-destroy-10 text-destroy-80 dark:bg-destroy-80 dark:text-destroy-10 group-hover:brightness-110"
|
||||
/>
|
||||
<Tooltip position="bottom" delay={500}>
|
||||
<Tooltip position="bottom">
|
||||
Cancel{' '}
|
||||
<kbd className="hotkey ml-4 dark:!bg-chalkboard-80">esc</kbd>
|
||||
</Tooltip>
|
||||
@ -144,7 +144,7 @@ export const CommandBar = () => {
|
||||
{!commandBarState.matches('Selecting command') && (
|
||||
<button onClick={stepBack} className="m-0 p-0 border-none">
|
||||
<CustomIcon name="arrowLeft" className="w-5 h-5 rounded-sm" />
|
||||
<Tooltip position="bottom" delay={500}>
|
||||
<Tooltip position="bottom">
|
||||
Step back{' '}
|
||||
<kbd className="hotkey ml-4 dark:!bg-chalkboard-80">
|
||||
Shift
|
||||
|
||||
@ -547,9 +547,7 @@ export const FileTreeMenu = ({
|
||||
className="!p-0 !bg-transparent hover:text-primary border-transparent hover:border-primary !outline-none"
|
||||
onClick={onCreateFile}
|
||||
>
|
||||
<Tooltip position="bottom-right" delay={750}>
|
||||
Create file
|
||||
</Tooltip>
|
||||
<Tooltip position="bottom-right">Create file</Tooltip>
|
||||
</ActionButton>
|
||||
|
||||
<ActionButton
|
||||
@ -563,9 +561,7 @@ export const FileTreeMenu = ({
|
||||
className="!p-0 !bg-transparent hover:text-primary border-transparent hover:border-primary !outline-none"
|
||||
onClick={onCreateFolder}
|
||||
>
|
||||
<Tooltip position="bottom-right" delay={750}>
|
||||
Create folder
|
||||
</Tooltip>
|
||||
<Tooltip position="bottom-right">Create folder</Tooltip>
|
||||
</ActionButton>
|
||||
</>
|
||||
)
|
||||
|
||||
@ -119,6 +119,8 @@ import { EXPORT_TOAST_MESSAGES, MAKE_TOAST_MESSAGES } from 'lib/constants'
|
||||
import { exportMake } from 'lib/exportMake'
|
||||
import { exportSave } from 'lib/exportSave'
|
||||
import { Plane } from '@rust/kcl-lib/bindings/Plane'
|
||||
import { updateModelingState } from 'lang/modelingWorkflows'
|
||||
import { EXECUTION_TYPE_MOCK } from 'lib/constants'
|
||||
|
||||
export const ModelingMachineContext = createContext(
|
||||
{} as {
|
||||
@ -148,7 +150,6 @@ export const ModelingMachineProvider = ({
|
||||
enableSSAO,
|
||||
},
|
||||
} = useSettings()
|
||||
const previousAllowOrbitInSketchMode = useRef(allowOrbitInSketchMode.current)
|
||||
const navigate = useNavigate()
|
||||
const { context, send: fileMachineSend } = useFileContext()
|
||||
const { file } = useLoaderData() as IndexLoaderData
|
||||
@ -1661,7 +1662,7 @@ export const ModelingMachineProvider = ({
|
||||
sketchDetails.sketchEntryNodePath
|
||||
)
|
||||
if (err(doesNeedSplitting)) return reject(doesNeedSplitting)
|
||||
let moddedAst: Program = structuredClone(kclManager.ast)
|
||||
let moddedAst: Node<Program> = structuredClone(kclManager.ast)
|
||||
let pathToProfile = sketchDetails.sketchEntryNodePath
|
||||
let updatedSketchNodePaths = sketchDetails.sketchNodePaths
|
||||
if (doesNeedSplitting) {
|
||||
@ -1723,8 +1724,11 @@ export const ModelingMachineProvider = ({
|
||||
indexToDelete >= 0 ||
|
||||
isLastInPipeThreePointArc
|
||||
) {
|
||||
await kclManager.executeAstMock(moddedAst)
|
||||
await codeManager.updateEditorWithAstAndWriteToFile(moddedAst)
|
||||
await updateModelingState(moddedAst, EXECUTION_TYPE_MOCK, {
|
||||
kclManager,
|
||||
editorManager,
|
||||
codeManager,
|
||||
})
|
||||
}
|
||||
return {
|
||||
updatedEntryNodePath: pathToProfile,
|
||||
@ -1841,14 +1845,6 @@ export const ModelingMachineProvider = ({
|
||||
}, [engineCommandManager.engineConnection, modelingSend])
|
||||
|
||||
useEffect(() => {
|
||||
// Only trigger this if the state actually changes, if it stays the same do not reload the camera
|
||||
if (
|
||||
previousAllowOrbitInSketchMode.current === allowOrbitInSketchMode.current
|
||||
) {
|
||||
//no op
|
||||
previousAllowOrbitInSketchMode.current = allowOrbitInSketchMode.current
|
||||
return
|
||||
}
|
||||
const inSketchMode = modelingState.matches('Sketch')
|
||||
|
||||
// If you are in sketch mode and you disable the orbit, return back to the normal view to the target
|
||||
@ -1871,9 +1867,7 @@ export const ModelingMachineProvider = ({
|
||||
if (inSketchMode) {
|
||||
sceneInfra.camControls.enableRotate = allowOrbitInSketchMode.current
|
||||
}
|
||||
|
||||
previousAllowOrbitInSketchMode.current = allowOrbitInSketchMode.current
|
||||
}, [allowOrbitInSketchMode])
|
||||
}, [allowOrbitInSketchMode.current])
|
||||
|
||||
// Allow using the delete key to delete solids. Backspace only on macOS as Windows and Linux have dedicated Delete
|
||||
// `navigator.platform` is deprecated, but the alternative `navigator.userAgentData.platform` is not reliable
|
||||
|
||||
@ -51,9 +51,7 @@ export const ModelingPaneHeader = ({
|
||||
className="!p-0 !bg-transparent hover:text-primary border-transparent dark:!border-transparent hover:!border-primary dark:hover:!border-chalkboard-70 !outline-none"
|
||||
onClick={() => onClose()}
|
||||
>
|
||||
<Tooltip position="bottom-right" delay={750}>
|
||||
Close
|
||||
</Tooltip>
|
||||
<Tooltip position="bottom-right">Close</Tooltip>
|
||||
</ActionButton>
|
||||
</div>
|
||||
)
|
||||
|
||||
@ -40,9 +40,7 @@ export const MemoryPaneMenu = () => {
|
||||
className="!p-0 !bg-transparent hover:text-primary border-transparent hover:border-primary !outline-none"
|
||||
onClick={copyProgramMemoryToClipboard}
|
||||
>
|
||||
<Tooltip position="bottom-right" delay={750}>
|
||||
Copy to clipboard
|
||||
</Tooltip>
|
||||
<Tooltip position="bottom-right">Copy to clipboard</Tooltip>
|
||||
</ActionButton>
|
||||
</>
|
||||
)
|
||||
|
||||
@ -169,9 +169,7 @@ function ProjectCard({
|
||||
}}
|
||||
className="!p-0"
|
||||
>
|
||||
<Tooltip position="top-right" delay={1000}>
|
||||
Rename project
|
||||
</Tooltip>
|
||||
<Tooltip position="top-right">Rename project</Tooltip>
|
||||
</ActionButton>
|
||||
<ActionButton
|
||||
disabled={!project.readWriteAccess}
|
||||
@ -188,9 +186,7 @@ function ProjectCard({
|
||||
setIsConfirmingDelete(true)
|
||||
}}
|
||||
>
|
||||
<Tooltip position="top-right" delay={1000}>
|
||||
Delete project
|
||||
</Tooltip>
|
||||
<Tooltip position="top-right">Delete project</Tooltip>
|
||||
</ActionButton>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@ -43,9 +43,7 @@ export const ProjectCardRenameForm = forwardRef(
|
||||
}}
|
||||
className="!p-0"
|
||||
>
|
||||
<Tooltip position="left" delay={1000}>
|
||||
Rename project
|
||||
</Tooltip>
|
||||
<Tooltip position="left">Rename project</Tooltip>
|
||||
</ActionButton>
|
||||
<ActionButton
|
||||
Element="button"
|
||||
@ -57,9 +55,7 @@ export const ProjectCardRenameForm = forwardRef(
|
||||
className="!p-0"
|
||||
onClick={onDismiss}
|
||||
>
|
||||
<Tooltip position="left" delay={1000}>
|
||||
Cancel
|
||||
</Tooltip>
|
||||
<Tooltip position="left">Cancel</Tooltip>
|
||||
</ActionButton>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@ -24,7 +24,7 @@ export default function Tooltip({
|
||||
wrapperClassName: className,
|
||||
contentClassName,
|
||||
wrapperStyle = {},
|
||||
delay = 200,
|
||||
delay = 0,
|
||||
hoverOnly = false,
|
||||
inert = true,
|
||||
}: TooltipProps) {
|
||||
|
||||
@ -193,7 +193,7 @@ const UserSidebarMenu = ({ user }: { user?: User }) => {
|
||||
className="w-4 h-4 text-chalkboard-70 dark:text-chalkboard-40 ui-open:rotate-180"
|
||||
/>
|
||||
</div>
|
||||
<Tooltip position="bottom-right" delay={1000} hoverOnly>
|
||||
<Tooltip position="bottom-right" hoverOnly>
|
||||
User menu
|
||||
</Tooltip>
|
||||
</Popover.Button>
|
||||
|
||||
@ -2,12 +2,12 @@ import { executeAst, executeAstMock, lintAst } from 'lang/langHelpers'
|
||||
import { handleSelectionBatch, Selections } from 'lib/selections'
|
||||
import {
|
||||
KCLError,
|
||||
complilationErrorsToDiagnostics,
|
||||
compilationErrorsToDiagnostics,
|
||||
kclErrorsToDiagnostics,
|
||||
} from './errors'
|
||||
import { uuidv4 } from 'lib/utils'
|
||||
import { EngineCommandManager } from './std/engineConnection'
|
||||
import { err } from 'lib/trap'
|
||||
import { err, reportRejection } from 'lib/trap'
|
||||
import { EXECUTE_AST_INTERRUPT_ERROR_MESSAGE } from 'lib/constants'
|
||||
|
||||
import {
|
||||
@ -295,8 +295,8 @@ export class KclManager {
|
||||
this._astParseFailed = false
|
||||
|
||||
if (err(result)) {
|
||||
const kclerror: KCLError = result as KCLError
|
||||
this.diagnostics = kclErrorsToDiagnostics([kclerror])
|
||||
const kclError: KCLError = result as KCLError
|
||||
this.diagnostics = kclErrorsToDiagnostics([kclError])
|
||||
this._astParseFailed = true
|
||||
|
||||
await this.checkIfSwitchedFilesShouldClear()
|
||||
@ -310,8 +310,8 @@ export class KclManager {
|
||||
this._kclErrorsCallBack([])
|
||||
this._logsCallBack([])
|
||||
|
||||
this.addDiagnostics(complilationErrorsToDiagnostics(result.errors))
|
||||
this.addDiagnostics(complilationErrorsToDiagnostics(result.warnings))
|
||||
this.addDiagnostics(compilationErrorsToDiagnostics(result.errors))
|
||||
this.addDiagnostics(compilationErrorsToDiagnostics(result.warnings))
|
||||
if (result.errors.length > 0) {
|
||||
this._astParseFailed = true
|
||||
|
||||
@ -337,8 +337,8 @@ export class KclManager {
|
||||
private _cancelTokens: Map<number, boolean> = new Map()
|
||||
|
||||
// This NEVER updates the code, if you want to update the code DO NOT add to
|
||||
// this function, too many other things that don't want it exist.
|
||||
// just call to codeManager from wherever you want in other files.
|
||||
// this function, too many other things that don't want it exist. For that,
|
||||
// use updateModelingState().
|
||||
async executeAst(args: ExecuteArgs = {}): Promise<void> {
|
||||
if (this.isExecuting) {
|
||||
this.executeIsStale = args
|
||||
@ -420,7 +420,7 @@ export class KclManager {
|
||||
this.addDiagnostics(isInterrupted ? [] : kclErrorsToDiagnostics(errors))
|
||||
// Add warnings and non-fatal errors
|
||||
this.addDiagnostics(
|
||||
isInterrupted ? [] : complilationErrorsToDiagnostics(execState.errors)
|
||||
isInterrupted ? [] : compilationErrorsToDiagnostics(execState.errors)
|
||||
)
|
||||
this.execState = execState
|
||||
if (!errors.length) {
|
||||
@ -460,7 +460,6 @@ export class KclManager {
|
||||
markOnce('code/endExecuteAst')
|
||||
}
|
||||
|
||||
// NOTE: this always updates the code state and editor.
|
||||
// DO NOT CALL THIS from codemirror ever.
|
||||
async executeAstMock(ast: Program) {
|
||||
await this.ensureWasmInit()
|
||||
@ -472,7 +471,7 @@ export class KclManager {
|
||||
}
|
||||
const newAst = await this.safeParse(newCode)
|
||||
if (!newAst) {
|
||||
// By clearning the AST we indicate to our callers that there was an issue with execution and
|
||||
// By clearing the AST we indicate to our callers that there was an issue with execution and
|
||||
// the pre-execution state should be restored.
|
||||
this.clearAst()
|
||||
return
|
||||
@ -501,7 +500,7 @@ export class KclManager {
|
||||
const ast = await this.safeParse(codeManager.code)
|
||||
|
||||
if (!ast) {
|
||||
// By clearning the AST we indicate to our callers that there was an issue with execution and
|
||||
// By clearing the AST we indicate to our callers that there was an issue with execution and
|
||||
// the pre-execution state should be restored.
|
||||
this.clearAst()
|
||||
return
|
||||
@ -516,8 +515,8 @@ export class KclManager {
|
||||
* This will override the zoom to fit to zoom into the model if the previous AST was empty.
|
||||
* Workflows this improves,
|
||||
* When someone comments the entire file then uncomments the entire file it zooms to the model
|
||||
* When someone CRTL+A and deletes the code then adds the code back it zooms to the model
|
||||
* When someone CRTL+A and copies new code into the editor it zooms to the model
|
||||
* When someone CTRL+A and deletes the code then adds the code back it zooms to the model
|
||||
* When someone CTRL+A and copies new code into the editor it zooms to the model
|
||||
*/
|
||||
tryToZoomToFitOnCodeUpdate(
|
||||
ast: Node<Program>,
|
||||
@ -555,12 +554,16 @@ export class KclManager {
|
||||
codeManager.updateCodeStateEditor(code)
|
||||
|
||||
// Write back to the file system.
|
||||
void codeManager.writeToFile().then(() => this.executeCode())
|
||||
void codeManager
|
||||
.writeToFile()
|
||||
.then(() => this.executeCode())
|
||||
.catch(reportRejection)
|
||||
}
|
||||
|
||||
// There's overlapping responsibility between updateAst and executeAst.
|
||||
// updateAst was added as it was used a lot before xState migration so makes the port easier.
|
||||
// but should probably have think about which of the function to keep
|
||||
// This always updates the code state and editor and writes to the file system.
|
||||
// This never updates the code state or editor and doesn't write to the file system.
|
||||
async updateAst(
|
||||
ast: Node<Program>,
|
||||
execute: boolean,
|
||||
@ -627,7 +630,6 @@ export class KclManager {
|
||||
// When we don't re-execute, we still want to update the program
|
||||
// memory with the new ast. So we will hit the mock executor
|
||||
// instead..
|
||||
// Execute ast mock will update the code state and editor.
|
||||
await this.executeAstMock(astWithUpdatedSource)
|
||||
}
|
||||
|
||||
|
||||
@ -165,10 +165,11 @@ export default class CodeManager {
|
||||
}
|
||||
|
||||
async updateEditorWithAstAndWriteToFile(ast: Program) {
|
||||
// We clear the AST when there it cannot be parsed, so if we are trying to write an empty AST, its
|
||||
// probably because of an earlier error. That's a bad state to be in and it's not going to be
|
||||
// pretty, but at the least, lets not permanently delete the user's code.
|
||||
// If you want to clear the scene, call updateCodeStateEditor directly.
|
||||
// We clear the AST when it cannot be parsed. If we are trying to write an
|
||||
// empty AST, it's probably because of an earlier error. That's a bad state
|
||||
// to be in, and it's not going to be pretty, but at the least, let's not
|
||||
// permanently delete the user's code. If you want to clear the scene, call
|
||||
// updateCodeStateEditor directly.
|
||||
if (ast.body.length === 0) return
|
||||
const newCode = recast(ast)
|
||||
if (err(newCode)) return
|
||||
|
||||
@ -320,7 +320,7 @@ export function kclErrorsToDiagnostics(
|
||||
})
|
||||
}
|
||||
|
||||
export function complilationErrorsToDiagnostics(
|
||||
export function compilationErrorsToDiagnostics(
|
||||
errors: CompilationError[]
|
||||
): CodeMirrorDiagnostic[] {
|
||||
return errors
|
||||
|
||||
@ -8,6 +8,12 @@
|
||||
|
||||
import { Node } from '@rust/kcl-lib/bindings/Node'
|
||||
import { KclManager } from 'lang/KclSingleton'
|
||||
import { ExecutionType } from 'lib/constants'
|
||||
import {
|
||||
EXECUTION_TYPE_MOCK,
|
||||
EXECUTION_TYPE_NONE,
|
||||
EXECUTION_TYPE_REAL,
|
||||
} from 'lib/constants'
|
||||
import { PathToNode, Program, SourceRange } from 'lang/wasm'
|
||||
import EditorManager from 'editor/manager'
|
||||
import CodeManager from 'lang/codeManager'
|
||||
@ -32,12 +38,13 @@ import CodeManager from 'lang/codeManager'
|
||||
* regardless of geometric validity issues.
|
||||
*
|
||||
* @param ast - AST to commit
|
||||
* @param executionType - How to execute the AST
|
||||
* @param dependencies - Required system components
|
||||
* @param options - Optional parameters for focus, zoom, etc.
|
||||
*/
|
||||
|
||||
export async function updateModelingState(
|
||||
ast: Node<Program>,
|
||||
executionType: ExecutionType,
|
||||
dependencies: {
|
||||
kclManager: KclManager
|
||||
editorManager: EditorManager
|
||||
@ -55,6 +62,7 @@ export async function updateModelingState(
|
||||
// Step 1: Update AST without executing (prepare selections)
|
||||
const updatedAst = await dependencies.kclManager.updateAst(
|
||||
ast,
|
||||
// false == mock execution. Is this what we want?
|
||||
false, // Execution handled separately for error resilience
|
||||
options
|
||||
)
|
||||
@ -69,14 +77,20 @@ export async function updateModelingState(
|
||||
dependencies.editorManager.selectRange(updatedAst.selections)
|
||||
}
|
||||
|
||||
// Step 4: Try to execute the new code in the engine
|
||||
// Step 4: Try to execute the new code
|
||||
// and continue regardless of errors
|
||||
try {
|
||||
await dependencies.kclManager.executeAst({
|
||||
ast: updatedAst.newAst,
|
||||
zoomToFit: options?.zoomToFit,
|
||||
zoomOnRangeAndType: options?.zoomOnRangeAndType,
|
||||
})
|
||||
if (executionType === EXECUTION_TYPE_REAL) {
|
||||
await dependencies.kclManager.executeAst({
|
||||
ast: updatedAst.newAst,
|
||||
zoomToFit: options?.zoomToFit,
|
||||
zoomOnRangeAndType: options?.zoomOnRangeAndType,
|
||||
})
|
||||
} else if (executionType === EXECUTION_TYPE_MOCK) {
|
||||
await dependencies.kclManager.executeAstMock(updatedAst.newAst)
|
||||
} else if (executionType === EXECUTION_TYPE_NONE) {
|
||||
// No execution.
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Engine execution error (UI is still updated):', e)
|
||||
}
|
||||
|
||||
@ -673,7 +673,7 @@ export function sketchOnExtrudedFace(
|
||||
sketchPathToNode: PathToNode,
|
||||
extrudePathToNode: PathToNode,
|
||||
info: ExtrudeFacePlane['faceInfo'] = { type: 'wall' }
|
||||
): { modifiedAst: Program; pathToNode: PathToNode } | Error {
|
||||
): { modifiedAst: Node<Program>; pathToNode: PathToNode } | Error {
|
||||
let _node = { ...node }
|
||||
const newSketchName = findUniqueName(
|
||||
node,
|
||||
@ -1375,7 +1375,7 @@ export function moveValueIntoNewVariablePath(
|
||||
pathToNode: PathToNode,
|
||||
variableName: string
|
||||
): {
|
||||
modifiedAst: Program
|
||||
modifiedAst: Node<Program>
|
||||
pathToReplacedNode?: PathToNode
|
||||
} {
|
||||
const meta = isNodeSafeToReplacePath(ast, pathToNode)
|
||||
@ -1975,11 +1975,11 @@ making it safe for later code that uses part001 (the extrude in this example)
|
||||
*
|
||||
*/
|
||||
export function splitPipedProfile(
|
||||
ast: Program,
|
||||
ast: Node<Program>,
|
||||
pathToPipe: PathToNode
|
||||
):
|
||||
| {
|
||||
modifiedAst: Program
|
||||
modifiedAst: Node<Program>
|
||||
pathToProfile: PathToNode
|
||||
pathToPlane: PathToNode
|
||||
}
|
||||
|
||||
@ -39,6 +39,7 @@ import { Artifact, getSweepArtifactFromSelection } from 'lang/std/artifactGraph'
|
||||
import { Node } from '@rust/kcl-lib/bindings/Node'
|
||||
import { findKwArg } from 'lang/util'
|
||||
import { KclManager } from 'lang/KclSingleton'
|
||||
import { EXECUTION_TYPE_REAL } from 'lib/constants'
|
||||
import { EngineCommandManager } from 'lang/std/engineConnection'
|
||||
import EditorManager from 'editor/manager'
|
||||
import CodeManager from 'lang/codeManager'
|
||||
@ -86,6 +87,7 @@ export async function applyEdgeTreatmentToSelection(
|
||||
// 2. update ast
|
||||
await updateModelingState(
|
||||
modifiedAst,
|
||||
EXECUTION_TYPE_REAL,
|
||||
{
|
||||
kclManager: dependencies.kclManager,
|
||||
editorManager: dependencies.editorManager,
|
||||
|
||||
@ -3,12 +3,15 @@ import { getFaceDetails } from 'clientSideScene/sceneEntities'
|
||||
import { deleteFromSelection } from 'lang/modifyAst'
|
||||
import {
|
||||
codeManager,
|
||||
editorManager,
|
||||
engineCommandManager,
|
||||
kclManager,
|
||||
rustContext,
|
||||
} from 'lib/singletons'
|
||||
import { err } from 'lib/trap'
|
||||
import { executeAstMock } from 'lang/langHelpers'
|
||||
import { updateModelingState } from 'lang/modelingWorkflows'
|
||||
import { EXECUTION_TYPE_REAL } from 'lib/constants'
|
||||
|
||||
export const deletionErrorMessage =
|
||||
'Unable to delete selection. Please edit manually in code pane.'
|
||||
@ -36,7 +39,9 @@ export async function deleteSelectionPromise(
|
||||
if (testExecute.errors.length) {
|
||||
return new Error(deletionErrorMessage)
|
||||
}
|
||||
|
||||
await kclManager.updateAst(modifiedAst, true)
|
||||
await codeManager.updateEditorWithAstAndWriteToFile(modifiedAst)
|
||||
await updateModelingState(modifiedAst, EXECUTION_TYPE_REAL, {
|
||||
kclManager,
|
||||
editorManager,
|
||||
codeManager,
|
||||
})
|
||||
}
|
||||
|
||||
@ -167,3 +167,17 @@ export const ZOO_STUDIO_PROTOCOL = 'zoo-studio'
|
||||
* to "open in desktop app" when present in the URL
|
||||
*/
|
||||
export const ASK_TO_OPEN_QUERY_PARAM = 'ask-open-desktop'
|
||||
|
||||
/** Real execution. */
|
||||
export const EXECUTION_TYPE_REAL = 'real' as const
|
||||
/** Mock execution. */
|
||||
export const EXECUTION_TYPE_MOCK = 'mock' as const
|
||||
/** No execution. */
|
||||
export const EXECUTION_TYPE_NONE = 'none' as const
|
||||
/**
|
||||
* Enum of engine execution kinds.
|
||||
*/
|
||||
export type ExecutionType =
|
||||
| typeof EXECUTION_TYPE_REAL
|
||||
| typeof EXECUTION_TYPE_MOCK
|
||||
| typeof EXECUTION_TYPE_NONE
|
||||
|
||||
@ -28,52 +28,25 @@ sketch001 = startSketchOn(XZ)
|
||||
|> xLine(length = thickness, tag = $seg05)
|
||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $seg06)
|
||||
|> close()
|
||||
|> extrude(%, length = width)
|
||||
|> fillet(
|
||||
radius = extFilletRadius,
|
||||
tags = [getNextAdjacentEdge(seg03)],
|
||||
)
|
||||
|> fillet(
|
||||
radius = filletRadius,
|
||||
tags = [getNextAdjacentEdge(seg06)],
|
||||
)
|
||||
|> fillet(
|
||||
radius = filletRadius,
|
||||
tags = [seg02, getOppositeEdge(seg02)],
|
||||
)
|
||||
|> fillet(
|
||||
radius = filletRadius,
|
||||
tags = [seg05, getOppositeEdge(seg05)],
|
||||
)
|
||||
|
||||
sketch002 = startSketchOn(sketch001, seg03)
|
||||
|> circle(
|
||||
center = [-1.25, 1],
|
||||
radius = mountingHoleDiameter / 2,
|
||||
)
|
||||
|> patternLinear2d(
|
||||
instances = 2,
|
||||
distance = 2.5,
|
||||
axis = [-1, 0],
|
||||
)
|
||||
|> patternLinear2d(
|
||||
instances = 2,
|
||||
distance = 4,
|
||||
axis = [0, 1],
|
||||
)
|
||||
|> extrude(%, length = -thickness-.01)
|
||||
extrude001 = extrude(sketch001, length = width)
|
||||
|> fillet(radius = extFilletRadius, tags = [getNextAdjacentEdge(seg03)])
|
||||
|> fillet(radius = filletRadius, tags = [getNextAdjacentEdge(seg06)])
|
||||
|> fillet(radius = filletRadius, tags = [seg02, getOppositeEdge(seg02)])
|
||||
|> fillet(radius = filletRadius, tags = [seg05, getOppositeEdge(seg05)])
|
||||
|
||||
sketch003 = startSketchOn(sketch001, seg04)
|
||||
|> circle(
|
||||
center = [1, -1],
|
||||
radius = mountingHoleDiameter / 2,
|
||||
)
|
||||
|> patternLinear2d(
|
||||
instances = 2,
|
||||
distance = 4,
|
||||
axis = [1, 0],
|
||||
)
|
||||
|> extrude(%, length = -thickness-0.1)
|
||||
sketch002 = startSketchOn(extrude001, seg03)
|
||||
|> circle(center = [-1.25, 1], radius = mountingHoleDiameter / 2)
|
||||
|> patternLinear2d(instances = 2, distance = 2.5, axis = [-1, 0])
|
||||
|> patternLinear2d(instances = 2, distance = 4, axis = [0, 1])
|
||||
|
||||
extrude002 = extrude(sketch002, length = -thickness - .01)
|
||||
|
||||
sketch003 = startSketchOn(extrude002, seg04)
|
||||
|> circle(center = [1, -1], radius = mountingHoleDiameter / 2)
|
||||
|> patternLinear2d(instances = 2, distance = 4, axis = [1, 0])
|
||||
|
||||
extrude003 = extrude(sketch003, length = -thickness - 0.1)
|
||||
`
|
||||
|
||||
/**
|
||||
|
||||
@ -642,11 +642,11 @@ const prepareToEditRevolve: PrepareToEditCallback = async ({
|
||||
operation.type !== 'StdLibCall' ||
|
||||
!operation.labeledArgs
|
||||
) {
|
||||
return baseCommand
|
||||
return { reason: 'Wrong operation type or artifact' }
|
||||
}
|
||||
|
||||
// We have to go a little roundabout to get from the original artifact
|
||||
// to the solid2DId that we need to pass to the Extrude command.
|
||||
// to the solid2DId that we need to pass to the command.
|
||||
const pathArtifact = getArtifactOfTypes(
|
||||
{
|
||||
key: artifact.pathId,
|
||||
@ -658,8 +658,10 @@ const prepareToEditRevolve: PrepareToEditCallback = async ({
|
||||
err(pathArtifact) ||
|
||||
pathArtifact.type !== 'path' ||
|
||||
!pathArtifact.solid2dId
|
||||
)
|
||||
return baseCommand
|
||||
) {
|
||||
return { reason: "Couldn't find related path artifact" }
|
||||
}
|
||||
|
||||
const solid2DArtifact = getArtifactOfTypes(
|
||||
{
|
||||
key: pathArtifact.solid2dId,
|
||||
@ -668,7 +670,7 @@ const prepareToEditRevolve: PrepareToEditCallback = async ({
|
||||
engineCommandManager.artifactGraph
|
||||
)
|
||||
if (err(solid2DArtifact) || solid2DArtifact.type !== 'solid2d') {
|
||||
return baseCommand
|
||||
return { reason: "Couldn't find related solid2d artifact" }
|
||||
}
|
||||
|
||||
const selection = {
|
||||
@ -683,7 +685,7 @@ const prepareToEditRevolve: PrepareToEditCallback = async ({
|
||||
|
||||
// axis options string arg
|
||||
if (!('axis' in operation.labeledArgs) || !operation.labeledArgs.axis) {
|
||||
return baseCommand
|
||||
return { reason: "Couldn't find axis argument" }
|
||||
}
|
||||
|
||||
const axisValue = operation.labeledArgs.axis.value
|
||||
@ -705,7 +707,7 @@ const prepareToEditRevolve: PrepareToEditCallback = async ({
|
||||
engineCommandManager.artifactGraph
|
||||
)
|
||||
if (err(artifact)) {
|
||||
return baseCommand
|
||||
return { reason: "Couldn't find related edge artifact" }
|
||||
}
|
||||
|
||||
edge = {
|
||||
@ -728,7 +730,7 @@ const prepareToEditRevolve: PrepareToEditCallback = async ({
|
||||
engineCommandManager.artifactGraph
|
||||
)
|
||||
if (err(artifact)) {
|
||||
return baseCommand
|
||||
return { reason: "Couldn't find related edge artifact" }
|
||||
}
|
||||
|
||||
const codeRef = getSweepEdgeCodeRef(
|
||||
@ -736,7 +738,7 @@ const prepareToEditRevolve: PrepareToEditCallback = async ({
|
||||
engineCommandManager.artifactGraph
|
||||
)
|
||||
if (err(codeRef)) {
|
||||
return baseCommand
|
||||
return { reason: "Couldn't find related edge code ref" }
|
||||
}
|
||||
|
||||
edge = {
|
||||
@ -749,12 +751,12 @@ const prepareToEditRevolve: PrepareToEditCallback = async ({
|
||||
otherSelections: [],
|
||||
}
|
||||
} else {
|
||||
return baseCommand
|
||||
return { reason: 'The type of the axis argument is unsupported' }
|
||||
}
|
||||
|
||||
// angle kcl arg
|
||||
if (!('angle' in operation.labeledArgs) || !operation.labeledArgs.angle) {
|
||||
return baseCommand
|
||||
return { reason: "Couldn't find angle argument" }
|
||||
}
|
||||
const angle = await stringToKclExpression(
|
||||
codeManager.code.slice(
|
||||
@ -763,7 +765,7 @@ const prepareToEditRevolve: PrepareToEditCallback = async ({
|
||||
)
|
||||
)
|
||||
if (err(angle) || 'errors' in angle) {
|
||||
return baseCommand
|
||||
return { reason: 'Error in angle argument retrieval' }
|
||||
}
|
||||
|
||||
// Assemble the default argument values for the Offset Plane command,
|
||||
@ -780,8 +782,6 @@ const prepareToEditRevolve: PrepareToEditCallback = async ({
|
||||
sourceRangeFromRust(operation.sourceRange)
|
||||
),
|
||||
}
|
||||
console.log(argDefaultValues)
|
||||
|
||||
return {
|
||||
...baseCommand,
|
||||
argDefaultValues,
|
||||
|
||||
@ -102,6 +102,7 @@ import { setAppearance } from 'lang/modifyAst/setAppearance'
|
||||
import { DRAFT_DASHED_LINE } from 'clientSideScene/sceneEntities'
|
||||
import { Node } from '@rust/kcl-lib/bindings/Node'
|
||||
import { updateModelingState } from 'lang/modelingWorkflows'
|
||||
import { EXECUTION_TYPE_REAL } from 'lib/constants'
|
||||
|
||||
export const MODELING_PERSIST_KEY = 'MODELING_PERSIST_KEY'
|
||||
|
||||
@ -1744,20 +1745,23 @@ export const modelingMachine = setup({
|
||||
pathToExtrudeArg[1][0]++
|
||||
}
|
||||
|
||||
const updatedAst = await kclManager.updateAst(modifiedAst, true, {
|
||||
focusPath: [pathToExtrudeArg],
|
||||
zoomToFit: true,
|
||||
zoomOnRangeAndType: {
|
||||
range: selection.graphSelections[0]?.codeRef.range,
|
||||
type: 'path',
|
||||
await updateModelingState(
|
||||
modifiedAst,
|
||||
EXECUTION_TYPE_REAL,
|
||||
{
|
||||
kclManager,
|
||||
editorManager,
|
||||
codeManager,
|
||||
},
|
||||
})
|
||||
|
||||
await codeManager.updateEditorWithAstAndWriteToFile(updatedAst.newAst)
|
||||
|
||||
if (updatedAst?.selections) {
|
||||
editorManager.selectRange(updatedAst?.selections)
|
||||
}
|
||||
{
|
||||
focusPath: [pathToExtrudeArg],
|
||||
zoomToFit: true,
|
||||
zoomOnRangeAndType: {
|
||||
range: selection.graphSelections[0]?.codeRef.range,
|
||||
type: 'path',
|
||||
},
|
||||
}
|
||||
)
|
||||
}),
|
||||
revolveAstMod: fromPromise<
|
||||
unknown,
|
||||
@ -1819,6 +1823,7 @@ export const modelingMachine = setup({
|
||||
const { modifiedAst, pathToRevolveArg } = revolveSketchRes
|
||||
await updateModelingState(
|
||||
modifiedAst,
|
||||
EXECUTION_TYPE_REAL,
|
||||
{
|
||||
kclManager,
|
||||
editorManager,
|
||||
@ -1826,6 +1831,11 @@ export const modelingMachine = setup({
|
||||
},
|
||||
{
|
||||
focusPath: [pathToRevolveArg],
|
||||
zoomToFit: true,
|
||||
zoomOnRangeAndType: {
|
||||
range: selection.graphSelections[0]?.codeRef.range,
|
||||
type: 'path',
|
||||
},
|
||||
}
|
||||
)
|
||||
}),
|
||||
@ -1897,21 +1907,18 @@ export const modelingMachine = setup({
|
||||
offsetPlaneResult.pathToNode[1][0]++
|
||||
}
|
||||
|
||||
const updateAstResult = await kclManager.updateAst(
|
||||
await updateModelingState(
|
||||
offsetPlaneResult.modifiedAst,
|
||||
true,
|
||||
EXECUTION_TYPE_REAL,
|
||||
{
|
||||
kclManager,
|
||||
editorManager,
|
||||
codeManager,
|
||||
},
|
||||
{
|
||||
focusPath: [offsetPlaneResult.pathToNode],
|
||||
}
|
||||
)
|
||||
|
||||
await codeManager.updateEditorWithAstAndWriteToFile(
|
||||
updateAstResult.newAst
|
||||
)
|
||||
|
||||
if (updateAstResult?.selections) {
|
||||
editorManager.selectRange(updateAstResult?.selections)
|
||||
}
|
||||
}
|
||||
),
|
||||
helixAstMod: fromPromise(
|
||||
@ -2012,6 +2019,7 @@ export const modelingMachine = setup({
|
||||
})
|
||||
await updateModelingState(
|
||||
modifiedAst,
|
||||
EXECUTION_TYPE_REAL,
|
||||
{
|
||||
kclManager,
|
||||
editorManager,
|
||||
@ -2105,6 +2113,7 @@ export const modelingMachine = setup({
|
||||
})
|
||||
await updateModelingState(
|
||||
modifiedAst,
|
||||
EXECUTION_TYPE_REAL,
|
||||
{
|
||||
kclManager,
|
||||
editorManager,
|
||||
@ -2143,21 +2152,18 @@ export const modelingMachine = setup({
|
||||
|
||||
// Perform the loft
|
||||
const loftSketchesRes = loftSketches(ast, declarators)
|
||||
const updateAstResult = await kclManager.updateAst(
|
||||
await updateModelingState(
|
||||
loftSketchesRes.modifiedAst,
|
||||
true,
|
||||
EXECUTION_TYPE_REAL,
|
||||
{
|
||||
kclManager,
|
||||
editorManager,
|
||||
codeManager,
|
||||
},
|
||||
{
|
||||
focusPath: [loftSketchesRes.pathToNode],
|
||||
}
|
||||
)
|
||||
|
||||
await codeManager.updateEditorWithAstAndWriteToFile(
|
||||
updateAstResult.newAst
|
||||
)
|
||||
|
||||
if (updateAstResult?.selections) {
|
||||
editorManager.selectRange(updateAstResult?.selections)
|
||||
}
|
||||
}
|
||||
),
|
||||
shellAstMod: fromPromise(
|
||||
@ -2323,21 +2329,18 @@ export const modelingMachine = setup({
|
||||
addResult.pathToNode[1][0]++
|
||||
}
|
||||
|
||||
const updateAstResult = await kclManager.updateAst(
|
||||
await updateModelingState(
|
||||
addResult.modifiedAst,
|
||||
true,
|
||||
EXECUTION_TYPE_REAL,
|
||||
{
|
||||
kclManager,
|
||||
editorManager,
|
||||
codeManager,
|
||||
},
|
||||
{
|
||||
focusPath: [addResult.pathToNode],
|
||||
}
|
||||
)
|
||||
|
||||
await codeManager.updateEditorWithAstAndWriteToFile(
|
||||
updateAstResult.newAst
|
||||
)
|
||||
|
||||
if (updateAstResult?.selections) {
|
||||
editorManager.selectRange(updateAstResult?.selections)
|
||||
}
|
||||
}
|
||||
),
|
||||
filletAstMod: fromPromise(
|
||||
@ -2389,15 +2392,11 @@ export const modelingMachine = setup({
|
||||
node: kclManager.ast,
|
||||
newExpression: value,
|
||||
})
|
||||
const updateAstResult = await kclManager.updateAst(newAst, true)
|
||||
|
||||
await codeManager.updateEditorWithAstAndWriteToFile(
|
||||
updateAstResult.newAst
|
||||
)
|
||||
|
||||
if (updateAstResult?.selections) {
|
||||
editorManager.selectRange(updateAstResult?.selections)
|
||||
}
|
||||
await updateModelingState(newAst, EXECUTION_TYPE_REAL, {
|
||||
kclManager,
|
||||
editorManager,
|
||||
codeManager,
|
||||
})
|
||||
}
|
||||
),
|
||||
'actor.parameter.edit': fromPromise(
|
||||
@ -2426,7 +2425,7 @@ export const modelingMachine = setup({
|
||||
// Mutate the variable's value
|
||||
variableNode.node.init = value.valueAst
|
||||
|
||||
await updateModelingState(newAst, {
|
||||
await updateModelingState(newAst, EXECUTION_TYPE_REAL, {
|
||||
codeManager,
|
||||
editorManager,
|
||||
kclManager,
|
||||
@ -2592,21 +2591,18 @@ export const modelingMachine = setup({
|
||||
return err(result)
|
||||
}
|
||||
|
||||
const updateAstResult = await kclManager.updateAst(
|
||||
await updateModelingState(
|
||||
result.modifiedAst,
|
||||
true,
|
||||
EXECUTION_TYPE_REAL,
|
||||
{
|
||||
kclManager,
|
||||
editorManager,
|
||||
codeManager,
|
||||
},
|
||||
{
|
||||
focusPath: [result.pathToNode],
|
||||
}
|
||||
)
|
||||
|
||||
await codeManager.updateEditorWithAstAndWriteToFile(
|
||||
updateAstResult.newAst
|
||||
)
|
||||
|
||||
if (updateAstResult?.selections) {
|
||||
editorManager.selectRange(updateAstResult?.selections)
|
||||
}
|
||||
}
|
||||
),
|
||||
exportFromEngine: fromPromise(
|
||||
|
||||
@ -193,7 +193,7 @@ export function OnboardingButtons({
|
||||
name="close"
|
||||
className="w-5 h-5 rounded-sm bg-destroy-10 text-destroy-80 dark:bg-destroy-80 dark:text-destroy-10 group-hover:brightness-110"
|
||||
/>
|
||||
<Tooltip position="bottom" delay={500}>
|
||||
<Tooltip position="bottom">
|
||||
Dismiss <kbd className="hotkey ml-4 dark:!bg-chalkboard-80">esc</kbd>
|
||||
</Tooltip>
|
||||
</button>
|
||||
|
||||