Compare commits
12 Commits
v0.49.0
...
jtran/exec
Author | SHA1 | Date | |
---|---|---|---|
437aacf477 | |||
c6fb56058b | |||
ca2fc1bf38 | |||
8e62f07d71 | |||
55ef40d136 | |||
3b7bbc1642 | |||
1a569af476 | |||
e9fe455607 | |||
35387bbd7d | |||
b26a0f98fc | |||
b697258ad5 | |||
6c8aa799b4 |
@ -44,6 +44,8 @@ import {
|
|||||||
VariableDeclaration,
|
VariableDeclaration,
|
||||||
VariableDeclarator,
|
VariableDeclarator,
|
||||||
sketchGroupFromKclValue,
|
sketchGroupFromKclValue,
|
||||||
|
ExecState,
|
||||||
|
sketchGroupFromArtifactId,
|
||||||
} from 'lang/wasm'
|
} from 'lang/wasm'
|
||||||
import {
|
import {
|
||||||
engineCommandManager,
|
engineCommandManager,
|
||||||
@ -77,7 +79,11 @@ import {
|
|||||||
createPipeSubstitution,
|
createPipeSubstitution,
|
||||||
findUniqueName,
|
findUniqueName,
|
||||||
} from 'lang/modifyAst'
|
} from 'lang/modifyAst'
|
||||||
import { Selections, getEventForSegmentSelection } from 'lib/selections'
|
import {
|
||||||
|
Selection,
|
||||||
|
Selections,
|
||||||
|
getEventForSegmentSelection,
|
||||||
|
} from 'lib/selections'
|
||||||
import { createGridHelper, orthoScale, perspScale } from './helpers'
|
import { createGridHelper, orthoScale, perspScale } from './helpers'
|
||||||
import { Models } from '@kittycad/lib'
|
import { Models } from '@kittycad/lib'
|
||||||
import { uuidv4 } from 'lib/utils'
|
import { uuidv4 } from 'lib/utils'
|
||||||
@ -90,7 +96,12 @@ import {
|
|||||||
import { getThemeColorForThreeJs, Themes } from 'lib/theme'
|
import { getThemeColorForThreeJs, Themes } from 'lib/theme'
|
||||||
import { err, reportRejection, trap } from 'lib/trap'
|
import { err, reportRejection, trap } from 'lib/trap'
|
||||||
import { CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer'
|
import { CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer'
|
||||||
import { Point3d } from 'wasm-lib/kcl/bindings/Point3d'
|
import {
|
||||||
|
ArtifactGraph,
|
||||||
|
ArtifactId,
|
||||||
|
getPathFromSelection,
|
||||||
|
getPlaneOrFaceFromSelection,
|
||||||
|
} from 'lang/std/artifactGraph'
|
||||||
import { SegmentInputs } from 'lang/std/stdTypes'
|
import { SegmentInputs } from 'lang/std/stdTypes'
|
||||||
|
|
||||||
type DraftSegment = 'line' | 'tangentialArcTo'
|
type DraftSegment = 'line' | 'tangentialArcTo'
|
||||||
@ -122,8 +133,6 @@ export const SEGMENT_BODIES_PLUS_PROFILE_START = [
|
|||||||
PROFILE_START,
|
PROFILE_START,
|
||||||
]
|
]
|
||||||
|
|
||||||
type Vec3Array = [number, number, number]
|
|
||||||
|
|
||||||
// This singleton Class is responsible for all of the things the user sees and interacts with.
|
// This singleton Class is responsible for all of the things the user sees and interacts with.
|
||||||
// That mostly mean sketch elements.
|
// That mostly mean sketch elements.
|
||||||
// Cameras, controls, raycasters, etc are handled by sceneInfra
|
// Cameras, controls, raycasters, etc are handled by sceneInfra
|
||||||
@ -391,17 +400,37 @@ export class SceneEntities {
|
|||||||
const { truncatedAst, programMemoryOverride, variableDeclarationName } =
|
const { truncatedAst, programMemoryOverride, variableDeclarationName } =
|
||||||
prepared
|
prepared
|
||||||
|
|
||||||
const { programMemory } = await executeAst({
|
const { execState } = await executeAst({
|
||||||
ast: truncatedAst,
|
ast: truncatedAst,
|
||||||
useFakeExecutor: true,
|
useFakeExecutor: true,
|
||||||
engineCommandManager: this.engineCommandManager,
|
engineCommandManager: this.engineCommandManager,
|
||||||
programMemoryOverride,
|
programMemoryOverride,
|
||||||
})
|
})
|
||||||
const sketchGroup = sketchGroupFromPathToNode({
|
const programMemory = execState.memory
|
||||||
pathToNode: sketchPathToNode,
|
let sketchGroup: SketchGroup | null | Error = null
|
||||||
ast: maybeModdedAst,
|
if (selectionRanges) {
|
||||||
programMemory,
|
console.warn('setupSketch looking for sketch from selection')
|
||||||
})
|
sketchGroup = sketchGroupFromSelection({
|
||||||
|
selections: selectionRanges,
|
||||||
|
execState: kclManager.execState,
|
||||||
|
// execState,
|
||||||
|
artifactGraph: this.engineCommandManager.artifactGraph,
|
||||||
|
})
|
||||||
|
if (sketchGroup) {
|
||||||
|
console.warn('setupSketch found sketch from selection')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!sketchGroup) {
|
||||||
|
console.warn(
|
||||||
|
'setupSketch sketch not found from selection; falling back to program memory'
|
||||||
|
)
|
||||||
|
// Fall back to the sketch group from the program memory.
|
||||||
|
sketchGroup = sketchGroupFromPathToNode({
|
||||||
|
pathToNode: sketchPathToNode,
|
||||||
|
ast: maybeModdedAst,
|
||||||
|
programMemory,
|
||||||
|
})
|
||||||
|
}
|
||||||
if (err(sketchGroup)) return Promise.reject(sketchGroup)
|
if (err(sketchGroup)) return Promise.reject(sketchGroup)
|
||||||
if (!sketchGroup) return Promise.reject('sketchGroup not found')
|
if (!sketchGroup) return Promise.reject('sketchGroup not found')
|
||||||
|
|
||||||
@ -598,11 +627,13 @@ export class SceneEntities {
|
|||||||
const _node1 = getNodeFromPath<VariableDeclaration>(
|
const _node1 = getNodeFromPath<VariableDeclaration>(
|
||||||
_ast,
|
_ast,
|
||||||
sketchPathToNode || [],
|
sketchPathToNode || [],
|
||||||
'VariableDeclaration'
|
['VariableDeclaration', 'ExpressionStatement']
|
||||||
)
|
) as { node: { type: string } } | Error
|
||||||
if (trap(_node1)) return Promise.reject(_node1)
|
if (trap(_node1)) return Promise.reject(_node1)
|
||||||
const variableDeclarationName =
|
const variableDeclarationName =
|
||||||
_node1.node?.declarations?.[0]?.id?.name || ''
|
_node1.node.type === 'VariableDeclaration'
|
||||||
|
? (_node1.node as VariableDeclaration).declarations[0]?.id?.name || ''
|
||||||
|
: ''
|
||||||
|
|
||||||
const sg = sketchGroupFromKclValue(
|
const sg = sketchGroupFromKclValue(
|
||||||
kclManager.programMemory.get(variableDeclarationName),
|
kclManager.programMemory.get(variableDeclarationName),
|
||||||
@ -802,12 +833,13 @@ export class SceneEntities {
|
|||||||
updateRectangleSketch(sketchInit, x, y, tags[0])
|
updateRectangleSketch(sketchInit, x, y, tags[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
const { programMemory } = await executeAst({
|
const { execState } = await executeAst({
|
||||||
ast: truncatedAst,
|
ast: truncatedAst,
|
||||||
useFakeExecutor: true,
|
useFakeExecutor: true,
|
||||||
engineCommandManager: this.engineCommandManager,
|
engineCommandManager: this.engineCommandManager,
|
||||||
programMemoryOverride,
|
programMemoryOverride,
|
||||||
})
|
})
|
||||||
|
const programMemory = execState.memory
|
||||||
this.sceneProgramMemory = programMemory
|
this.sceneProgramMemory = programMemory
|
||||||
const sketchGroup = sketchGroupFromKclValue(
|
const sketchGroup = sketchGroupFromKclValue(
|
||||||
programMemory.get(variableDeclarationName),
|
programMemory.get(variableDeclarationName),
|
||||||
@ -856,12 +888,13 @@ export class SceneEntities {
|
|||||||
await kclManager.executeAstMock(_ast)
|
await kclManager.executeAstMock(_ast)
|
||||||
sceneInfra.modelingSend({ type: 'Finish rectangle' })
|
sceneInfra.modelingSend({ type: 'Finish rectangle' })
|
||||||
|
|
||||||
const { programMemory } = await executeAst({
|
const { execState } = await executeAst({
|
||||||
ast: _ast,
|
ast: _ast,
|
||||||
useFakeExecutor: true,
|
useFakeExecutor: true,
|
||||||
engineCommandManager: this.engineCommandManager,
|
engineCommandManager: this.engineCommandManager,
|
||||||
programMemoryOverride,
|
programMemoryOverride,
|
||||||
})
|
})
|
||||||
|
const programMemory = execState.memory
|
||||||
|
|
||||||
// Prepare to update the THREEjs scene
|
// Prepare to update the THREEjs scene
|
||||||
this.sceneProgramMemory = programMemory
|
this.sceneProgramMemory = programMemory
|
||||||
@ -980,12 +1013,13 @@ export class SceneEntities {
|
|||||||
modded = moddedResult.modifiedAst
|
modded = moddedResult.modifiedAst
|
||||||
}
|
}
|
||||||
|
|
||||||
const { programMemory } = await executeAst({
|
const { execState } = await executeAst({
|
||||||
ast: modded,
|
ast: modded,
|
||||||
useFakeExecutor: true,
|
useFakeExecutor: true,
|
||||||
engineCommandManager: this.engineCommandManager,
|
engineCommandManager: this.engineCommandManager,
|
||||||
programMemoryOverride,
|
programMemoryOverride,
|
||||||
})
|
})
|
||||||
|
const programMemory = execState.memory
|
||||||
this.sceneProgramMemory = programMemory
|
this.sceneProgramMemory = programMemory
|
||||||
const sketchGroup = sketchGroupFromKclValue(
|
const sketchGroup = sketchGroupFromKclValue(
|
||||||
programMemory.get(variableDeclarationName),
|
programMemory.get(variableDeclarationName),
|
||||||
@ -1339,12 +1373,13 @@ export class SceneEntities {
|
|||||||
// don't want to mod the user's code yet as they have't committed to the change yet
|
// don't want to mod the user's code yet as they have't committed to the change yet
|
||||||
// plus this would be the truncated ast being recast, it would be wrong
|
// plus this would be the truncated ast being recast, it would be wrong
|
||||||
codeManager.updateCodeEditor(code)
|
codeManager.updateCodeEditor(code)
|
||||||
const { programMemory } = await executeAst({
|
const { execState } = await executeAst({
|
||||||
ast: truncatedAst,
|
ast: truncatedAst,
|
||||||
useFakeExecutor: true,
|
useFakeExecutor: true,
|
||||||
engineCommandManager: this.engineCommandManager,
|
engineCommandManager: this.engineCommandManager,
|
||||||
programMemoryOverride,
|
programMemoryOverride,
|
||||||
})
|
})
|
||||||
|
const programMemory = execState.memory
|
||||||
this.sceneProgramMemory = programMemory
|
this.sceneProgramMemory = programMemory
|
||||||
|
|
||||||
const maybeSketchGroup = programMemory.get(variableDeclarationName)
|
const maybeSketchGroup = programMemory.get(variableDeclarationName)
|
||||||
@ -1820,6 +1855,70 @@ export function getParentGroup(
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function planeOrFaceFromSelection({
|
||||||
|
artifactGraph,
|
||||||
|
selection,
|
||||||
|
}: {
|
||||||
|
artifactGraph: ArtifactGraph
|
||||||
|
selection: Selection
|
||||||
|
}): Promise<{
|
||||||
|
id: ArtifactId
|
||||||
|
faceDetails: Models['GetSketchModePlane_type']
|
||||||
|
} | null> {
|
||||||
|
// If the selection doesn't have an artifactId associated with it, we can't
|
||||||
|
// do it.
|
||||||
|
if (!selection.artifactId) return null
|
||||||
|
|
||||||
|
const planeOrFace = getPlaneOrFaceFromSelection(
|
||||||
|
selection.artifactId,
|
||||||
|
artifactGraph
|
||||||
|
)
|
||||||
|
if (!planeOrFace) return null
|
||||||
|
if (planeOrFace?.type === 'plane') {
|
||||||
|
const faceDetails = await getFaceDetails(planeOrFace.id)
|
||||||
|
return { id: planeOrFace.id, faceDetails }
|
||||||
|
}
|
||||||
|
// TODO: Handle wall or cap artifact.
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
export function sketchGroupFromSelection({
|
||||||
|
selections,
|
||||||
|
artifactGraph,
|
||||||
|
execState,
|
||||||
|
}: {
|
||||||
|
selections: Selections
|
||||||
|
artifactGraph: ArtifactGraph
|
||||||
|
execState: ExecState
|
||||||
|
}): SketchGroup | null {
|
||||||
|
if (selections.codeBasedSelections.length !== 1) {
|
||||||
|
// Give up if there isn't exactly one selection.
|
||||||
|
console.warn(
|
||||||
|
'sketchGroupFromSelection no single selection',
|
||||||
|
selections.codeBasedSelections.length,
|
||||||
|
selections
|
||||||
|
)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
const selection = selections.codeBasedSelections[0]
|
||||||
|
const artifactId = selection.artifactId
|
||||||
|
if (!artifactId) {
|
||||||
|
console.warn(
|
||||||
|
'sketchGroupFromSelection artifact ID not found',
|
||||||
|
selections.codeBasedSelections.length,
|
||||||
|
selections
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (!artifactId) return null
|
||||||
|
const path = getPathFromSelection(artifactId, artifactGraph)
|
||||||
|
if (!path) {
|
||||||
|
console.warn('sketchGroupFromSelection path not found', artifactId)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
const sketch = sketchGroupFromArtifactId(execState, path.id)
|
||||||
|
return sketch
|
||||||
|
}
|
||||||
|
|
||||||
export function sketchGroupFromPathToNode({
|
export function sketchGroupFromPathToNode({
|
||||||
pathToNode,
|
pathToNode,
|
||||||
ast,
|
ast,
|
||||||
@ -1829,6 +1928,7 @@ export function sketchGroupFromPathToNode({
|
|||||||
ast: Program
|
ast: Program
|
||||||
programMemory: ProgramMemory
|
programMemory: ProgramMemory
|
||||||
}): SketchGroup | null | Error {
|
}): SketchGroup | null | Error {
|
||||||
|
console.warn('**** sketchGroupFromPathToNode **** Deprecated')
|
||||||
const _varDec = getNodeFromPath<VariableDeclarator>(
|
const _varDec = getNodeFromPath<VariableDeclarator>(
|
||||||
kclManager.ast,
|
kclManager.ast,
|
||||||
pathToNode,
|
pathToNode,
|
||||||
@ -1868,27 +1968,55 @@ function colorSegment(object: any, color: number) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getSketchQuaternion(
|
|
||||||
sketchPathToNode: PathToNode,
|
|
||||||
sketchNormalBackUp: [number, number, number] | null
|
|
||||||
): Quaternion | Error {
|
|
||||||
const sketchGroup = sketchGroupFromPathToNode({
|
|
||||||
pathToNode: sketchPathToNode,
|
|
||||||
ast: kclManager.ast,
|
|
||||||
programMemory: kclManager.programMemory,
|
|
||||||
})
|
|
||||||
if (err(sketchGroup)) return sketchGroup
|
|
||||||
const zAxis = sketchGroup?.on.zAxis || sketchNormalBackUp
|
|
||||||
if (!zAxis) return Error('SketchGroup zAxis not found')
|
|
||||||
|
|
||||||
return getQuaternionFromZAxis(massageFormats(zAxis))
|
|
||||||
}
|
|
||||||
export async function getSketchOrientationDetails(
|
export async function getSketchOrientationDetails(
|
||||||
|
artifactGraph: ArtifactGraph,
|
||||||
|
selection: Selection,
|
||||||
sketchPathToNode: PathToNode
|
sketchPathToNode: PathToNode
|
||||||
): Promise<{
|
): Promise<{
|
||||||
quat: Quaternion
|
sketchDetails: {
|
||||||
sketchDetails: SketchDetails & { faceId?: string }
|
zAxis: [number, number, number]
|
||||||
|
yAxis: [number, number, number]
|
||||||
|
origin: [number, number, number]
|
||||||
|
faceId: string
|
||||||
|
}
|
||||||
}> {
|
}> {
|
||||||
|
const plane = await planeOrFaceFromSelection({
|
||||||
|
artifactGraph,
|
||||||
|
selection,
|
||||||
|
})
|
||||||
|
if (plane) {
|
||||||
|
const details = plane.faceDetails
|
||||||
|
console.warn('Found plane', plane)
|
||||||
|
const zAxis: [number, number, number] = [
|
||||||
|
details.z_axis.x,
|
||||||
|
details.z_axis.y,
|
||||||
|
details.z_axis.z,
|
||||||
|
]
|
||||||
|
const yAxis: [number, number, number] = [
|
||||||
|
details.y_axis.x,
|
||||||
|
details.y_axis.y,
|
||||||
|
details.y_axis.z,
|
||||||
|
]
|
||||||
|
const origin: [number, number, number] = [
|
||||||
|
details.origin.x,
|
||||||
|
details.origin.y,
|
||||||
|
details.origin.z,
|
||||||
|
]
|
||||||
|
return {
|
||||||
|
sketchDetails: {
|
||||||
|
zAxis,
|
||||||
|
yAxis,
|
||||||
|
origin,
|
||||||
|
faceId: plane.id,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We couldn't find the plane or face, so try to look at the AST, and find it
|
||||||
|
// through there.
|
||||||
|
console.warn(
|
||||||
|
'getSketchOrientationDetails falling back to sketchGroupFromPathToNode'
|
||||||
|
)
|
||||||
const sketchGroup = sketchGroupFromPathToNode({
|
const sketchGroup = sketchGroupFromPathToNode({
|
||||||
pathToNode: sketchPathToNode,
|
pathToNode: sketchPathToNode,
|
||||||
ast: kclManager.ast,
|
ast: kclManager.ast,
|
||||||
@ -1900,9 +2028,7 @@ export async function getSketchOrientationDetails(
|
|||||||
if (sketchGroup.on.type === 'plane') {
|
if (sketchGroup.on.type === 'plane') {
|
||||||
const zAxis = sketchGroup?.on.zAxis
|
const zAxis = sketchGroup?.on.zAxis
|
||||||
return {
|
return {
|
||||||
quat: getQuaternionFromZAxis(massageFormats(zAxis)),
|
|
||||||
sketchDetails: {
|
sketchDetails: {
|
||||||
sketchPathToNode,
|
|
||||||
zAxis: [zAxis.x, zAxis.y, zAxis.z],
|
zAxis: [zAxis.x, zAxis.y, zAxis.z],
|
||||||
yAxis: [
|
yAxis: [
|
||||||
sketchGroup.on.yAxis.x,
|
sketchGroup.on.yAxis.x,
|
||||||
@ -1921,14 +2047,8 @@ export async function getSketchOrientationDetails(
|
|||||||
if (!faceInfo?.origin || !faceInfo?.z_axis || !faceInfo?.y_axis)
|
if (!faceInfo?.origin || !faceInfo?.z_axis || !faceInfo?.y_axis)
|
||||||
return Promise.reject('face info')
|
return Promise.reject('face info')
|
||||||
const { z_axis, y_axis, origin } = faceInfo
|
const { z_axis, y_axis, origin } = faceInfo
|
||||||
const quaternion = quaternionFromUpNForward(
|
|
||||||
new Vector3(y_axis.x, y_axis.y, y_axis.z),
|
|
||||||
new Vector3(z_axis.x, z_axis.y, z_axis.z)
|
|
||||||
)
|
|
||||||
return {
|
return {
|
||||||
quat: quaternion,
|
|
||||||
sketchDetails: {
|
sketchDetails: {
|
||||||
sketchPathToNode,
|
|
||||||
zAxis: [z_axis.x, z_axis.y, z_axis.z],
|
zAxis: [z_axis.x, z_axis.y, z_axis.z],
|
||||||
yAxis: [y_axis.x, y_axis.y, y_axis.z],
|
yAxis: [y_axis.x, y_axis.y, y_axis.z],
|
||||||
origin: [origin.x, origin.y, origin.z],
|
origin: [origin.x, origin.y, origin.z],
|
||||||
@ -2003,7 +2123,3 @@ export function getQuaternionFromZAxis(zAxis: Vector3): Quaternion {
|
|||||||
}
|
}
|
||||||
return quaternion
|
return quaternion
|
||||||
}
|
}
|
||||||
|
|
||||||
function massageFormats(a: Vec3Array | Point3d): Vector3 {
|
|
||||||
return isArray(a) ? new Vector3(a[0], a[1], a[2]) : new Vector3(a.x, a.y, a.z)
|
|
||||||
}
|
|
||||||
|
@ -157,7 +157,7 @@ export function useCalc({
|
|||||||
engineCommandManager,
|
engineCommandManager,
|
||||||
useFakeExecutor: true,
|
useFakeExecutor: true,
|
||||||
programMemoryOverride: kclManager.programMemory.clone(),
|
programMemoryOverride: kclManager.programMemory.clone(),
|
||||||
}).then(({ programMemory }) => {
|
}).then(({ execState }) => {
|
||||||
const resultDeclaration = ast.body.find(
|
const resultDeclaration = ast.body.find(
|
||||||
(a) =>
|
(a) =>
|
||||||
a.type === 'VariableDeclaration' &&
|
a.type === 'VariableDeclaration' &&
|
||||||
@ -166,7 +166,7 @@ export function useCalc({
|
|||||||
const init =
|
const init =
|
||||||
resultDeclaration?.type === 'VariableDeclaration' &&
|
resultDeclaration?.type === 'VariableDeclaration' &&
|
||||||
resultDeclaration?.declarations?.[0]?.init
|
resultDeclaration?.declarations?.[0]?.init
|
||||||
const result = programMemory?.get('__result__')?.value
|
const result = execState.memory?.get('__result__')?.value
|
||||||
setCalcResult(typeof result === 'number' ? String(result) : 'NAN')
|
setCalcResult(typeof result === 'number' ? String(result) : 'NAN')
|
||||||
init && setValueNode(init)
|
init && setValueNode(init)
|
||||||
})
|
})
|
||||||
|
@ -625,12 +625,15 @@ export const ModelingMachineProvider = ({
|
|||||||
}),
|
}),
|
||||||
'animate-to-sketch': fromPromise(
|
'animate-to-sketch': fromPromise(
|
||||||
async ({ input: { selectionRanges } }) => {
|
async ({ input: { selectionRanges } }) => {
|
||||||
const sourceRange = selectionRanges.codeBasedSelections[0].range
|
const selection = selectionRanges.codeBasedSelections[0]
|
||||||
|
const sourceRange = selection.range
|
||||||
const sketchPathToNode = getNodePathFromSourceRange(
|
const sketchPathToNode = getNodePathFromSourceRange(
|
||||||
kclManager.ast,
|
kclManager.ast,
|
||||||
sourceRange
|
sourceRange
|
||||||
)
|
)
|
||||||
const info = await getSketchOrientationDetails(
|
const info = await getSketchOrientationDetails(
|
||||||
|
engineCommandManager.artifactGraph,
|
||||||
|
selection,
|
||||||
sketchPathToNode || []
|
sketchPathToNode || []
|
||||||
)
|
)
|
||||||
await letEngineAnimateAndSyncCamAfter(
|
await letEngineAnimateAndSyncCamAfter(
|
||||||
|
@ -29,8 +29,8 @@ describe('processMemory', () => {
|
|||||||
|> lineTo([2.15, 4.32], %)
|
|> lineTo([2.15, 4.32], %)
|
||||||
// |> rx(90, %)`
|
// |> rx(90, %)`
|
||||||
const ast = parse(code)
|
const ast = parse(code)
|
||||||
const programMemory = await enginelessExecutor(ast, ProgramMemory.empty())
|
const execState = await enginelessExecutor(ast, ProgramMemory.empty())
|
||||||
const output = processMemory(programMemory)
|
const output = processMemory(execState.memory)
|
||||||
expect(output.myVar).toEqual(5)
|
expect(output.myVar).toEqual(5)
|
||||||
expect(output.otherVar).toEqual(3)
|
expect(output.otherVar).toEqual(3)
|
||||||
expect(output).toEqual({
|
expect(output).toEqual({
|
||||||
|
@ -8,6 +8,8 @@ import { EXECUTE_AST_INTERRUPT_ERROR_MESSAGE } from 'lib/constants'
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
CallExpression,
|
CallExpression,
|
||||||
|
emptyExecState,
|
||||||
|
ExecState,
|
||||||
initPromise,
|
initPromise,
|
||||||
parse,
|
parse,
|
||||||
PathToNode,
|
PathToNode,
|
||||||
@ -19,6 +21,8 @@ import {
|
|||||||
import { getNodeFromPath } from './queryAst'
|
import { getNodeFromPath } from './queryAst'
|
||||||
import { codeManager, editorManager, sceneInfra } from 'lib/singletons'
|
import { codeManager, editorManager, sceneInfra } from 'lib/singletons'
|
||||||
import { Diagnostic } from '@codemirror/lint'
|
import { Diagnostic } from '@codemirror/lint'
|
||||||
|
import { ArtifactId } from 'wasm-lib/kcl/bindings/ArtifactId'
|
||||||
|
import { Artifact } from 'wasm-lib/kcl/bindings/Artifact'
|
||||||
|
|
||||||
interface ExecuteArgs {
|
interface ExecuteArgs {
|
||||||
ast?: Program
|
ast?: Program
|
||||||
@ -43,6 +47,7 @@ export class KclManager {
|
|||||||
digest: null,
|
digest: null,
|
||||||
}
|
}
|
||||||
private _programMemory: ProgramMemory = ProgramMemory.empty()
|
private _programMemory: ProgramMemory = ProgramMemory.empty()
|
||||||
|
private _execState: ExecState = emptyExecState()
|
||||||
private _logs: string[] = []
|
private _logs: string[] = []
|
||||||
private _lints: Diagnostic[] = []
|
private _lints: Diagnostic[] = []
|
||||||
private _kclErrors: KCLError[] = []
|
private _kclErrors: KCLError[] = []
|
||||||
@ -71,11 +76,21 @@ export class KclManager {
|
|||||||
get programMemory() {
|
get programMemory() {
|
||||||
return this._programMemory
|
return this._programMemory
|
||||||
}
|
}
|
||||||
set programMemory(programMemory) {
|
// This is private because callers should be setting the entire execState.
|
||||||
|
private set programMemory(programMemory) {
|
||||||
this._programMemory = programMemory
|
this._programMemory = programMemory
|
||||||
this._programMemoryCallBack(programMemory)
|
this._programMemoryCallBack(programMemory)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
set execState(execState) {
|
||||||
|
this._execState = execState
|
||||||
|
this.programMemory = execState.memory
|
||||||
|
}
|
||||||
|
|
||||||
|
get execState() {
|
||||||
|
return this._execState
|
||||||
|
}
|
||||||
|
|
||||||
get logs() {
|
get logs() {
|
||||||
return this._logs
|
return this._logs
|
||||||
}
|
}
|
||||||
@ -252,7 +267,7 @@ export class KclManager {
|
|||||||
// Make sure we clear before starting again. End session will do this.
|
// Make sure we clear before starting again. End session will do this.
|
||||||
this.engineCommandManager?.endSession()
|
this.engineCommandManager?.endSession()
|
||||||
await this.ensureWasmInit()
|
await this.ensureWasmInit()
|
||||||
const { logs, errors, programMemory, isInterrupted } = await executeAst({
|
const { logs, errors, execState, isInterrupted } = await executeAst({
|
||||||
ast,
|
ast,
|
||||||
engineCommandManager: this.engineCommandManager,
|
engineCommandManager: this.engineCommandManager,
|
||||||
})
|
})
|
||||||
@ -263,7 +278,7 @@ export class KclManager {
|
|||||||
this.lints = await lintAst({ ast: ast })
|
this.lints = await lintAst({ ast: ast })
|
||||||
|
|
||||||
sceneInfra.modelingSend({ type: 'code edit during sketch' })
|
sceneInfra.modelingSend({ type: 'code edit during sketch' })
|
||||||
defaultSelectionFilter(programMemory, this.engineCommandManager)
|
defaultSelectionFilter(execState.memory, this.engineCommandManager)
|
||||||
|
|
||||||
if (args.zoomToFit) {
|
if (args.zoomToFit) {
|
||||||
let zoomObjectId: string | undefined = ''
|
let zoomObjectId: string | undefined = ''
|
||||||
@ -296,7 +311,7 @@ export class KclManager {
|
|||||||
this.logs = logs
|
this.logs = logs
|
||||||
// Do not add the errors since the program was interrupted and the error is not a real KCL error
|
// Do not add the errors since the program was interrupted and the error is not a real KCL error
|
||||||
this.addKclErrors(isInterrupted ? [] : errors)
|
this.addKclErrors(isInterrupted ? [] : errors)
|
||||||
this.programMemory = programMemory
|
this.execState = execState
|
||||||
this.ast = { ...ast }
|
this.ast = { ...ast }
|
||||||
this._executeCallback()
|
this._executeCallback()
|
||||||
this.engineCommandManager.addCommandLog({
|
this.engineCommandManager.addCommandLog({
|
||||||
@ -333,7 +348,7 @@ export class KclManager {
|
|||||||
await codeManager.writeToFile()
|
await codeManager.writeToFile()
|
||||||
this._ast = { ...newAst }
|
this._ast = { ...newAst }
|
||||||
|
|
||||||
const { logs, errors, programMemory } = await executeAst({
|
const { logs, errors, execState } = await executeAst({
|
||||||
ast: newAst,
|
ast: newAst,
|
||||||
engineCommandManager: this.engineCommandManager,
|
engineCommandManager: this.engineCommandManager,
|
||||||
useFakeExecutor: true,
|
useFakeExecutor: true,
|
||||||
@ -341,7 +356,8 @@ export class KclManager {
|
|||||||
|
|
||||||
this._logs = logs
|
this._logs = logs
|
||||||
this._kclErrors = errors
|
this._kclErrors = errors
|
||||||
this._programMemory = programMemory
|
this._execState = execState
|
||||||
|
this._programMemory = execState.memory
|
||||||
if (updates !== 'artifactRanges') return
|
if (updates !== 'artifactRanges') return
|
||||||
|
|
||||||
// TODO the below seems like a work around, I wish there's a comment explaining exactly what
|
// TODO the below seems like a work around, I wish there's a comment explaining exactly what
|
||||||
|
@ -445,6 +445,6 @@ async function exe(
|
|||||||
) {
|
) {
|
||||||
const ast = parse(code)
|
const ast = parse(code)
|
||||||
|
|
||||||
const result = await enginelessExecutor(ast, programMemory)
|
const execState = await enginelessExecutor(ast, programMemory)
|
||||||
return result
|
return execState.memory
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,8 @@ import {
|
|||||||
ProgramMemory,
|
ProgramMemory,
|
||||||
programMemoryInit,
|
programMemoryInit,
|
||||||
kclLint,
|
kclLint,
|
||||||
|
emptyExecState,
|
||||||
|
ExecState,
|
||||||
} from 'lang/wasm'
|
} from 'lang/wasm'
|
||||||
import { enginelessExecutor } from 'lib/testHelpers'
|
import { enginelessExecutor } from 'lib/testHelpers'
|
||||||
import { EngineCommandManager } from 'lang/std/engineConnection'
|
import { EngineCommandManager } from 'lang/std/engineConnection'
|
||||||
@ -56,7 +58,7 @@ export async function executeAst({
|
|||||||
}): Promise<{
|
}): Promise<{
|
||||||
logs: string[]
|
logs: string[]
|
||||||
errors: KCLError[]
|
errors: KCLError[]
|
||||||
programMemory: ProgramMemory
|
execState: ExecState
|
||||||
isInterrupted: boolean
|
isInterrupted: boolean
|
||||||
}> {
|
}> {
|
||||||
try {
|
try {
|
||||||
@ -65,7 +67,7 @@ export async function executeAst({
|
|||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
engineCommandManager.startNewSession()
|
engineCommandManager.startNewSession()
|
||||||
}
|
}
|
||||||
const programMemory = await (useFakeExecutor
|
const execState = await (useFakeExecutor
|
||||||
? enginelessExecutor(ast, programMemoryOverride || programMemoryInit())
|
? enginelessExecutor(ast, programMemoryOverride || programMemoryInit())
|
||||||
: _executor(ast, programMemoryInit(), engineCommandManager, false))
|
: _executor(ast, programMemoryInit(), engineCommandManager, false))
|
||||||
|
|
||||||
@ -73,7 +75,7 @@ export async function executeAst({
|
|||||||
return {
|
return {
|
||||||
logs: [],
|
logs: [],
|
||||||
errors: [],
|
errors: [],
|
||||||
programMemory,
|
execState,
|
||||||
isInterrupted: false,
|
isInterrupted: false,
|
||||||
}
|
}
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
@ -89,7 +91,7 @@ export async function executeAst({
|
|||||||
return {
|
return {
|
||||||
errors: [e],
|
errors: [e],
|
||||||
logs: [],
|
logs: [],
|
||||||
programMemory: ProgramMemory.empty(),
|
execState: emptyExecState(),
|
||||||
isInterrupted,
|
isInterrupted,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -97,7 +99,7 @@ export async function executeAst({
|
|||||||
return {
|
return {
|
||||||
logs: [e],
|
logs: [e],
|
||||||
errors: [],
|
errors: [],
|
||||||
programMemory: ProgramMemory.empty(),
|
execState: emptyExecState(),
|
||||||
isInterrupted,
|
isInterrupted,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -220,11 +220,11 @@ const yo2 = hmm([identifierGuy + 5])`
|
|||||||
it('should move a binary expression into a new variable', async () => {
|
it('should move a binary expression into a new variable', async () => {
|
||||||
const ast = parse(code)
|
const ast = parse(code)
|
||||||
if (err(ast)) throw ast
|
if (err(ast)) throw ast
|
||||||
const programMemory = await enginelessExecutor(ast)
|
const execState = await enginelessExecutor(ast)
|
||||||
const startIndex = code.indexOf('100 + 100') + 1
|
const startIndex = code.indexOf('100 + 100') + 1
|
||||||
const { modifiedAst } = moveValueIntoNewVariable(
|
const { modifiedAst } = moveValueIntoNewVariable(
|
||||||
ast,
|
ast,
|
||||||
programMemory,
|
execState.memory,
|
||||||
[startIndex, startIndex],
|
[startIndex, startIndex],
|
||||||
'newVar'
|
'newVar'
|
||||||
)
|
)
|
||||||
@ -235,11 +235,11 @@ const yo2 = hmm([identifierGuy + 5])`
|
|||||||
it('should move a value into a new variable', async () => {
|
it('should move a value into a new variable', async () => {
|
||||||
const ast = parse(code)
|
const ast = parse(code)
|
||||||
if (err(ast)) throw ast
|
if (err(ast)) throw ast
|
||||||
const programMemory = await enginelessExecutor(ast)
|
const execState = await enginelessExecutor(ast)
|
||||||
const startIndex = code.indexOf('2.8') + 1
|
const startIndex = code.indexOf('2.8') + 1
|
||||||
const { modifiedAst } = moveValueIntoNewVariable(
|
const { modifiedAst } = moveValueIntoNewVariable(
|
||||||
ast,
|
ast,
|
||||||
programMemory,
|
execState.memory,
|
||||||
[startIndex, startIndex],
|
[startIndex, startIndex],
|
||||||
'newVar'
|
'newVar'
|
||||||
)
|
)
|
||||||
@ -250,11 +250,11 @@ const yo2 = hmm([identifierGuy + 5])`
|
|||||||
it('should move a callExpression into a new variable', async () => {
|
it('should move a callExpression into a new variable', async () => {
|
||||||
const ast = parse(code)
|
const ast = parse(code)
|
||||||
if (err(ast)) throw ast
|
if (err(ast)) throw ast
|
||||||
const programMemory = await enginelessExecutor(ast)
|
const execState = await enginelessExecutor(ast)
|
||||||
const startIndex = code.indexOf('def(')
|
const startIndex = code.indexOf('def(')
|
||||||
const { modifiedAst } = moveValueIntoNewVariable(
|
const { modifiedAst } = moveValueIntoNewVariable(
|
||||||
ast,
|
ast,
|
||||||
programMemory,
|
execState.memory,
|
||||||
[startIndex, startIndex],
|
[startIndex, startIndex],
|
||||||
'newVar'
|
'newVar'
|
||||||
)
|
)
|
||||||
@ -265,11 +265,11 @@ const yo2 = hmm([identifierGuy + 5])`
|
|||||||
it('should move a binary expression with call expression into a new variable', async () => {
|
it('should move a binary expression with call expression into a new variable', async () => {
|
||||||
const ast = parse(code)
|
const ast = parse(code)
|
||||||
if (err(ast)) throw ast
|
if (err(ast)) throw ast
|
||||||
const programMemory = await enginelessExecutor(ast)
|
const execState = await enginelessExecutor(ast)
|
||||||
const startIndex = code.indexOf('jkl(') + 1
|
const startIndex = code.indexOf('jkl(') + 1
|
||||||
const { modifiedAst } = moveValueIntoNewVariable(
|
const { modifiedAst } = moveValueIntoNewVariable(
|
||||||
ast,
|
ast,
|
||||||
programMemory,
|
execState.memory,
|
||||||
[startIndex, startIndex],
|
[startIndex, startIndex],
|
||||||
'newVar'
|
'newVar'
|
||||||
)
|
)
|
||||||
@ -280,11 +280,11 @@ const yo2 = hmm([identifierGuy + 5])`
|
|||||||
it('should move a identifier into a new variable', async () => {
|
it('should move a identifier into a new variable', async () => {
|
||||||
const ast = parse(code)
|
const ast = parse(code)
|
||||||
if (err(ast)) throw ast
|
if (err(ast)) throw ast
|
||||||
const programMemory = await enginelessExecutor(ast)
|
const execState = await enginelessExecutor(ast)
|
||||||
const startIndex = code.indexOf('identifierGuy +') + 1
|
const startIndex = code.indexOf('identifierGuy +') + 1
|
||||||
const { modifiedAst } = moveValueIntoNewVariable(
|
const { modifiedAst } = moveValueIntoNewVariable(
|
||||||
ast,
|
ast,
|
||||||
programMemory,
|
execState.memory,
|
||||||
[startIndex, startIndex],
|
[startIndex, startIndex],
|
||||||
'newVar'
|
'newVar'
|
||||||
)
|
)
|
||||||
@ -465,7 +465,7 @@ describe('Testing deleteSegmentFromPipeExpression', () => {
|
|||||||
|> line([306.21, 198.87], %)`
|
|> line([306.21, 198.87], %)`
|
||||||
const ast = parse(code)
|
const ast = parse(code)
|
||||||
if (err(ast)) throw ast
|
if (err(ast)) throw ast
|
||||||
const programMemory = await enginelessExecutor(ast)
|
const execState = await enginelessExecutor(ast)
|
||||||
const lineOfInterest = 'line([306.21, 198.85], %, $a)'
|
const lineOfInterest = 'line([306.21, 198.85], %, $a)'
|
||||||
const range: [number, number] = [
|
const range: [number, number] = [
|
||||||
code.indexOf(lineOfInterest),
|
code.indexOf(lineOfInterest),
|
||||||
@ -475,7 +475,7 @@ describe('Testing deleteSegmentFromPipeExpression', () => {
|
|||||||
const modifiedAst = deleteSegmentFromPipeExpression(
|
const modifiedAst = deleteSegmentFromPipeExpression(
|
||||||
[],
|
[],
|
||||||
ast,
|
ast,
|
||||||
programMemory,
|
execState.memory,
|
||||||
code,
|
code,
|
||||||
pathToNode
|
pathToNode
|
||||||
)
|
)
|
||||||
@ -543,7 +543,7 @@ ${!replace1 ? ` |> ${line}\n` : ''} |> angledLine([-65, ${
|
|||||||
const code = makeCode(line)
|
const code = makeCode(line)
|
||||||
const ast = parse(code)
|
const ast = parse(code)
|
||||||
if (err(ast)) throw ast
|
if (err(ast)) throw ast
|
||||||
const programMemory = await enginelessExecutor(ast)
|
const execState = await enginelessExecutor(ast)
|
||||||
const lineOfInterest = line
|
const lineOfInterest = line
|
||||||
const range: [number, number] = [
|
const range: [number, number] = [
|
||||||
code.indexOf(lineOfInterest),
|
code.indexOf(lineOfInterest),
|
||||||
@ -554,7 +554,7 @@ ${!replace1 ? ` |> ${line}\n` : ''} |> angledLine([-65, ${
|
|||||||
const modifiedAst = deleteSegmentFromPipeExpression(
|
const modifiedAst = deleteSegmentFromPipeExpression(
|
||||||
dependentSegments,
|
dependentSegments,
|
||||||
ast,
|
ast,
|
||||||
programMemory,
|
execState.memory,
|
||||||
code,
|
code,
|
||||||
pathToNode
|
pathToNode
|
||||||
)
|
)
|
||||||
@ -632,7 +632,7 @@ describe('Testing removeSingleConstraintInfo', () => {
|
|||||||
const ast = parse(code)
|
const ast = parse(code)
|
||||||
if (err(ast)) throw ast
|
if (err(ast)) throw ast
|
||||||
|
|
||||||
const programMemory = await enginelessExecutor(ast)
|
const execState = await enginelessExecutor(ast)
|
||||||
const lineOfInterest = expectedFinish.split('(')[0] + '('
|
const lineOfInterest = expectedFinish.split('(')[0] + '('
|
||||||
const range: [number, number] = [
|
const range: [number, number] = [
|
||||||
code.indexOf(lineOfInterest) + 1,
|
code.indexOf(lineOfInterest) + 1,
|
||||||
@ -661,7 +661,7 @@ describe('Testing removeSingleConstraintInfo', () => {
|
|||||||
pathToNode,
|
pathToNode,
|
||||||
argPosition,
|
argPosition,
|
||||||
ast,
|
ast,
|
||||||
programMemory
|
execState.memory
|
||||||
)
|
)
|
||||||
if (!mod) return new Error('mod is undefined')
|
if (!mod) return new Error('mod is undefined')
|
||||||
const recastCode = recast(mod.modifiedAst)
|
const recastCode = recast(mod.modifiedAst)
|
||||||
@ -686,7 +686,7 @@ describe('Testing removeSingleConstraintInfo', () => {
|
|||||||
const ast = parse(code)
|
const ast = parse(code)
|
||||||
if (err(ast)) throw ast
|
if (err(ast)) throw ast
|
||||||
|
|
||||||
const programMemory = await enginelessExecutor(ast)
|
const execState = await enginelessExecutor(ast)
|
||||||
const lineOfInterest = expectedFinish.split('(')[0] + '('
|
const lineOfInterest = expectedFinish.split('(')[0] + '('
|
||||||
const range: [number, number] = [
|
const range: [number, number] = [
|
||||||
code.indexOf(lineOfInterest) + 1,
|
code.indexOf(lineOfInterest) + 1,
|
||||||
@ -711,7 +711,7 @@ describe('Testing removeSingleConstraintInfo', () => {
|
|||||||
pathToNode,
|
pathToNode,
|
||||||
argPosition,
|
argPosition,
|
||||||
ast,
|
ast,
|
||||||
programMemory
|
execState.memory
|
||||||
)
|
)
|
||||||
if (!mod) return new Error('mod is undefined')
|
if (!mod) return new Error('mod is undefined')
|
||||||
const recastCode = recast(mod.modifiedAst)
|
const recastCode = recast(mod.modifiedAst)
|
||||||
@ -882,7 +882,7 @@ const sketch002 = startSketchOn({
|
|||||||
// const lineOfInterest = 'line([-2.94, 2.7], %)'
|
// const lineOfInterest = 'line([-2.94, 2.7], %)'
|
||||||
const ast = parse(codeBefore)
|
const ast = parse(codeBefore)
|
||||||
if (err(ast)) throw ast
|
if (err(ast)) throw ast
|
||||||
const programMemory = await enginelessExecutor(ast)
|
const execState = await enginelessExecutor(ast)
|
||||||
|
|
||||||
// deleteFromSelection
|
// deleteFromSelection
|
||||||
const range: [number, number] = [
|
const range: [number, number] = [
|
||||||
@ -895,7 +895,7 @@ const sketch002 = startSketchOn({
|
|||||||
range,
|
range,
|
||||||
type,
|
type,
|
||||||
},
|
},
|
||||||
programMemory,
|
execState.memory,
|
||||||
async () => {
|
async () => {
|
||||||
await new Promise((resolve) => setTimeout(resolve, 100))
|
await new Promise((resolve) => setTimeout(resolve, 100))
|
||||||
return {
|
return {
|
||||||
|
@ -18,6 +18,7 @@ import {
|
|||||||
ProgramMemory,
|
ProgramMemory,
|
||||||
SourceRange,
|
SourceRange,
|
||||||
sketchGroupFromKclValue,
|
sketchGroupFromKclValue,
|
||||||
|
ExpressionStatement,
|
||||||
} from './wasm'
|
} from './wasm'
|
||||||
import {
|
import {
|
||||||
isNodeSafeToReplacePath,
|
isNodeSafeToReplacePath,
|
||||||
@ -80,18 +81,24 @@ export function addStartProfileAt(
|
|||||||
pathToNode: PathToNode,
|
pathToNode: PathToNode,
|
||||||
at: [number, number]
|
at: [number, number]
|
||||||
): { modifiedAst: Program; pathToNode: PathToNode } | Error {
|
): { modifiedAst: Program; pathToNode: PathToNode } | Error {
|
||||||
const _node1 = getNodeFromPath<VariableDeclaration>(
|
const _node1 = getNodeFromPath<VariableDeclaration>(node, pathToNode, [
|
||||||
node,
|
'VariableDeclaration',
|
||||||
pathToNode,
|
'ExpressionStatement',
|
||||||
'VariableDeclaration'
|
]) as { node: { type: string } } | Error
|
||||||
)
|
|
||||||
if (err(_node1)) return _node1
|
if (err(_node1)) return _node1
|
||||||
const variableDeclaration = _node1.node
|
|
||||||
if (variableDeclaration.type !== 'VariableDeclaration') {
|
|
||||||
return new Error('variableDeclaration.init.type !== PipeExpression')
|
|
||||||
}
|
|
||||||
const _node = { ...node }
|
const _node = { ...node }
|
||||||
const init = variableDeclaration.declarations[0].init
|
let expr: Expr
|
||||||
|
let variableDeclaration: VariableDeclaration | undefined
|
||||||
|
if (_node1.node.type === 'VariableDeclaration') {
|
||||||
|
const node: VariableDeclaration = _node1.node as VariableDeclaration
|
||||||
|
variableDeclaration = node
|
||||||
|
expr = node.declarations[0].init
|
||||||
|
} else if (_node1.node.type === 'ExpressionStatement') {
|
||||||
|
const node: ExpressionStatement = _node1.node as ExpressionStatement
|
||||||
|
expr = node.expression
|
||||||
|
} else {
|
||||||
|
return new Error(`Unrecognized node type ${_node1.node.type}`)
|
||||||
|
}
|
||||||
const startProfileAt = createCallExpressionStdLib('startProfileAt', [
|
const startProfileAt = createCallExpressionStdLib('startProfileAt', [
|
||||||
createArrayExpression([
|
createArrayExpression([
|
||||||
createLiteral(roundOff(at[0])),
|
createLiteral(roundOff(at[0])),
|
||||||
@ -99,11 +106,11 @@ export function addStartProfileAt(
|
|||||||
]),
|
]),
|
||||||
createPipeSubstitution(),
|
createPipeSubstitution(),
|
||||||
])
|
])
|
||||||
if (init.type === 'PipeExpression') {
|
if (expr.type === 'PipeExpression') {
|
||||||
init.body.splice(1, 0, startProfileAt)
|
expr.body.splice(1, 0, startProfileAt)
|
||||||
} else {
|
} else if (variableDeclaration) {
|
||||||
variableDeclaration.declarations[0].init = createPipeExpression([
|
variableDeclaration.declarations[0].init = createPipeExpression([
|
||||||
init,
|
expr,
|
||||||
startProfileAt,
|
startProfileAt,
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
@ -45,11 +45,11 @@ const variableBelowShouldNotBeIncluded = 3
|
|||||||
const rangeStart = code.indexOf('// selection-range-7ish-before-this') - 7
|
const rangeStart = code.indexOf('// selection-range-7ish-before-this') - 7
|
||||||
const ast = parse(code)
|
const ast = parse(code)
|
||||||
if (err(ast)) throw ast
|
if (err(ast)) throw ast
|
||||||
const programMemory = await enginelessExecutor(ast)
|
const execState = await enginelessExecutor(ast)
|
||||||
|
|
||||||
const { variables, bodyPath, insertIndex } = findAllPreviousVariables(
|
const { variables, bodyPath, insertIndex } = findAllPreviousVariables(
|
||||||
ast,
|
ast,
|
||||||
programMemory,
|
execState.memory,
|
||||||
[rangeStart, rangeStart]
|
[rangeStart, rangeStart]
|
||||||
)
|
)
|
||||||
expect(variables).toEqual([
|
expect(variables).toEqual([
|
||||||
@ -351,11 +351,11 @@ const part001 = startSketchAt([-1.41, 3.46])
|
|||||||
const ast = parse(exampleCode)
|
const ast = parse(exampleCode)
|
||||||
if (err(ast)) throw ast
|
if (err(ast)) throw ast
|
||||||
|
|
||||||
const programMemory = await enginelessExecutor(ast)
|
const execState = await enginelessExecutor(ast)
|
||||||
const result = hasExtrudeSketchGroup({
|
const result = hasExtrudeSketchGroup({
|
||||||
ast,
|
ast,
|
||||||
selection: { type: 'default', range: [100, 101] },
|
selection: { type: 'default', range: [100, 101] },
|
||||||
programMemory,
|
programMemory: execState.memory,
|
||||||
})
|
})
|
||||||
expect(result).toEqual(true)
|
expect(result).toEqual(true)
|
||||||
})
|
})
|
||||||
@ -370,11 +370,11 @@ const part001 = startSketchAt([-1.41, 3.46])
|
|||||||
const ast = parse(exampleCode)
|
const ast = parse(exampleCode)
|
||||||
if (err(ast)) throw ast
|
if (err(ast)) throw ast
|
||||||
|
|
||||||
const programMemory = await enginelessExecutor(ast)
|
const execState = await enginelessExecutor(ast)
|
||||||
const result = hasExtrudeSketchGroup({
|
const result = hasExtrudeSketchGroup({
|
||||||
ast,
|
ast,
|
||||||
selection: { type: 'default', range: [100, 101] },
|
selection: { type: 'default', range: [100, 101] },
|
||||||
programMemory,
|
programMemory: execState.memory,
|
||||||
})
|
})
|
||||||
expect(result).toEqual(true)
|
expect(result).toEqual(true)
|
||||||
})
|
})
|
||||||
@ -383,11 +383,11 @@ const part001 = startSketchAt([-1.41, 3.46])
|
|||||||
const ast = parse(exampleCode)
|
const ast = parse(exampleCode)
|
||||||
if (err(ast)) throw ast
|
if (err(ast)) throw ast
|
||||||
|
|
||||||
const programMemory = await enginelessExecutor(ast)
|
const execState = await enginelessExecutor(ast)
|
||||||
const result = hasExtrudeSketchGroup({
|
const result = hasExtrudeSketchGroup({
|
||||||
ast,
|
ast,
|
||||||
selection: { type: 'default', range: [10, 11] },
|
selection: { type: 'default', range: [10, 11] },
|
||||||
programMemory,
|
programMemory: execState.memory,
|
||||||
})
|
})
|
||||||
expect(result).toEqual(false)
|
expect(result).toEqual(false)
|
||||||
})
|
})
|
||||||
|
@ -795,7 +795,7 @@ export function isSingleCursorInPipe(
|
|||||||
const pathToNode = getNodePathFromSourceRange(ast, selection.range)
|
const pathToNode = getNodePathFromSourceRange(ast, selection.range)
|
||||||
const nodeTypes = pathToNode.map(([, type]) => type)
|
const nodeTypes = pathToNode.map(([, type]) => type)
|
||||||
if (nodeTypes.includes('FunctionExpression')) return false
|
if (nodeTypes.includes('FunctionExpression')) return false
|
||||||
if (!nodeTypes.includes('VariableDeclaration')) return false
|
// if (!nodeTypes.includes('VariableDeclaration')) return false
|
||||||
if (nodeTypes.includes('PipeExpression')) return true
|
if (nodeTypes.includes('PipeExpression')) return true
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -12,17 +12,20 @@ interface CommonCommandProperties {
|
|||||||
|
|
||||||
export interface PlaneArtifact {
|
export interface PlaneArtifact {
|
||||||
type: 'plane'
|
type: 'plane'
|
||||||
|
id: ArtifactId
|
||||||
pathIds: Array<ArtifactId>
|
pathIds: Array<ArtifactId>
|
||||||
codeRef: CommonCommandProperties
|
codeRef: CommonCommandProperties
|
||||||
}
|
}
|
||||||
export interface PlaneArtifactRich {
|
export interface PlaneArtifactRich {
|
||||||
type: 'plane'
|
type: 'plane'
|
||||||
|
id: ArtifactId
|
||||||
paths: Array<PathArtifact>
|
paths: Array<PathArtifact>
|
||||||
codeRef: CommonCommandProperties
|
codeRef: CommonCommandProperties
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PathArtifact {
|
export interface PathArtifact {
|
||||||
type: 'path'
|
type: 'path'
|
||||||
|
id: ArtifactId
|
||||||
planeId: ArtifactId
|
planeId: ArtifactId
|
||||||
segIds: Array<ArtifactId>
|
segIds: Array<ArtifactId>
|
||||||
sweepId: ArtifactId
|
sweepId: ArtifactId
|
||||||
@ -32,10 +35,12 @@ export interface PathArtifact {
|
|||||||
|
|
||||||
interface solid2D {
|
interface solid2D {
|
||||||
type: 'solid2D'
|
type: 'solid2D'
|
||||||
|
id: ArtifactId
|
||||||
pathId: ArtifactId
|
pathId: ArtifactId
|
||||||
}
|
}
|
||||||
export interface PathArtifactRich {
|
export interface PathArtifactRich {
|
||||||
type: 'path'
|
type: 'path'
|
||||||
|
id: ArtifactId
|
||||||
plane: PlaneArtifact | WallArtifact
|
plane: PlaneArtifact | WallArtifact
|
||||||
segments: Array<SegmentArtifact>
|
segments: Array<SegmentArtifact>
|
||||||
sweep: SweepArtifact
|
sweep: SweepArtifact
|
||||||
@ -44,6 +49,7 @@ export interface PathArtifactRich {
|
|||||||
|
|
||||||
export interface SegmentArtifact {
|
export interface SegmentArtifact {
|
||||||
type: 'segment'
|
type: 'segment'
|
||||||
|
id: ArtifactId
|
||||||
pathId: ArtifactId
|
pathId: ArtifactId
|
||||||
surfaceId: ArtifactId
|
surfaceId: ArtifactId
|
||||||
edgeIds: Array<ArtifactId>
|
edgeIds: Array<ArtifactId>
|
||||||
@ -52,6 +58,7 @@ export interface SegmentArtifact {
|
|||||||
}
|
}
|
||||||
interface SegmentArtifactRich {
|
interface SegmentArtifactRich {
|
||||||
type: 'segment'
|
type: 'segment'
|
||||||
|
id: ArtifactId
|
||||||
path: PathArtifact
|
path: PathArtifact
|
||||||
surf: WallArtifact
|
surf: WallArtifact
|
||||||
edges: Array<SweepEdge>
|
edges: Array<SweepEdge>
|
||||||
@ -63,14 +70,16 @@ interface SegmentArtifactRich {
|
|||||||
interface SweepArtifact {
|
interface SweepArtifact {
|
||||||
type: 'sweep'
|
type: 'sweep'
|
||||||
subType: 'extrusion' | 'revolve'
|
subType: 'extrusion' | 'revolve'
|
||||||
|
id: ArtifactId
|
||||||
pathId: string
|
pathId: string
|
||||||
surfaceIds: Array<string>
|
surfaceIds: Array<ArtifactId>
|
||||||
edgeIds: Array<string>
|
edgeIds: Array<ArtifactId>
|
||||||
codeRef: CommonCommandProperties
|
codeRef: CommonCommandProperties
|
||||||
}
|
}
|
||||||
interface SweepArtifactRich {
|
interface SweepArtifactRich {
|
||||||
type: 'sweep'
|
type: 'sweep'
|
||||||
subType: 'extrusion' | 'revolve'
|
subType: 'extrusion' | 'revolve'
|
||||||
|
id: ArtifactId
|
||||||
path: PathArtifact
|
path: PathArtifact
|
||||||
surfaces: Array<WallArtifact | CapArtifact>
|
surfaces: Array<WallArtifact | CapArtifact>
|
||||||
edges: Array<SweepEdge>
|
edges: Array<SweepEdge>
|
||||||
@ -79,6 +88,7 @@ interface SweepArtifactRich {
|
|||||||
|
|
||||||
interface WallArtifact {
|
interface WallArtifact {
|
||||||
type: 'wall'
|
type: 'wall'
|
||||||
|
id: ArtifactId
|
||||||
segId: ArtifactId
|
segId: ArtifactId
|
||||||
edgeCutEdgeIds: Array<ArtifactId>
|
edgeCutEdgeIds: Array<ArtifactId>
|
||||||
sweepId: ArtifactId
|
sweepId: ArtifactId
|
||||||
@ -86,6 +96,7 @@ interface WallArtifact {
|
|||||||
}
|
}
|
||||||
interface CapArtifact {
|
interface CapArtifact {
|
||||||
type: 'cap'
|
type: 'cap'
|
||||||
|
id: ArtifactId
|
||||||
subType: 'start' | 'end'
|
subType: 'start' | 'end'
|
||||||
edgeCutEdgeIds: Array<ArtifactId>
|
edgeCutEdgeIds: Array<ArtifactId>
|
||||||
sweepId: ArtifactId
|
sweepId: ArtifactId
|
||||||
@ -94,6 +105,7 @@ interface CapArtifact {
|
|||||||
|
|
||||||
interface SweepEdge {
|
interface SweepEdge {
|
||||||
type: 'sweepEdge'
|
type: 'sweepEdge'
|
||||||
|
id: ArtifactId
|
||||||
segId: ArtifactId
|
segId: ArtifactId
|
||||||
sweepId: ArtifactId
|
sweepId: ArtifactId
|
||||||
subType: 'opposite' | 'adjacent'
|
subType: 'opposite' | 'adjacent'
|
||||||
@ -102,6 +114,7 @@ interface SweepEdge {
|
|||||||
/** A edgeCut is a more generic term for both fillet or chamfer */
|
/** A edgeCut is a more generic term for both fillet or chamfer */
|
||||||
interface EdgeCut {
|
interface EdgeCut {
|
||||||
type: 'edgeCut'
|
type: 'edgeCut'
|
||||||
|
id: ArtifactId
|
||||||
subType: 'fillet' | 'chamfer'
|
subType: 'fillet' | 'chamfer'
|
||||||
consumedEdgeId: ArtifactId
|
consumedEdgeId: ArtifactId
|
||||||
edgeIds: Array<ArtifactId>
|
edgeIds: Array<ArtifactId>
|
||||||
@ -111,6 +124,7 @@ interface EdgeCut {
|
|||||||
|
|
||||||
interface EdgeCutEdge {
|
interface EdgeCutEdge {
|
||||||
type: 'edgeCutEdge'
|
type: 'edgeCutEdge'
|
||||||
|
id: ArtifactId
|
||||||
edgeCutId: ArtifactId
|
edgeCutId: ArtifactId
|
||||||
surfaceId: ArtifactId
|
surfaceId: ArtifactId
|
||||||
}
|
}
|
||||||
@ -215,7 +229,7 @@ function mergeArtifacts(
|
|||||||
* It does not mutate the map directly, but returns an array of artifacts to update
|
* It does not mutate the map directly, but returns an array of artifacts to update
|
||||||
*
|
*
|
||||||
* @param currentPlaneId is only needed for `start_path` commands because this command does not have a pathId
|
* @param currentPlaneId is only needed for `start_path` commands because this command does not have a pathId
|
||||||
* instead it relies on the id used with the `enable_sketch_mode` command, so this much be kept track of
|
* instead it relies on the id used with the `enable_sketch_mode` command, so this must be kept track of
|
||||||
* outside of this function. It would be good to update the `start_path` command to include the planeId so we
|
* outside of this function. It would be good to update the `start_path` command to include the planeId so we
|
||||||
* can remove this.
|
* can remove this.
|
||||||
*/
|
*/
|
||||||
@ -258,6 +272,7 @@ export function getArtifactsToUpdate({
|
|||||||
id: currentPlaneId,
|
id: currentPlaneId,
|
||||||
artifact: {
|
artifact: {
|
||||||
type: 'wall',
|
type: 'wall',
|
||||||
|
id: currentPlaneId,
|
||||||
segId: existingPlane.segId,
|
segId: existingPlane.segId,
|
||||||
edgeCutEdgeIds: existingPlane.edgeCutEdgeIds,
|
edgeCutEdgeIds: existingPlane.edgeCutEdgeIds,
|
||||||
sweepId: existingPlane.sweepId,
|
sweepId: existingPlane.sweepId,
|
||||||
@ -267,7 +282,10 @@ export function getArtifactsToUpdate({
|
|||||||
]
|
]
|
||||||
} else {
|
} else {
|
||||||
return [
|
return [
|
||||||
{ id: currentPlaneId, artifact: { type: 'plane', pathIds, codeRef } },
|
{
|
||||||
|
id: currentPlaneId,
|
||||||
|
artifact: { type: 'plane', id: currentPlaneId, pathIds, codeRef },
|
||||||
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
} else if (cmd.type === 'start_path') {
|
} else if (cmd.type === 'start_path') {
|
||||||
@ -275,6 +293,7 @@ export function getArtifactsToUpdate({
|
|||||||
id,
|
id,
|
||||||
artifact: {
|
artifact: {
|
||||||
type: 'path',
|
type: 'path',
|
||||||
|
id,
|
||||||
segIds: [],
|
segIds: [],
|
||||||
planeId: currentPlaneId,
|
planeId: currentPlaneId,
|
||||||
sweepId: '',
|
sweepId: '',
|
||||||
@ -287,7 +306,7 @@ export function getArtifactsToUpdate({
|
|||||||
if (plane?.type === 'plane') {
|
if (plane?.type === 'plane') {
|
||||||
returnArr.push({
|
returnArr.push({
|
||||||
id: currentPlaneId,
|
id: currentPlaneId,
|
||||||
artifact: { type: 'plane', pathIds: [id], codeRef },
|
artifact: { type: 'plane', id: currentPlaneId, pathIds: [id], codeRef },
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if (plane?.type === 'wall') {
|
if (plane?.type === 'wall') {
|
||||||
@ -295,6 +314,7 @@ export function getArtifactsToUpdate({
|
|||||||
id: currentPlaneId,
|
id: currentPlaneId,
|
||||||
artifact: {
|
artifact: {
|
||||||
type: 'wall',
|
type: 'wall',
|
||||||
|
id: currentPlaneId,
|
||||||
segId: plane.segId,
|
segId: plane.segId,
|
||||||
edgeCutEdgeIds: plane.edgeCutEdgeIds,
|
edgeCutEdgeIds: plane.edgeCutEdgeIds,
|
||||||
sweepId: plane.sweepId,
|
sweepId: plane.sweepId,
|
||||||
@ -309,6 +329,7 @@ export function getArtifactsToUpdate({
|
|||||||
id,
|
id,
|
||||||
artifact: {
|
artifact: {
|
||||||
type: 'segment',
|
type: 'segment',
|
||||||
|
id,
|
||||||
pathId,
|
pathId,
|
||||||
surfaceId: '',
|
surfaceId: '',
|
||||||
edgeIds: [],
|
edgeIds: [],
|
||||||
@ -318,21 +339,22 @@ export function getArtifactsToUpdate({
|
|||||||
const path = getArtifact(pathId)
|
const path = getArtifact(pathId)
|
||||||
if (path?.type === 'path')
|
if (path?.type === 'path')
|
||||||
returnArr.push({
|
returnArr.push({
|
||||||
id: pathId,
|
id: path.id,
|
||||||
artifact: { ...path, segIds: [id] },
|
artifact: { ...path, segIds: [id] },
|
||||||
})
|
})
|
||||||
if (
|
if (
|
||||||
response?.type === 'modeling' &&
|
response?.type === 'modeling' &&
|
||||||
response.data.modeling_response.type === 'close_path'
|
response.data.modeling_response.type === 'close_path'
|
||||||
) {
|
) {
|
||||||
|
const id = response.data.modeling_response.data.face_id
|
||||||
returnArr.push({
|
returnArr.push({
|
||||||
id: response.data.modeling_response.data.face_id,
|
id,
|
||||||
artifact: { type: 'solid2D', pathId },
|
artifact: { type: 'solid2D', id, pathId },
|
||||||
})
|
})
|
||||||
const path = getArtifact(pathId)
|
const path = getArtifact(pathId)
|
||||||
if (path?.type === 'path')
|
if (path?.type === 'path')
|
||||||
returnArr.push({
|
returnArr.push({
|
||||||
id: pathId,
|
id: path.id,
|
||||||
artifact: {
|
artifact: {
|
||||||
...path,
|
...path,
|
||||||
solid2dId: response.data.modeling_response.data.face_id,
|
solid2dId: response.data.modeling_response.data.face_id,
|
||||||
@ -347,6 +369,7 @@ export function getArtifactsToUpdate({
|
|||||||
artifact: {
|
artifact: {
|
||||||
type: 'sweep',
|
type: 'sweep',
|
||||||
subType: subType,
|
subType: subType,
|
||||||
|
id,
|
||||||
pathId: cmd.target,
|
pathId: cmd.target,
|
||||||
surfaceIds: [],
|
surfaceIds: [],
|
||||||
edgeIds: [],
|
edgeIds: [],
|
||||||
@ -356,7 +379,7 @@ export function getArtifactsToUpdate({
|
|||||||
const path = getArtifact(cmd.target)
|
const path = getArtifact(cmd.target)
|
||||||
if (path?.type === 'path')
|
if (path?.type === 'path')
|
||||||
returnArr.push({
|
returnArr.push({
|
||||||
id: cmd.target,
|
id: path.id,
|
||||||
artifact: { ...path, sweepId: id },
|
artifact: { ...path, sweepId: id },
|
||||||
})
|
})
|
||||||
return returnArr
|
return returnArr
|
||||||
@ -378,6 +401,7 @@ export function getArtifactsToUpdate({
|
|||||||
id: face_id,
|
id: face_id,
|
||||||
artifact: {
|
artifact: {
|
||||||
type: 'wall',
|
type: 'wall',
|
||||||
|
id: face_id,
|
||||||
segId: curve_id,
|
segId: curve_id,
|
||||||
edgeCutEdgeIds: [],
|
edgeCutEdgeIds: [],
|
||||||
sweepId: path.sweepId,
|
sweepId: path.sweepId,
|
||||||
@ -385,7 +409,7 @@ export function getArtifactsToUpdate({
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
returnArr.push({
|
returnArr.push({
|
||||||
id: curve_id,
|
id: seg.id,
|
||||||
artifact: { ...seg, surfaceId: face_id },
|
artifact: { ...seg, surfaceId: face_id },
|
||||||
})
|
})
|
||||||
const sweep = getArtifact(path.sweepId)
|
const sweep = getArtifact(path.sweepId)
|
||||||
@ -394,6 +418,7 @@ export function getArtifactsToUpdate({
|
|||||||
id: path.sweepId,
|
id: path.sweepId,
|
||||||
artifact: {
|
artifact: {
|
||||||
...sweep,
|
...sweep,
|
||||||
|
id: path.sweepId,
|
||||||
surfaceIds: [face_id],
|
surfaceIds: [face_id],
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@ -410,6 +435,7 @@ export function getArtifactsToUpdate({
|
|||||||
id: face_id,
|
id: face_id,
|
||||||
artifact: {
|
artifact: {
|
||||||
type: 'cap',
|
type: 'cap',
|
||||||
|
id: face_id,
|
||||||
subType: cap === 'bottom' ? 'start' : 'end',
|
subType: cap === 'bottom' ? 'start' : 'end',
|
||||||
edgeCutEdgeIds: [],
|
edgeCutEdgeIds: [],
|
||||||
sweepId: path.sweepId,
|
sweepId: path.sweepId,
|
||||||
@ -419,7 +445,7 @@ export function getArtifactsToUpdate({
|
|||||||
const sweep = getArtifact(path.sweepId)
|
const sweep = getArtifact(path.sweepId)
|
||||||
if (sweep?.type !== 'sweep') return
|
if (sweep?.type !== 'sweep') return
|
||||||
returnArr.push({
|
returnArr.push({
|
||||||
id: path.sweepId,
|
id: sweep.id,
|
||||||
artifact: {
|
artifact: {
|
||||||
...sweep,
|
...sweep,
|
||||||
surfaceIds: [face_id],
|
surfaceIds: [face_id],
|
||||||
@ -460,6 +486,7 @@ export function getArtifactsToUpdate({
|
|||||||
cmd.type === 'solid3d_get_next_adjacent_edge'
|
cmd.type === 'solid3d_get_next_adjacent_edge'
|
||||||
? 'adjacent'
|
? 'adjacent'
|
||||||
: 'opposite',
|
: 'opposite',
|
||||||
|
id: response.data.modeling_response.data.edge,
|
||||||
segId: cmd.edge_id,
|
segId: cmd.edge_id,
|
||||||
sweepId: path.sweepId,
|
sweepId: path.sweepId,
|
||||||
},
|
},
|
||||||
@ -468,6 +495,7 @@ export function getArtifactsToUpdate({
|
|||||||
id: cmd.edge_id,
|
id: cmd.edge_id,
|
||||||
artifact: {
|
artifact: {
|
||||||
...segment,
|
...segment,
|
||||||
|
id: cmd.edge_id,
|
||||||
edgeIds: [response.data.modeling_response.data.edge],
|
edgeIds: [response.data.modeling_response.data.edge],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -475,6 +503,7 @@ export function getArtifactsToUpdate({
|
|||||||
id: path.sweepId,
|
id: path.sweepId,
|
||||||
artifact: {
|
artifact: {
|
||||||
...sweep,
|
...sweep,
|
||||||
|
id: path.sweepId,
|
||||||
edgeIds: [response.data.modeling_response.data.edge],
|
edgeIds: [response.data.modeling_response.data.edge],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -484,6 +513,7 @@ export function getArtifactsToUpdate({
|
|||||||
id,
|
id,
|
||||||
artifact: {
|
artifact: {
|
||||||
type: 'edgeCut',
|
type: 'edgeCut',
|
||||||
|
id,
|
||||||
subType: cmd.cut_type,
|
subType: cmd.cut_type,
|
||||||
consumedEdgeId: cmd.edge_id,
|
consumedEdgeId: cmd.edge_id,
|
||||||
edgeIds: [],
|
edgeIds: [],
|
||||||
@ -494,7 +524,7 @@ export function getArtifactsToUpdate({
|
|||||||
const consumedEdge = getArtifact(cmd.edge_id)
|
const consumedEdge = getArtifact(cmd.edge_id)
|
||||||
if (consumedEdge?.type === 'segment') {
|
if (consumedEdge?.type === 'segment') {
|
||||||
returnArr.push({
|
returnArr.push({
|
||||||
id: cmd.edge_id,
|
id: consumedEdge.id,
|
||||||
artifact: { ...consumedEdge, edgeCutId: id },
|
artifact: { ...consumedEdge, edgeCutId: id },
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -574,6 +604,7 @@ export function expandPlane(
|
|||||||
)
|
)
|
||||||
return {
|
return {
|
||||||
type: 'plane',
|
type: 'plane',
|
||||||
|
id: plane.id,
|
||||||
paths: Array.from(paths.values()),
|
paths: Array.from(paths.values()),
|
||||||
codeRef: plane.codeRef,
|
codeRef: plane.codeRef,
|
||||||
}
|
}
|
||||||
@ -602,6 +633,7 @@ export function expandPath(
|
|||||||
if (err(plane)) return plane
|
if (err(plane)) return plane
|
||||||
return {
|
return {
|
||||||
type: 'path',
|
type: 'path',
|
||||||
|
id: path.id,
|
||||||
segments: Array.from(segs.values()),
|
segments: Array.from(segs.values()),
|
||||||
sweep,
|
sweep,
|
||||||
plane,
|
plane,
|
||||||
@ -629,6 +661,7 @@ export function expandSweep(
|
|||||||
return {
|
return {
|
||||||
type: 'sweep',
|
type: 'sweep',
|
||||||
subType: 'extrusion',
|
subType: 'extrusion',
|
||||||
|
id: sweep.id,
|
||||||
surfaces: Array.from(surfs.values()),
|
surfaces: Array.from(surfs.values()),
|
||||||
edges: Array.from(edges.values()),
|
edges: Array.from(edges.values()),
|
||||||
path,
|
path,
|
||||||
@ -664,6 +697,7 @@ export function expandSegment(
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
type: 'segment',
|
type: 'segment',
|
||||||
|
id: segment.id,
|
||||||
path,
|
path,
|
||||||
surf,
|
surf,
|
||||||
edges: Array.from(edges.values()),
|
edges: Array.from(edges.values()),
|
||||||
@ -785,3 +819,56 @@ export function getSweepFromSuspectedPath(
|
|||||||
artifactGraph
|
artifactGraph
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the plane or face from a selection.
|
||||||
|
*
|
||||||
|
* TODO: Handle sketch on face.
|
||||||
|
*/
|
||||||
|
export function getPlaneOrFaceFromSelection(
|
||||||
|
id: ArtifactId,
|
||||||
|
artifactGraph: ArtifactGraph
|
||||||
|
): PlaneArtifactRich | null {
|
||||||
|
const selection = artifactGraph.get(id)
|
||||||
|
if (!selection) return null
|
||||||
|
if (selection.type === 'solid2D') {
|
||||||
|
const path = artifactGraph.get(selection.pathId)
|
||||||
|
if (path?.type !== 'path') return null
|
||||||
|
const plane = artifactGraph.get(path.planeId)
|
||||||
|
if (plane?.type !== 'plane') return null
|
||||||
|
return expandPlane(plane, artifactGraph)
|
||||||
|
} else if (selection.type === 'wall' || selection.type === 'cap') {
|
||||||
|
const sweep = artifactGraph.get(selection.sweepId)
|
||||||
|
if (sweep?.type !== 'sweep') return null
|
||||||
|
const path = artifactGraph.get(sweep.pathId)
|
||||||
|
if (path?.type !== 'path') return null
|
||||||
|
const plane = artifactGraph.get(path.planeId)
|
||||||
|
// TODO: For sketch on face, this won't be a plane.
|
||||||
|
if (plane?.type !== 'plane') return null
|
||||||
|
return expandPlane(plane, artifactGraph)
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the path from a selection.
|
||||||
|
*/
|
||||||
|
export function getPathFromSelection(
|
||||||
|
id: ArtifactId,
|
||||||
|
artifactGraph: ArtifactGraph
|
||||||
|
): PathArtifact | null {
|
||||||
|
const selection = artifactGraph.get(id)
|
||||||
|
if (!selection) return null
|
||||||
|
if (selection.type === 'solid2D') {
|
||||||
|
const path = artifactGraph.get(selection.pathId)
|
||||||
|
if (path?.type !== 'path') return null
|
||||||
|
return path
|
||||||
|
} else if (selection.type === 'wall' || selection.type === 'cap') {
|
||||||
|
const sweep = artifactGraph.get(selection.sweepId)
|
||||||
|
if (sweep?.type !== 'sweep') return null
|
||||||
|
const path = artifactGraph.get(sweep.pathId)
|
||||||
|
if (path?.type !== 'path') return null
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
@ -117,11 +117,11 @@ describe('testing changeSketchArguments', () => {
|
|||||||
const ast = parse(code)
|
const ast = parse(code)
|
||||||
if (err(ast)) return ast
|
if (err(ast)) return ast
|
||||||
|
|
||||||
const programMemory = await enginelessExecutor(ast)
|
const execState = await enginelessExecutor(ast)
|
||||||
const sourceStart = code.indexOf(lineToChange)
|
const sourceStart = code.indexOf(lineToChange)
|
||||||
const changeSketchArgsRetVal = changeSketchArguments(
|
const changeSketchArgsRetVal = changeSketchArguments(
|
||||||
ast,
|
ast,
|
||||||
programMemory,
|
execState.memory,
|
||||||
{
|
{
|
||||||
type: 'sourceRange',
|
type: 'sourceRange',
|
||||||
sourceRange: [sourceStart, sourceStart + lineToChange.length],
|
sourceRange: [sourceStart, sourceStart + lineToChange.length],
|
||||||
@ -150,12 +150,12 @@ const mySketch001 = startSketchOn('XY')
|
|||||||
const ast = parse(code)
|
const ast = parse(code)
|
||||||
if (err(ast)) return ast
|
if (err(ast)) return ast
|
||||||
|
|
||||||
const programMemory = await enginelessExecutor(ast)
|
const execState = await enginelessExecutor(ast)
|
||||||
const sourceStart = code.indexOf(lineToChange)
|
const sourceStart = code.indexOf(lineToChange)
|
||||||
expect(sourceStart).toBe(95)
|
expect(sourceStart).toBe(95)
|
||||||
const newSketchLnRetVal = addNewSketchLn({
|
const newSketchLnRetVal = addNewSketchLn({
|
||||||
node: ast,
|
node: ast,
|
||||||
programMemory,
|
programMemory: execState.memory,
|
||||||
input: {
|
input: {
|
||||||
type: 'straight-segment',
|
type: 'straight-segment',
|
||||||
from: [0, 0],
|
from: [0, 0],
|
||||||
@ -186,7 +186,7 @@ const mySketch001 = startSketchOn('XY')
|
|||||||
|
|
||||||
const modifiedAst2 = addCloseToPipe({
|
const modifiedAst2 = addCloseToPipe({
|
||||||
node: ast,
|
node: ast,
|
||||||
programMemory,
|
programMemory: execState.memory,
|
||||||
pathToNode: [
|
pathToNode: [
|
||||||
['body', ''],
|
['body', ''],
|
||||||
[0, 'index'],
|
[0, 'index'],
|
||||||
@ -230,7 +230,7 @@ describe('testing addTagForSketchOnFace', () => {
|
|||||||
const pathToNode = getNodePathFromSourceRange(ast, sourceRange)
|
const pathToNode = getNodePathFromSourceRange(ast, sourceRange)
|
||||||
const sketchOnFaceRetVal = addTagForSketchOnFace(
|
const sketchOnFaceRetVal = addTagForSketchOnFace(
|
||||||
{
|
{
|
||||||
// previousProgramMemory: programMemory, // redundant?
|
// previousProgramMemory: execState.memory, // redundant?
|
||||||
pathToNode,
|
pathToNode,
|
||||||
node: ast,
|
node: ast,
|
||||||
},
|
},
|
||||||
|
@ -40,7 +40,7 @@ async function testingSwapSketchFnCall({
|
|||||||
const ast = parse(inputCode)
|
const ast = parse(inputCode)
|
||||||
if (err(ast)) return Promise.reject(ast)
|
if (err(ast)) return Promise.reject(ast)
|
||||||
|
|
||||||
const programMemory = await enginelessExecutor(ast)
|
const execState = await enginelessExecutor(ast)
|
||||||
const selections = {
|
const selections = {
|
||||||
codeBasedSelections: [range],
|
codeBasedSelections: [range],
|
||||||
otherSelections: [],
|
otherSelections: [],
|
||||||
@ -51,7 +51,7 @@ async function testingSwapSketchFnCall({
|
|||||||
return Promise.reject(new Error('transformInfos undefined'))
|
return Promise.reject(new Error('transformInfos undefined'))
|
||||||
const ast2 = transformAstSketchLines({
|
const ast2 = transformAstSketchLines({
|
||||||
ast,
|
ast,
|
||||||
programMemory,
|
programMemory: execState.memory,
|
||||||
selectionRanges: selections,
|
selectionRanges: selections,
|
||||||
transformInfos,
|
transformInfos,
|
||||||
referenceSegName: '',
|
referenceSegName: '',
|
||||||
@ -366,10 +366,10 @@ const part001 = startSketchOn('XY')
|
|||||||
|> line([2.14, 1.35], %) // normal-segment
|
|> line([2.14, 1.35], %) // normal-segment
|
||||||
|> xLine(3.54, %)`
|
|> xLine(3.54, %)`
|
||||||
it('normal case works', async () => {
|
it('normal case works', async () => {
|
||||||
const programMemory = await enginelessExecutor(parse(code))
|
const execState = await enginelessExecutor(parse(code))
|
||||||
const index = code.indexOf('// normal-segment') - 7
|
const index = code.indexOf('// normal-segment') - 7
|
||||||
const sg = sketchGroupFromKclValue(
|
const sg = sketchGroupFromKclValue(
|
||||||
programMemory.get('part001'),
|
execState.memory.get('part001'),
|
||||||
'part001'
|
'part001'
|
||||||
) as SketchGroup
|
) as SketchGroup
|
||||||
const _segment = getSketchSegmentFromSourceRange(sg, [index, index])
|
const _segment = getSketchSegmentFromSourceRange(sg, [index, index])
|
||||||
@ -383,11 +383,11 @@ const part001 = startSketchOn('XY')
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
it('verify it works when the segment is in the `start` property', async () => {
|
it('verify it works when the segment is in the `start` property', async () => {
|
||||||
const programMemory = await enginelessExecutor(parse(code))
|
const execState = await enginelessExecutor(parse(code))
|
||||||
const index = code.indexOf('// segment-in-start') - 7
|
const index = code.indexOf('// segment-in-start') - 7
|
||||||
const _segment = getSketchSegmentFromSourceRange(
|
const _segment = getSketchSegmentFromSourceRange(
|
||||||
sketchGroupFromKclValue(
|
sketchGroupFromKclValue(
|
||||||
programMemory.get('part001'),
|
execState.memory.get('part001'),
|
||||||
'part001'
|
'part001'
|
||||||
) as SketchGroup,
|
) as SketchGroup,
|
||||||
[index, index]
|
[index, index]
|
||||||
|
@ -220,7 +220,7 @@ const part001 = startSketchOn('XY')
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const programMemory = await enginelessExecutor(ast)
|
const execState = await enginelessExecutor(ast)
|
||||||
const transformInfos = getTransformInfos(
|
const transformInfos = getTransformInfos(
|
||||||
makeSelections(selectionRanges.slice(1)),
|
makeSelections(selectionRanges.slice(1)),
|
||||||
ast,
|
ast,
|
||||||
@ -231,7 +231,7 @@ const part001 = startSketchOn('XY')
|
|||||||
ast,
|
ast,
|
||||||
selectionRanges: makeSelections(selectionRanges),
|
selectionRanges: makeSelections(selectionRanges),
|
||||||
transformInfos,
|
transformInfos,
|
||||||
programMemory,
|
programMemory: execState.memory,
|
||||||
})
|
})
|
||||||
if (err(newAst)) return Promise.reject(newAst)
|
if (err(newAst)) return Promise.reject(newAst)
|
||||||
|
|
||||||
@ -311,7 +311,7 @@ const part001 = startSketchOn('XY')
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const programMemory = await enginelessExecutor(ast)
|
const execState = await enginelessExecutor(ast)
|
||||||
const transformInfos = getTransformInfos(
|
const transformInfos = getTransformInfos(
|
||||||
makeSelections(selectionRanges),
|
makeSelections(selectionRanges),
|
||||||
ast,
|
ast,
|
||||||
@ -322,7 +322,7 @@ const part001 = startSketchOn('XY')
|
|||||||
ast,
|
ast,
|
||||||
selectionRanges: makeSelections(selectionRanges),
|
selectionRanges: makeSelections(selectionRanges),
|
||||||
transformInfos,
|
transformInfos,
|
||||||
programMemory,
|
programMemory: execState.memory,
|
||||||
referenceSegName: '',
|
referenceSegName: '',
|
||||||
})
|
})
|
||||||
if (err(newAst)) return Promise.reject(newAst)
|
if (err(newAst)) return Promise.reject(newAst)
|
||||||
@ -373,7 +373,7 @@ const part001 = startSketchOn('XY')
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const programMemory = await enginelessExecutor(ast)
|
const execState = await enginelessExecutor(ast)
|
||||||
const transformInfos = getTransformInfos(
|
const transformInfos = getTransformInfos(
|
||||||
makeSelections(selectionRanges),
|
makeSelections(selectionRanges),
|
||||||
ast,
|
ast,
|
||||||
@ -384,7 +384,7 @@ const part001 = startSketchOn('XY')
|
|||||||
ast,
|
ast,
|
||||||
selectionRanges: makeSelections(selectionRanges),
|
selectionRanges: makeSelections(selectionRanges),
|
||||||
transformInfos,
|
transformInfos,
|
||||||
programMemory,
|
programMemory: execState.memory,
|
||||||
referenceSegName: '',
|
referenceSegName: '',
|
||||||
})
|
})
|
||||||
if (err(newAst)) return Promise.reject(newAst)
|
if (err(newAst)) return Promise.reject(newAst)
|
||||||
@ -470,7 +470,7 @@ async function helperThing(
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const programMemory = await enginelessExecutor(ast)
|
const execState = await enginelessExecutor(ast)
|
||||||
const transformInfos = getTransformInfos(
|
const transformInfos = getTransformInfos(
|
||||||
makeSelections(selectionRanges.slice(1)),
|
makeSelections(selectionRanges.slice(1)),
|
||||||
ast,
|
ast,
|
||||||
@ -481,7 +481,7 @@ async function helperThing(
|
|||||||
ast,
|
ast,
|
||||||
selectionRanges: makeSelections(selectionRanges),
|
selectionRanges: makeSelections(selectionRanges),
|
||||||
transformInfos,
|
transformInfos,
|
||||||
programMemory,
|
programMemory: execState.memory,
|
||||||
})
|
})
|
||||||
|
|
||||||
if (err(newAst)) return Promise.reject(newAst)
|
if (err(newAst)) return Promise.reject(newAst)
|
||||||
|
@ -17,9 +17,9 @@ describe('testing angledLineThatIntersects', () => {
|
|||||||
offset: ${offset},
|
offset: ${offset},
|
||||||
}, %, $yo2)
|
}, %, $yo2)
|
||||||
const intersect = segEndX(yo2)`
|
const intersect = segEndX(yo2)`
|
||||||
const mem = await enginelessExecutor(parse(code('-1')))
|
const execState = await enginelessExecutor(parse(code('-1')))
|
||||||
expect(mem.get('intersect')?.value).toBe(1 + Math.sqrt(2))
|
expect(execState.memory.get('intersect')?.value).toBe(1 + Math.sqrt(2))
|
||||||
const noOffset = await enginelessExecutor(parse(code('0')))
|
const noOffset = await enginelessExecutor(parse(code('0')))
|
||||||
expect(noOffset.get('intersect')?.value).toBeCloseTo(1)
|
expect(noOffset.memory.get('intersect')?.value).toBeCloseTo(1)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -37,6 +37,8 @@ import { Configuration } from 'wasm-lib/kcl/bindings/Configuration'
|
|||||||
import { DeepPartial } from 'lib/types'
|
import { DeepPartial } from 'lib/types'
|
||||||
import { ProjectConfiguration } from 'wasm-lib/kcl/bindings/ProjectConfiguration'
|
import { ProjectConfiguration } from 'wasm-lib/kcl/bindings/ProjectConfiguration'
|
||||||
import { SketchGroup } from '../wasm-lib/kcl/bindings/SketchGroup'
|
import { SketchGroup } from '../wasm-lib/kcl/bindings/SketchGroup'
|
||||||
|
import { ArtifactId } from 'wasm-lib/kcl/bindings/ArtifactId'
|
||||||
|
import { Artifact } from 'wasm-lib/kcl/bindings/Artifact'
|
||||||
|
|
||||||
export type { Program } from '../wasm-lib/kcl/bindings/Program'
|
export type { Program } from '../wasm-lib/kcl/bindings/Program'
|
||||||
export type { Expr } from '../wasm-lib/kcl/bindings/Expr'
|
export type { Expr } from '../wasm-lib/kcl/bindings/Expr'
|
||||||
@ -136,6 +138,34 @@ export const parse = (code: string | Error): Program | Error => {
|
|||||||
|
|
||||||
export type PathToNode = [string | number, string][]
|
export type PathToNode = [string | number, string][]
|
||||||
|
|
||||||
|
interface RawExecState {
|
||||||
|
memory: RawProgramMemory
|
||||||
|
artifacts: { [key: ArtifactId]: Artifact }
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ExecState {
|
||||||
|
memory: ProgramMemory
|
||||||
|
artifacts: { [key: ArtifactId]: Artifact }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an empty ExecState. This is useful on init to prevent needing an
|
||||||
|
* Option.
|
||||||
|
*/
|
||||||
|
export function emptyExecState(): ExecState {
|
||||||
|
return {
|
||||||
|
memory: ProgramMemory.empty(),
|
||||||
|
artifacts: {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function execStateFromRaw(raw: RawExecState): ExecState {
|
||||||
|
return {
|
||||||
|
memory: ProgramMemory.fromRaw(raw.memory),
|
||||||
|
artifacts: raw.artifacts,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
interface Memory {
|
interface Memory {
|
||||||
[key: string]: KclValue
|
[key: string]: KclValue
|
||||||
}
|
}
|
||||||
@ -353,12 +383,49 @@ export function sketchGroupFromKclValue(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function optionalSketchGroupFromKclValue(
|
||||||
|
value: KclValue
|
||||||
|
): SketchGroup | null {
|
||||||
|
if (value.type === 'UserVal' && value.value.type === 'SketchGroup')
|
||||||
|
return value.value
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
export function kclValueFromArtifactId(
|
||||||
|
execState: ExecState,
|
||||||
|
id: ArtifactId
|
||||||
|
): KclValue | null {
|
||||||
|
const artifact = execState.artifacts[id]
|
||||||
|
if (!artifact) {
|
||||||
|
console.warn('kclValueFromArtifactId id not found', id, execState)
|
||||||
|
}
|
||||||
|
if (!artifact) return null
|
||||||
|
return artifact.value
|
||||||
|
}
|
||||||
|
|
||||||
|
export function sketchGroupFromArtifactId(
|
||||||
|
execState: ExecState,
|
||||||
|
id: ArtifactId
|
||||||
|
): SketchGroup | null {
|
||||||
|
const kclValue = kclValueFromArtifactId(execState, id)
|
||||||
|
if (!kclValue) {
|
||||||
|
console.warn('sketchGroupFromArtifactId id not found', id)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
const sketch = optionalSketchGroupFromKclValue(kclValue)
|
||||||
|
if (!sketch) {
|
||||||
|
console.warn('sketchGroupFromArtifactId not a SketchGroup', kclValue)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
return sketch
|
||||||
|
}
|
||||||
|
|
||||||
export const executor = async (
|
export const executor = async (
|
||||||
node: Program,
|
node: Program,
|
||||||
programMemory: ProgramMemory | Error = ProgramMemory.empty(),
|
programMemory: ProgramMemory | Error = ProgramMemory.empty(),
|
||||||
engineCommandManager: EngineCommandManager,
|
engineCommandManager: EngineCommandManager,
|
||||||
isMock: boolean = false
|
isMock: boolean = false
|
||||||
): Promise<ProgramMemory> => {
|
): Promise<ExecState> => {
|
||||||
if (err(programMemory)) return Promise.reject(programMemory)
|
if (err(programMemory)) return Promise.reject(programMemory)
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
@ -380,7 +447,7 @@ export const _executor = async (
|
|||||||
programMemory: ProgramMemory | Error = ProgramMemory.empty(),
|
programMemory: ProgramMemory | Error = ProgramMemory.empty(),
|
||||||
engineCommandManager: EngineCommandManager,
|
engineCommandManager: EngineCommandManager,
|
||||||
isMock: boolean
|
isMock: boolean
|
||||||
): Promise<ProgramMemory> => {
|
): Promise<ExecState> => {
|
||||||
if (err(programMemory)) return Promise.reject(programMemory)
|
if (err(programMemory)) return Promise.reject(programMemory)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -392,7 +459,7 @@ export const _executor = async (
|
|||||||
baseUnit =
|
baseUnit =
|
||||||
(await getSettingsState)()?.modeling.defaultUnit.current || 'mm'
|
(await getSettingsState)()?.modeling.defaultUnit.current || 'mm'
|
||||||
}
|
}
|
||||||
const memory: RawProgramMemory = await execute_wasm(
|
const execState: RawExecState = await execute_wasm(
|
||||||
JSON.stringify(node),
|
JSON.stringify(node),
|
||||||
JSON.stringify(programMemory.toRaw()),
|
JSON.stringify(programMemory.toRaw()),
|
||||||
baseUnit,
|
baseUnit,
|
||||||
@ -400,7 +467,7 @@ export const _executor = async (
|
|||||||
fileSystemManager,
|
fileSystemManager,
|
||||||
isMock
|
isMock
|
||||||
)
|
)
|
||||||
return ProgramMemory.fromRaw(memory)
|
return execStateFromRaw(execState)
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
console.log(e)
|
console.log(e)
|
||||||
const parsed: RustKclError = JSON.parse(e.toString())
|
const parsed: RustKclError = JSON.parse(e.toString())
|
||||||
|
@ -58,10 +58,12 @@ export type Selection =
|
|||||||
| 'line'
|
| 'line'
|
||||||
| 'arc'
|
| 'arc'
|
||||||
| 'all'
|
| 'all'
|
||||||
|
artifactId?: ArtifactId
|
||||||
range: SourceRange
|
range: SourceRange
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
type: 'opposite-edgeCut' | 'adjacent-edgeCut' | 'base-edgeCut'
|
type: 'opposite-edgeCut' | 'adjacent-edgeCut' | 'base-edgeCut'
|
||||||
|
artifactId?: ArtifactId
|
||||||
range: SourceRange
|
range: SourceRange
|
||||||
// TODO this is a temporary measure that well be made redundant with: https://github.com/KittyCAD/modeling-app/pull/3836
|
// TODO this is a temporary measure that well be made redundant with: https://github.com/KittyCAD/modeling-app/pull/3836
|
||||||
secondaryRange: SourceRange
|
secondaryRange: SourceRange
|
||||||
@ -108,7 +110,11 @@ export async function getEventForSelectWithPoint({
|
|||||||
type: 'Set selection',
|
type: 'Set selection',
|
||||||
data: {
|
data: {
|
||||||
selectionType: 'singleCodeCursor',
|
selectionType: 'singleCodeCursor',
|
||||||
selection: { range: codeRef.range, type: 'solid2D' },
|
selection: {
|
||||||
|
artifactId: data.entity_id,
|
||||||
|
range: codeRef.range,
|
||||||
|
type: 'solid2D',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -120,6 +126,7 @@ export async function getEventForSelectWithPoint({
|
|||||||
data: {
|
data: {
|
||||||
selectionType: 'singleCodeCursor',
|
selectionType: 'singleCodeCursor',
|
||||||
selection: {
|
selection: {
|
||||||
|
artifactId: data.entity_id,
|
||||||
range: codeRef.range,
|
range: codeRef.range,
|
||||||
type: _artifact?.subType === 'end' ? 'end-cap' : 'start-cap',
|
type: _artifact?.subType === 'end' ? 'end-cap' : 'start-cap',
|
||||||
},
|
},
|
||||||
@ -136,7 +143,11 @@ export async function getEventForSelectWithPoint({
|
|||||||
type: 'Set selection',
|
type: 'Set selection',
|
||||||
data: {
|
data: {
|
||||||
selectionType: 'singleCodeCursor',
|
selectionType: 'singleCodeCursor',
|
||||||
selection: { range: codeRef.range, type: 'extrude-wall' },
|
selection: {
|
||||||
|
artifactId: data.entity_id,
|
||||||
|
range: codeRef.range,
|
||||||
|
type: 'extrude-wall',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -145,7 +156,11 @@ export async function getEventForSelectWithPoint({
|
|||||||
type: 'Set selection',
|
type: 'Set selection',
|
||||||
data: {
|
data: {
|
||||||
selectionType: 'singleCodeCursor',
|
selectionType: 'singleCodeCursor',
|
||||||
selection: { range: _artifact.codeRef.range, type: 'default' },
|
selection: {
|
||||||
|
artifactId: data.entity_id,
|
||||||
|
range: _artifact.codeRef.range,
|
||||||
|
type: 'default',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -807,16 +822,18 @@ export function updateSelections(
|
|||||||
selection?.type === 'opposite-edgeCut'
|
selection?.type === 'opposite-edgeCut'
|
||||||
)
|
)
|
||||||
return {
|
return {
|
||||||
|
artifactId: selection?.artifactId,
|
||||||
range: [node.start, node.end],
|
range: [node.start, node.end],
|
||||||
type: selection?.type,
|
type: selection?.type,
|
||||||
secondaryRange: selection?.secondaryRange,
|
secondaryRange: selection?.secondaryRange,
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
|
artifactId: selection?.artifactId,
|
||||||
range: [node.start, node.end],
|
range: [node.start, node.end],
|
||||||
type: selection?.type,
|
type: selection?.type,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.filter((x?: Selection) => x !== undefined) as Selection[]
|
.filter((x?: Selection) => x !== undefined)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
codeBasedSelections:
|
codeBasedSelections:
|
||||||
|
@ -1,4 +1,10 @@
|
|||||||
import { Program, ProgramMemory, _executor, SourceRange } from '../lang/wasm'
|
import {
|
||||||
|
Program,
|
||||||
|
ProgramMemory,
|
||||||
|
_executor,
|
||||||
|
SourceRange,
|
||||||
|
ExecState,
|
||||||
|
} from '../lang/wasm'
|
||||||
import {
|
import {
|
||||||
EngineCommandManager,
|
EngineCommandManager,
|
||||||
EngineCommandManagerEvents,
|
EngineCommandManagerEvents,
|
||||||
@ -78,7 +84,7 @@ class MockEngineCommandManager {
|
|||||||
export async function enginelessExecutor(
|
export async function enginelessExecutor(
|
||||||
ast: Program | Error,
|
ast: Program | Error,
|
||||||
pm: ProgramMemory | Error = ProgramMemory.empty()
|
pm: ProgramMemory | Error = ProgramMemory.empty()
|
||||||
): Promise<ProgramMemory> {
|
): Promise<ExecState> {
|
||||||
if (err(ast)) return Promise.reject(ast)
|
if (err(ast)) return Promise.reject(ast)
|
||||||
if (err(pm)) return Promise.reject(pm)
|
if (err(pm)) return Promise.reject(pm)
|
||||||
|
|
||||||
@ -88,15 +94,15 @@ export async function enginelessExecutor(
|
|||||||
}) as any as EngineCommandManager
|
}) as any as EngineCommandManager
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
mockEngineCommandManager.startNewSession()
|
mockEngineCommandManager.startNewSession()
|
||||||
const programMemory = await _executor(ast, pm, mockEngineCommandManager, true)
|
const execState = await _executor(ast, pm, mockEngineCommandManager, true)
|
||||||
await mockEngineCommandManager.waitForAllCommands()
|
await mockEngineCommandManager.waitForAllCommands()
|
||||||
return programMemory
|
return execState
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function executor(
|
export async function executor(
|
||||||
ast: Program,
|
ast: Program,
|
||||||
pm: ProgramMemory = ProgramMemory.empty()
|
pm: ProgramMemory = ProgramMemory.empty()
|
||||||
): Promise<ProgramMemory> {
|
): Promise<ExecState> {
|
||||||
const engineCommandManager = new EngineCommandManager()
|
const engineCommandManager = new EngineCommandManager()
|
||||||
engineCommandManager.start({
|
engineCommandManager.start({
|
||||||
setIsStreamReady: () => {},
|
setIsStreamReady: () => {},
|
||||||
@ -117,14 +123,9 @@ export async function executor(
|
|||||||
toSync(async () => {
|
toSync(async () => {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
engineCommandManager.startNewSession()
|
engineCommandManager.startNewSession()
|
||||||
const programMemory = await _executor(
|
const execState = await _executor(ast, pm, engineCommandManager, false)
|
||||||
ast,
|
|
||||||
pm,
|
|
||||||
engineCommandManager,
|
|
||||||
false
|
|
||||||
)
|
|
||||||
await engineCommandManager.waitForAllCommands()
|
await engineCommandManager.waitForAllCommands()
|
||||||
resolve(programMemory)
|
resolve(execState)
|
||||||
}, reportRejection)
|
}, reportRejection)
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -97,7 +97,7 @@ export function useCalculateKclExpression({
|
|||||||
})
|
})
|
||||||
if (trap(error, { suppress: true })) return
|
if (trap(error, { suppress: true })) return
|
||||||
}
|
}
|
||||||
const { programMemory } = await executeAst({
|
const { execState } = await executeAst({
|
||||||
ast,
|
ast,
|
||||||
engineCommandManager,
|
engineCommandManager,
|
||||||
useFakeExecutor: true,
|
useFakeExecutor: true,
|
||||||
@ -111,7 +111,7 @@ export function useCalculateKclExpression({
|
|||||||
const init =
|
const init =
|
||||||
resultDeclaration?.type === 'VariableDeclaration' &&
|
resultDeclaration?.type === 'VariableDeclaration' &&
|
||||||
resultDeclaration?.declarations?.[0]?.init
|
resultDeclaration?.declarations?.[0]?.init
|
||||||
const result = programMemory?.get('__result__')?.value
|
const result = execState.memory?.get('__result__')?.value
|
||||||
setCalcResult(typeof result === 'number' ? String(result) : 'NAN')
|
setCalcResult(typeof result === 'number' ? String(result) : 'NAN')
|
||||||
init && setValueNode(init)
|
init && setValueNode(init)
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
import {
|
import {
|
||||||
|
Expr,
|
||||||
|
ExpressionStatement,
|
||||||
PathToNode,
|
PathToNode,
|
||||||
|
PipeExpression,
|
||||||
VariableDeclaration,
|
VariableDeclaration,
|
||||||
VariableDeclarator,
|
VariableDeclarator,
|
||||||
parse,
|
parse,
|
||||||
@ -2116,15 +2119,24 @@ export function isEditingExistingSketch({
|
|||||||
// should check that the variable declaration is a pipeExpression
|
// should check that the variable declaration is a pipeExpression
|
||||||
// and that the pipeExpression contains a "startProfileAt" callExpression
|
// and that the pipeExpression contains a "startProfileAt" callExpression
|
||||||
if (!sketchDetails?.sketchPathToNode) return false
|
if (!sketchDetails?.sketchPathToNode) return false
|
||||||
const variableDeclaration = getNodeFromPath<VariableDeclarator>(
|
const _node1 = getNodeFromPath<VariableDeclaration | ExpressionStatement>(
|
||||||
kclManager.ast,
|
kclManager.ast,
|
||||||
sketchDetails.sketchPathToNode,
|
sketchDetails.sketchPathToNode,
|
||||||
'VariableDeclarator'
|
['VariableDeclaration', 'ExpressionStatement']
|
||||||
)
|
) as { node: { type: string } } | Error
|
||||||
if (err(variableDeclaration)) return false
|
if (err(_node1)) return false
|
||||||
if (variableDeclaration.node.type !== 'VariableDeclarator') return false
|
let expr: Expr
|
||||||
const pipeExpression = variableDeclaration.node.init
|
if (_node1.node.type === 'VariableDeclaration') {
|
||||||
if (pipeExpression.type !== 'PipeExpression') return false
|
const varDecl = _node1.node as VariableDeclaration
|
||||||
|
expr = varDecl.declarations[0].init
|
||||||
|
} else if (_node1.node.type === 'ExpressionStatement') {
|
||||||
|
const exprStatement = _node1.node as ExpressionStatement
|
||||||
|
expr = exprStatement.expression
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (expr.type !== 'PipeExpression') return false
|
||||||
|
const pipeExpression: PipeExpression = expr
|
||||||
const hasStartProfileAt = pipeExpression.body.some(
|
const hasStartProfileAt = pipeExpression.body.some(
|
||||||
(item) =>
|
(item) =>
|
||||||
item.type === 'CallExpression' && item.callee.name === 'startProfileAt'
|
item.type === 'CallExpression' && item.callee.name === 'startProfileAt'
|
||||||
|
1
src/wasm-lib/Cargo.lock
generated
1
src/wasm-lib/Cargo.lock
generated
@ -1430,6 +1430,7 @@ dependencies = [
|
|||||||
"databake",
|
"databake",
|
||||||
"derive-docs",
|
"derive-docs",
|
||||||
"expectorate",
|
"expectorate",
|
||||||
|
"fnv",
|
||||||
"form_urlencoded",
|
"form_urlencoded",
|
||||||
"futures",
|
"futures",
|
||||||
"git_rev",
|
"git_rev",
|
||||||
|
@ -21,6 +21,7 @@ convert_case = "0.6.0"
|
|||||||
dashmap = "6.1.0"
|
dashmap = "6.1.0"
|
||||||
databake = { version = "0.1.8", features = ["derive"] }
|
databake = { version = "0.1.8", features = ["derive"] }
|
||||||
derive-docs = { version = "0.1.28", path = "../derive-docs" }
|
derive-docs = { version = "0.1.28", path = "../derive-docs" }
|
||||||
|
fnv = "1.0.7"
|
||||||
form_urlencoded = "1.2.1"
|
form_urlencoded = "1.2.1"
|
||||||
futures = { version = "0.3.30" }
|
futures = { version = "0.3.30" }
|
||||||
git_rev = "0.1.0"
|
git_rev = "0.1.0"
|
||||||
|
@ -4,6 +4,7 @@ use std::{collections::HashMap, sync::Arc};
|
|||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use async_recursion::async_recursion;
|
use async_recursion::async_recursion;
|
||||||
|
use fnv::FnvHashMap;
|
||||||
use kcmc::{
|
use kcmc::{
|
||||||
each_cmd as mcmd,
|
each_cmd as mcmd,
|
||||||
ok_response::{output::TakeSnapshot, OkModelingCmdResponse},
|
ok_response::{output::TakeSnapshot, OkModelingCmdResponse},
|
||||||
@ -45,6 +46,16 @@ pub struct ExecState {
|
|||||||
/// The current value of the pipe operator returned from the previous
|
/// The current value of the pipe operator returned from the previous
|
||||||
/// expression. If we're not currently in a pipeline, this will be None.
|
/// expression. If we're not currently in a pipeline, this will be None.
|
||||||
pub pipe_value: Option<KclValue>,
|
pub pipe_value: Option<KclValue>,
|
||||||
|
/// Artifacts created by the program. It's safe to use a faster hash
|
||||||
|
/// algorithm since all keys are UUIDs that we generate.
|
||||||
|
pub artifacts: FnvHashMap<ArtifactId, Artifact>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ExecState {
|
||||||
|
/// Insert or update artifact by ID.
|
||||||
|
pub(crate) fn put_artifact(&mut self, id: ArtifactId, value: KclValue) {
|
||||||
|
self.artifacts.insert(id, Artifact { id, value });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
@ -396,6 +407,21 @@ impl From<Vec<Box<ExtrudeGroup>>> for KclValue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Deserialize, Serialize, ts_rs::TS, JsonSchema)]
|
||||||
|
pub struct ArtifactId(uuid::Uuid);
|
||||||
|
|
||||||
|
impl ArtifactId {
|
||||||
|
pub(crate) fn new(id: uuid::Uuid) -> Self {
|
||||||
|
Self(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, ts_rs::TS, JsonSchema)]
|
||||||
|
pub struct Artifact {
|
||||||
|
pub id: ArtifactId,
|
||||||
|
pub value: KclValue,
|
||||||
|
}
|
||||||
|
|
||||||
/// A geometry.
|
/// A geometry.
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||||
#[ts(export)]
|
#[ts(export)]
|
||||||
|
@ -15,17 +15,17 @@ use uuid::Uuid;
|
|||||||
use crate::{
|
use crate::{
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
executor::{
|
executor::{
|
||||||
ExecState, ExtrudeGroup, ExtrudeGroupSet, ExtrudeSurface, GeoMeta, KclValue, Path, SketchGroup, SketchGroupSet,
|
ArtifactId, ExecState, ExtrudeGroup, ExtrudeGroupSet, ExtrudeSurface, GeoMeta, KclValue, Path, SketchGroup,
|
||||||
SketchSurface,
|
SketchGroupSet, SketchSurface,
|
||||||
},
|
},
|
||||||
std::Args,
|
std::Args,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Extrudes by a given amount.
|
/// Extrudes by a given amount.
|
||||||
pub async fn extrude(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
pub async fn extrude(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let (length, sketch_group_set) = args.get_number_sketch_group_set()?;
|
let (length, sketch_group_set) = args.get_number_sketch_group_set()?;
|
||||||
|
|
||||||
let result = inner_extrude(length, sketch_group_set, args).await?;
|
let result = inner_extrude(length, sketch_group_set, exec_state, args).await?;
|
||||||
|
|
||||||
Ok(result.into())
|
Ok(result.into())
|
||||||
}
|
}
|
||||||
@ -79,7 +79,12 @@ pub async fn extrude(_exec_state: &mut ExecState, args: Args) -> Result<KclValue
|
|||||||
#[stdlib {
|
#[stdlib {
|
||||||
name = "extrude"
|
name = "extrude"
|
||||||
}]
|
}]
|
||||||
async fn inner_extrude(length: f64, sketch_group_set: SketchGroupSet, args: Args) -> Result<ExtrudeGroupSet, KclError> {
|
async fn inner_extrude(
|
||||||
|
length: f64,
|
||||||
|
sketch_group_set: SketchGroupSet,
|
||||||
|
exec_state: &mut ExecState,
|
||||||
|
args: Args,
|
||||||
|
) -> Result<ExtrudeGroupSet, KclError> {
|
||||||
let id = uuid::Uuid::new_v4();
|
let id = uuid::Uuid::new_v4();
|
||||||
|
|
||||||
// Extrude the element(s).
|
// Extrude the element(s).
|
||||||
@ -120,7 +125,7 @@ async fn inner_extrude(length: f64, sketch_group_set: SketchGroupSet, args: Args
|
|||||||
ModelingCmd::SketchModeDisable(mcmd::SketchModeDisable {}),
|
ModelingCmd::SketchModeDisable(mcmd::SketchModeDisable {}),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
extrude_groups.push(do_post_extrude(sketch_group.clone(), length, args.clone()).await?);
|
extrude_groups.push(do_post_extrude(sketch_group.clone(), length, exec_state, args.clone()).await?);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(extrude_groups.into())
|
Ok(extrude_groups.into())
|
||||||
@ -129,6 +134,7 @@ async fn inner_extrude(length: f64, sketch_group_set: SketchGroupSet, args: Args
|
|||||||
pub(crate) async fn do_post_extrude(
|
pub(crate) async fn do_post_extrude(
|
||||||
sketch_group: SketchGroup,
|
sketch_group: SketchGroup,
|
||||||
length: f64,
|
length: f64,
|
||||||
|
exec_state: &mut ExecState,
|
||||||
args: Args,
|
args: Args,
|
||||||
) -> Result<Box<ExtrudeGroup>, KclError> {
|
) -> Result<Box<ExtrudeGroup>, KclError> {
|
||||||
// Bring the object to the front of the scene.
|
// Bring the object to the front of the scene.
|
||||||
@ -276,7 +282,7 @@ pub(crate) async fn do_post_extrude(
|
|||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
Ok(Box::new(ExtrudeGroup {
|
let extrude_group = Box::new(ExtrudeGroup {
|
||||||
// Ok so you would think that the id would be the id of the extrude group,
|
// Ok so you would think that the id would be the id of the extrude group,
|
||||||
// that we passed in to the function, but it's actually the id of the
|
// that we passed in to the function, but it's actually the id of the
|
||||||
// sketch group.
|
// sketch group.
|
||||||
@ -288,7 +294,13 @@ pub(crate) async fn do_post_extrude(
|
|||||||
start_cap_id,
|
start_cap_id,
|
||||||
end_cap_id,
|
end_cap_id,
|
||||||
edge_cuts: vec![],
|
edge_cuts: vec![],
|
||||||
}))
|
});
|
||||||
|
exec_state.put_artifact(
|
||||||
|
ArtifactId::new(extrude_group.id),
|
||||||
|
KclValue::ExtrudeGroup(extrude_group.clone()),
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(extrude_group)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
@ -50,10 +50,10 @@ impl Default for LoftData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Create a 3D surface or solid by interpolating between two or more sketches.
|
/// Create a 3D surface or solid by interpolating between two or more sketches.
|
||||||
pub async fn loft(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
pub async fn loft(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let (sketch_groups, data): (Vec<SketchGroup>, Option<LoftData>) = args.get_sketch_groups_and_data()?;
|
let (sketch_groups, data): (Vec<SketchGroup>, Option<LoftData>) = args.get_sketch_groups_and_data()?;
|
||||||
|
|
||||||
let extrude_group = inner_loft(sketch_groups, data, args).await?;
|
let extrude_group = inner_loft(sketch_groups, data, exec_state, args).await?;
|
||||||
Ok(KclValue::ExtrudeGroup(extrude_group))
|
Ok(KclValue::ExtrudeGroup(extrude_group))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,6 +138,7 @@ pub async fn loft(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
|
|||||||
async fn inner_loft(
|
async fn inner_loft(
|
||||||
sketch_groups: Vec<SketchGroup>,
|
sketch_groups: Vec<SketchGroup>,
|
||||||
data: Option<LoftData>,
|
data: Option<LoftData>,
|
||||||
|
exec_state: &mut ExecState,
|
||||||
args: Args,
|
args: Args,
|
||||||
) -> Result<Box<ExtrudeGroup>, KclError> {
|
) -> Result<Box<ExtrudeGroup>, KclError> {
|
||||||
// Make sure we have at least two sketches.
|
// Make sure we have at least two sketches.
|
||||||
@ -170,5 +171,5 @@ async fn inner_loft(
|
|||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
// Using the first sketch as the base curve, idk we might want to change this later.
|
// Using the first sketch as the base curve, idk we might want to change this later.
|
||||||
do_post_extrude(sketch_groups[0].clone(), 0.0, args).await
|
do_post_extrude(sketch_groups[0].clone(), 0.0, exec_state, args).await
|
||||||
}
|
}
|
||||||
|
@ -295,7 +295,7 @@ async fn inner_revolve(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
do_post_extrude(sketch_group, 0.0, args).await
|
do_post_extrude(sketch_group, 0.0, exec_state, args).await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -15,7 +15,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
use crate::{
|
use crate::{
|
||||||
ast::types::TagDeclarator,
|
ast::types::TagDeclarator,
|
||||||
errors::KclError,
|
errors::KclError,
|
||||||
executor::{BasePath, ExecState, GeoMeta, KclValue, Path, SketchGroup, SketchSurface},
|
executor::{ArtifactId, BasePath, ExecState, GeoMeta, KclValue, Path, SketchGroup, SketchSurface},
|
||||||
std::Args,
|
std::Args,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -46,6 +46,11 @@ pub async fn circle(exec_state: &mut ExecState, args: Args) -> Result<KclValue,
|
|||||||
args.get_circle_args()?;
|
args.get_circle_args()?;
|
||||||
|
|
||||||
let sketch_group = inner_circle(data, sketch_surface_or_group, tag, exec_state, args).await?;
|
let sketch_group = inner_circle(data, sketch_surface_or_group, tag, exec_state, args).await?;
|
||||||
|
exec_state.put_artifact(
|
||||||
|
ArtifactId::new(sketch_group.id),
|
||||||
|
KclValue::new_user_val(sketch_group.meta.clone(), sketch_group.clone()),
|
||||||
|
);
|
||||||
|
|
||||||
Ok(KclValue::new_user_val(sketch_group.meta.clone(), sketch_group))
|
Ok(KclValue::new_user_val(sketch_group.meta.clone(), sketch_group))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,8 +16,8 @@ use crate::{
|
|||||||
ast::types::TagDeclarator,
|
ast::types::TagDeclarator,
|
||||||
errors::{KclError, KclErrorDetails},
|
errors::{KclError, KclErrorDetails},
|
||||||
executor::{
|
executor::{
|
||||||
BasePath, ExecState, ExtrudeGroup, Face, GeoMeta, KclValue, Path, Plane, PlaneType, Point2d, Point3d,
|
ArtifactId, BasePath, ExecState, ExtrudeGroup, Face, GeoMeta, KclValue, Path, Plane, PlaneType, Point2d,
|
||||||
SketchGroup, SketchGroupSet, SketchSurface, TagEngineInfo, TagIdentifier, UserVal,
|
Point3d, SketchGroup, SketchGroupSet, SketchSurface, TagEngineInfo, TagIdentifier, UserVal,
|
||||||
},
|
},
|
||||||
std::{
|
std::{
|
||||||
utils::{
|
utils::{
|
||||||
@ -93,11 +93,16 @@ pub enum StartOrEnd {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Draw a line to a point.
|
/// Draw a line to a point.
|
||||||
pub async fn line_to(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
pub async fn line_to(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let (to, sketch_group, tag): ([f64; 2], SketchGroup, Option<TagDeclarator>) =
|
let (to, sketch_group, tag): ([f64; 2], SketchGroup, Option<TagDeclarator>) =
|
||||||
args.get_data_and_sketch_group_and_tag()?;
|
args.get_data_and_sketch_group_and_tag()?;
|
||||||
|
|
||||||
let new_sketch_group = inner_line_to(to, sketch_group, tag, args).await?;
|
let new_sketch_group = inner_line_to(to, sketch_group, tag, args).await?;
|
||||||
|
exec_state.put_artifact(
|
||||||
|
ArtifactId::new(new_sketch_group.id),
|
||||||
|
KclValue::new_user_val(new_sketch_group.meta.clone(), new_sketch_group.clone()),
|
||||||
|
);
|
||||||
|
|
||||||
Ok(KclValue::new_user_val(new_sketch_group.meta.clone(), new_sketch_group))
|
Ok(KclValue::new_user_val(new_sketch_group.meta.clone(), new_sketch_group))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -248,11 +253,16 @@ async fn inner_y_line_to(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Draw a line.
|
/// Draw a line.
|
||||||
pub async fn line(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
pub async fn line(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let (delta, sketch_group, tag): ([f64; 2], SketchGroup, Option<TagDeclarator>) =
|
let (delta, sketch_group, tag): ([f64; 2], SketchGroup, Option<TagDeclarator>) =
|
||||||
args.get_data_and_sketch_group_and_tag()?;
|
args.get_data_and_sketch_group_and_tag()?;
|
||||||
|
|
||||||
let new_sketch_group = inner_line(delta, sketch_group, tag, args).await?;
|
let new_sketch_group = inner_line(delta, sketch_group, tag, args).await?;
|
||||||
|
exec_state.put_artifact(
|
||||||
|
ArtifactId::new(new_sketch_group.id),
|
||||||
|
KclValue::new_user_val(new_sketch_group.meta.clone(), new_sketch_group.clone()),
|
||||||
|
);
|
||||||
|
|
||||||
Ok(KclValue::new_user_val(new_sketch_group.meta.clone(), new_sketch_group))
|
Ok(KclValue::new_user_val(new_sketch_group.meta.clone(), new_sketch_group))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1410,10 +1420,14 @@ pub(crate) fn inner_profile_start(sketch_group: SketchGroup) -> Result<[f64; 2],
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Close the current sketch.
|
/// Close the current sketch.
|
||||||
pub async fn close(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
pub async fn close(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
|
||||||
let (sketch_group, tag): (SketchGroup, Option<TagDeclarator>) = args.get_sketch_group_and_optional_tag()?;
|
let (sketch_group, tag): (SketchGroup, Option<TagDeclarator>) = args.get_sketch_group_and_optional_tag()?;
|
||||||
|
|
||||||
let new_sketch_group = inner_close(sketch_group, tag, args).await?;
|
let new_sketch_group = inner_close(sketch_group, tag, args).await?;
|
||||||
|
exec_state.put_artifact(
|
||||||
|
ArtifactId::new(new_sketch_group.id),
|
||||||
|
KclValue::new_user_val(new_sketch_group.meta.clone(), new_sketch_group.clone()),
|
||||||
|
);
|
||||||
|
|
||||||
Ok(KclValue::new_user_val(new_sketch_group.meta.clone(), new_sketch_group))
|
Ok(KclValue::new_user_val(new_sketch_group.meta.clone(), new_sketch_group))
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,7 @@ pub async fn execute_wasm(
|
|||||||
// gloo-serialize crate instead.
|
// gloo-serialize crate instead.
|
||||||
// DO NOT USE serde_wasm_bindgen::to_value(&memory).map_err(|e| e.to_string())
|
// DO NOT USE serde_wasm_bindgen::to_value(&memory).map_err(|e| e.to_string())
|
||||||
// it will break the frontend.
|
// it will break the frontend.
|
||||||
JsValue::from_serde(&exec_state.memory).map_err(|e| e.to_string())
|
JsValue::from_serde(&exec_state).map_err(|e| e.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
// wasm_bindgen wrapper for execute
|
// wasm_bindgen wrapper for execute
|
||||||
|
Reference in New Issue
Block a user