Add Rust side artifacts for startSketchOn face or plane (#4834)
* Add Rust side artifacts for startSketchOn face or plane * move ast digging --------- Co-authored-by: Kurt Hutten Irev-Dev <k.hutten@protonmail.ch>
This commit is contained in:
@ -357,7 +357,10 @@ export class KclManager {
|
||||
}
|
||||
this.ast = { ...ast }
|
||||
// updateArtifactGraph relies on updated executeState/programMemory
|
||||
await this.engineCommandManager.updateArtifactGraph(this.ast)
|
||||
await this.engineCommandManager.updateArtifactGraph(
|
||||
this.ast,
|
||||
execState.artifacts
|
||||
)
|
||||
this._executeCallback()
|
||||
if (!isInterrupted)
|
||||
sceneInfra.modelingSend({ type: 'code edit during sketch' })
|
||||
|
@ -212,7 +212,19 @@ Map {
|
||||
"type": "wall",
|
||||
},
|
||||
"UUID-10" => {
|
||||
"codeRef": undefined,
|
||||
"codeRef": {
|
||||
"pathToNode": [
|
||||
[
|
||||
"body",
|
||||
"",
|
||||
],
|
||||
],
|
||||
"range": [
|
||||
312,
|
||||
344,
|
||||
true,
|
||||
],
|
||||
},
|
||||
"edgeCutEdgeIds": [],
|
||||
"id": "UUID",
|
||||
"pathIds": [
|
||||
|
@ -1,4 +1,10 @@
|
||||
import { makeDefaultPlanes, assertParse, initPromise, Program } from 'lang/wasm'
|
||||
import {
|
||||
makeDefaultPlanes,
|
||||
assertParse,
|
||||
initPromise,
|
||||
Program,
|
||||
ExecState,
|
||||
} from 'lang/wasm'
|
||||
import { Models } from '@kittycad/lib'
|
||||
import {
|
||||
OrderedCommand,
|
||||
@ -123,6 +129,7 @@ type CacheShape = {
|
||||
[key in CodeKey]: {
|
||||
orderedCommands: OrderedCommand[]
|
||||
responseMap: ResponseMap
|
||||
execStateArtifacts: ExecState['artifacts']
|
||||
}
|
||||
}
|
||||
|
||||
@ -154,6 +161,7 @@ beforeAll(async () => {
|
||||
cacheToWriteToFileTemp[codeKey] = {
|
||||
orderedCommands: engineCommandManager.orderedCommands,
|
||||
responseMap: engineCommandManager.responseMap,
|
||||
execStateArtifacts: kclManager.execState.artifacts,
|
||||
}
|
||||
}
|
||||
const cache = JSON.stringify(cacheToWriteToFileTemp)
|
||||
@ -181,9 +189,15 @@ describe('testing createArtifactGraph', () => {
|
||||
orderedCommands,
|
||||
responseMap,
|
||||
ast: _ast,
|
||||
execStateArtifacts,
|
||||
} = getCommands('exampleCodeOffsetPlanes')
|
||||
ast = _ast
|
||||
theMap = createArtifactGraph({ orderedCommands, responseMap, ast })
|
||||
theMap = createArtifactGraph({
|
||||
orderedCommands,
|
||||
responseMap,
|
||||
ast,
|
||||
execStateArtifacts,
|
||||
})
|
||||
})
|
||||
|
||||
it(`there should be one sketch`, () => {
|
||||
@ -226,9 +240,15 @@ describe('testing createArtifactGraph', () => {
|
||||
orderedCommands,
|
||||
responseMap,
|
||||
ast: _ast,
|
||||
execStateArtifacts,
|
||||
} = getCommands('exampleCode1')
|
||||
ast = _ast
|
||||
theMap = createArtifactGraph({ orderedCommands, responseMap, ast })
|
||||
theMap = createArtifactGraph({
|
||||
orderedCommands,
|
||||
responseMap,
|
||||
ast,
|
||||
execStateArtifacts,
|
||||
})
|
||||
})
|
||||
|
||||
it('there should be two planes for the extrusion and the sketch on face', () => {
|
||||
@ -321,9 +341,15 @@ describe('testing createArtifactGraph', () => {
|
||||
orderedCommands,
|
||||
responseMap,
|
||||
ast: _ast,
|
||||
execStateArtifacts,
|
||||
} = getCommands('exampleCodeNo3D')
|
||||
ast = _ast
|
||||
theMap = createArtifactGraph({ orderedCommands, responseMap, ast })
|
||||
theMap = createArtifactGraph({
|
||||
orderedCommands,
|
||||
responseMap,
|
||||
ast,
|
||||
execStateArtifacts,
|
||||
})
|
||||
})
|
||||
|
||||
it('there should be two planes, one for each sketch path', () => {
|
||||
@ -386,9 +412,15 @@ describe('capture graph of sketchOnFaceOnFace...', () => {
|
||||
orderedCommands,
|
||||
responseMap,
|
||||
ast: _ast,
|
||||
execStateArtifacts,
|
||||
} = getCommands('sketchOnFaceOnFaceEtc')
|
||||
ast = _ast
|
||||
theMap = createArtifactGraph({ orderedCommands, responseMap, ast })
|
||||
theMap = createArtifactGraph({
|
||||
orderedCommands,
|
||||
responseMap,
|
||||
ast,
|
||||
execStateArtifacts,
|
||||
})
|
||||
|
||||
// Ostensibly this takes a screen shot of the graph of the artifactGraph
|
||||
// but it's it also tests that all of the id links are correct because if one
|
||||
@ -409,10 +441,12 @@ function getCommands(
|
||||
// these either already exist from the last run, or were created in
|
||||
const orderedCommands = parsed[codeKey].orderedCommands
|
||||
const responseMap = parsed[codeKey].responseMap
|
||||
const execStateArtifacts = parsed[codeKey].execStateArtifacts
|
||||
return {
|
||||
orderedCommands,
|
||||
responseMap,
|
||||
ast,
|
||||
execStateArtifacts,
|
||||
}
|
||||
}
|
||||
|
||||
@ -638,8 +672,14 @@ async function GraphTheGraph(
|
||||
|
||||
describe('testing getArtifactsToUpdate', () => {
|
||||
it('should return an array of artifacts to update', () => {
|
||||
const { orderedCommands, responseMap, ast } = getCommands('exampleCode1')
|
||||
const map = createArtifactGraph({ orderedCommands, responseMap, ast })
|
||||
const { orderedCommands, responseMap, ast, execStateArtifacts } =
|
||||
getCommands('exampleCode1')
|
||||
const map = createArtifactGraph({
|
||||
orderedCommands,
|
||||
responseMap,
|
||||
ast,
|
||||
execStateArtifacts,
|
||||
})
|
||||
const getArtifact = (id: string) => map.get(id)
|
||||
const currentPlaneId = 'UUID-1'
|
||||
const getUpdateObjects = (type: Models['ModelingCmd_type']['type']) => {
|
||||
@ -652,6 +692,7 @@ describe('testing getArtifactsToUpdate', () => {
|
||||
getArtifact,
|
||||
currentPlaneId,
|
||||
ast,
|
||||
execStateArtifacts,
|
||||
})
|
||||
return artifactsToUpdate.map(({ artifact }) => artifact)
|
||||
}
|
||||
@ -779,6 +820,10 @@ describe('testing getArtifactsToUpdate', () => {
|
||||
},
|
||||
{
|
||||
type: 'wall',
|
||||
codeRef: {
|
||||
pathToNode: [['body', '']],
|
||||
range: [312, 344, true],
|
||||
},
|
||||
id: expect.any(String),
|
||||
segId: expect.any(String),
|
||||
edgeCutEdgeIds: [],
|
||||
|
@ -1,16 +1,6 @@
|
||||
import {
|
||||
Expr,
|
||||
PathToNode,
|
||||
Program,
|
||||
SourceRange,
|
||||
VariableDeclaration,
|
||||
} from 'lang/wasm'
|
||||
import { ExecState, Expr, PathToNode, Program, SourceRange } from 'lang/wasm'
|
||||
import { Models } from '@kittycad/lib'
|
||||
import {
|
||||
getNodeFromPath,
|
||||
getNodePathFromSourceRange,
|
||||
traverse,
|
||||
} from 'lang/queryAst'
|
||||
import { getNodePathFromSourceRange } from 'lang/queryAst'
|
||||
import { err } from 'lib/trap'
|
||||
import { engineCommandManager, kclManager } from 'lib/singletons'
|
||||
import { Node } from 'wasm-lib/kcl/bindings/Node'
|
||||
@ -174,10 +164,12 @@ export function createArtifactGraph({
|
||||
orderedCommands,
|
||||
responseMap,
|
||||
ast,
|
||||
execStateArtifacts,
|
||||
}: {
|
||||
orderedCommands: Array<OrderedCommand>
|
||||
responseMap: ResponseMap
|
||||
ast: Node<Program>
|
||||
execStateArtifacts: ExecState['artifacts']
|
||||
}) {
|
||||
const myMap = new Map<ArtifactId, Artifact>()
|
||||
|
||||
@ -199,6 +191,7 @@ export function createArtifactGraph({
|
||||
getArtifact: (id: ArtifactId) => myMap.get(id),
|
||||
currentPlaneId,
|
||||
ast,
|
||||
execStateArtifacts,
|
||||
})
|
||||
artifactsToUpdate.forEach(({ id, artifact }) => {
|
||||
const mergedArtifact = mergeArtifacts(myMap.get(id), artifact)
|
||||
@ -250,6 +243,7 @@ export function getArtifactsToUpdate({
|
||||
responseMap,
|
||||
currentPlaneId,
|
||||
ast,
|
||||
execStateArtifacts,
|
||||
}: {
|
||||
orderedCommand: OrderedCommand
|
||||
responseMap: ResponseMap
|
||||
@ -257,6 +251,7 @@ export function getArtifactsToUpdate({
|
||||
getArtifact: (id: ArtifactId) => Artifact | undefined
|
||||
currentPlaneId: ArtifactId
|
||||
ast: Node<Program>
|
||||
execStateArtifacts: ExecState['artifacts']
|
||||
}): Array<{
|
||||
id: ArtifactId
|
||||
artifact: Artifact
|
||||
@ -292,13 +287,6 @@ export function getArtifactsToUpdate({
|
||||
plane?.type === 'plane' ? plane?.codeRef : { range, pathToNode }
|
||||
const existingPlane = getArtifact(currentPlaneId)
|
||||
if (existingPlane?.type === 'wall') {
|
||||
let existingPlaneCodeRef = existingPlane.codeRef
|
||||
if (!existingPlaneCodeRef) {
|
||||
const astWalkCodeRef = getWallOrCapPlaneCodeRef(ast, codeRef.pathToNode)
|
||||
if (!err(astWalkCodeRef)) {
|
||||
existingPlaneCodeRef = astWalkCodeRef
|
||||
}
|
||||
}
|
||||
return [
|
||||
{
|
||||
id: currentPlaneId,
|
||||
@ -309,18 +297,11 @@ export function getArtifactsToUpdate({
|
||||
edgeCutEdgeIds: existingPlane.edgeCutEdgeIds,
|
||||
sweepId: existingPlane.sweepId,
|
||||
pathIds: existingPlane.pathIds,
|
||||
codeRef: existingPlaneCodeRef,
|
||||
codeRef: existingPlane.codeRef,
|
||||
},
|
||||
},
|
||||
]
|
||||
} else if (existingPlane?.type === 'cap') {
|
||||
let existingPlaneCodeRef = existingPlane.codeRef
|
||||
if (!existingPlaneCodeRef) {
|
||||
const astWalkCodeRef = getWallOrCapPlaneCodeRef(ast, codeRef.pathToNode)
|
||||
if (!err(astWalkCodeRef)) {
|
||||
existingPlaneCodeRef = astWalkCodeRef
|
||||
}
|
||||
}
|
||||
return [
|
||||
{
|
||||
id: currentPlaneId,
|
||||
@ -331,7 +312,7 @@ export function getArtifactsToUpdate({
|
||||
edgeCutEdgeIds: existingPlane.edgeCutEdgeIds,
|
||||
sweepId: existingPlane.sweepId,
|
||||
pathIds: existingPlane.pathIds,
|
||||
codeRef: existingPlaneCodeRef,
|
||||
codeRef: existingPlane.codeRef,
|
||||
},
|
||||
},
|
||||
]
|
||||
@ -467,16 +448,33 @@ export function getArtifactsToUpdate({
|
||||
const path = getArtifact(seg.pathId)
|
||||
if (path?.type === 'path' && seg?.type === 'segment') {
|
||||
lastPath = path
|
||||
returnArr.push({
|
||||
id: face_id,
|
||||
artifact: {
|
||||
const extraArtifact = Object.values(execStateArtifacts).find(
|
||||
(a) => a?.type === 'StartSketchOnFace' && a.faceId === face_id
|
||||
)
|
||||
const sketchOnFaceSourceRange = extraArtifact?.sourceRange
|
||||
const wallArtifact: Artifact = {
|
||||
type: 'wall',
|
||||
id: face_id,
|
||||
segId: curve_id,
|
||||
edgeCutEdgeIds: [],
|
||||
sweepId: path.sweepId,
|
||||
pathIds: [],
|
||||
},
|
||||
}
|
||||
|
||||
if (sketchOnFaceSourceRange) {
|
||||
const range: SourceRange = [
|
||||
sketchOnFaceSourceRange[0],
|
||||
sketchOnFaceSourceRange[1],
|
||||
true,
|
||||
]
|
||||
wallArtifact.codeRef = {
|
||||
range,
|
||||
pathToNode: getNodePathFromSourceRange(ast, range),
|
||||
}
|
||||
}
|
||||
returnArr.push({
|
||||
id: face_id,
|
||||
artifact: wallArtifact,
|
||||
})
|
||||
returnArr.push({
|
||||
id: curve_id,
|
||||
@ -500,16 +498,33 @@ export function getArtifactsToUpdate({
|
||||
if ((cap === 'top' || cap === 'bottom') && face_id) {
|
||||
const path = lastPath
|
||||
if (path?.type === 'path') {
|
||||
returnArr.push({
|
||||
id: face_id,
|
||||
artifact: {
|
||||
const extraArtifact = Object.values(execStateArtifacts).find(
|
||||
(a) => a?.type === 'StartSketchOnFace' && a.faceId === face_id
|
||||
)
|
||||
const sketchOnFaceSourceRange = extraArtifact?.sourceRange
|
||||
const capArtifact: Artifact = {
|
||||
type: 'cap',
|
||||
id: face_id,
|
||||
subType: cap === 'bottom' ? 'start' : 'end',
|
||||
edgeCutEdgeIds: [],
|
||||
sweepId: path.sweepId,
|
||||
pathIds: [],
|
||||
},
|
||||
}
|
||||
if (sketchOnFaceSourceRange) {
|
||||
const range: SourceRange = [
|
||||
sketchOnFaceSourceRange[0],
|
||||
sketchOnFaceSourceRange[1],
|
||||
true,
|
||||
]
|
||||
|
||||
capArtifact.codeRef = {
|
||||
range,
|
||||
pathToNode: getNodePathFromSourceRange(ast, range),
|
||||
}
|
||||
}
|
||||
returnArr.push({
|
||||
id: face_id,
|
||||
artifact: capArtifact,
|
||||
})
|
||||
const sweep = getArtifact(path.sweepId)
|
||||
if (sweep?.type !== 'sweep') return
|
||||
@ -1131,84 +1146,6 @@ function isNodeSafe(node: Expr): boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
/** {@deprecated} this information should come from the ArtifactGraph not digging around in the AST */
|
||||
function getWallOrCapPlaneCodeRef(
|
||||
ast: Node<Program>,
|
||||
pathToNode: PathToNode
|
||||
): CodeRef | Error {
|
||||
const varDec = getNodeFromPath<VariableDeclaration>(
|
||||
ast,
|
||||
pathToNode,
|
||||
'VariableDeclaration'
|
||||
)
|
||||
if (err(varDec)) return varDec
|
||||
if (varDec.node.type !== 'VariableDeclaration')
|
||||
return new Error('Expected VariableDeclaration')
|
||||
const init = varDec.node.declaration.init
|
||||
let varName = ''
|
||||
if (
|
||||
init.type === 'CallExpression' &&
|
||||
init.callee.type === 'Identifier' &&
|
||||
(init.callee.name === 'circle' || init.callee.name === 'startProfileAt')
|
||||
) {
|
||||
const secondArg = init.arguments[1]
|
||||
if (secondArg.type === 'Identifier') {
|
||||
varName = secondArg.name
|
||||
}
|
||||
} else if (init.type === 'PipeExpression') {
|
||||
const firstExpr = init.body[0]
|
||||
if (
|
||||
firstExpr.type === 'CallExpression' &&
|
||||
firstExpr.callee.type === 'Identifier' &&
|
||||
firstExpr.callee.name === 'startProfileAt'
|
||||
) {
|
||||
const secondArg = firstExpr.arguments[1]
|
||||
if (secondArg.type === 'Identifier') {
|
||||
varName = secondArg.name
|
||||
}
|
||||
}
|
||||
}
|
||||
if (varName === '') return new Error('Could not find variable name')
|
||||
|
||||
let currentVariableName = ''
|
||||
const planeCodeRef: Array<{
|
||||
path: PathToNode
|
||||
sketchName: string
|
||||
range: SourceRange
|
||||
}> = []
|
||||
traverse(ast, {
|
||||
leave: (node) => {
|
||||
if (node.type === 'VariableDeclaration') {
|
||||
currentVariableName = ''
|
||||
}
|
||||
},
|
||||
enter: (node, path) => {
|
||||
if (node.type === 'VariableDeclaration') {
|
||||
currentVariableName = node.declaration.id.name
|
||||
}
|
||||
if (
|
||||
// match `${varName} = startSketchOn(...)`
|
||||
node.type === 'CallExpression' &&
|
||||
node.callee.name === 'startSketchOn' &&
|
||||
node.arguments[0].type === 'Identifier' &&
|
||||
currentVariableName === varName
|
||||
) {
|
||||
planeCodeRef.push({
|
||||
path,
|
||||
sketchName: currentVariableName,
|
||||
range: [node.start, node.end, true],
|
||||
})
|
||||
}
|
||||
},
|
||||
})
|
||||
if (!planeCodeRef.length)
|
||||
return new Error('No paths found depending on extrude')
|
||||
|
||||
return {
|
||||
pathToNode: planeCodeRef[0].path,
|
||||
range: planeCodeRef[0].range,
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Get an artifact from a code source range
|
||||
*/
|
||||
|
@ -1,6 +1,7 @@
|
||||
import {
|
||||
defaultRustSourceRange,
|
||||
defaultSourceRange,
|
||||
ExecState,
|
||||
Program,
|
||||
RustSourceRange,
|
||||
SourceRange,
|
||||
@ -2116,11 +2117,15 @@ export class EngineCommandManager extends EventTarget {
|
||||
Object.values(this.pendingCommands).map((a) => a.promise)
|
||||
)
|
||||
}
|
||||
updateArtifactGraph(ast: Node<Program>) {
|
||||
updateArtifactGraph(
|
||||
ast: Node<Program>,
|
||||
execStateArtifacts: ExecState['artifacts']
|
||||
) {
|
||||
this.artifactGraph = createArtifactGraph({
|
||||
orderedCommands: this.orderedCommands,
|
||||
responseMap: this.responseMap,
|
||||
ast,
|
||||
execStateArtifacts,
|
||||
})
|
||||
// TODO check if these still need to be deferred once e2e tests are working again.
|
||||
if (this.artifactGraph.size) {
|
||||
|
@ -44,7 +44,11 @@ import { CompilationError } from 'wasm-lib/kcl/bindings/CompilationError'
|
||||
import { SourceRange as RustSourceRange } from 'wasm-lib/kcl/bindings/SourceRange'
|
||||
import { getAllCurrentSettings } from 'lib/settings/settingsUtils'
|
||||
import { KclErrorWithOutputs } from 'wasm-lib/kcl/bindings/KclErrorWithOutputs'
|
||||
import { Artifact } from 'wasm-lib/kcl/bindings/Artifact'
|
||||
import { ArtifactId } from 'wasm-lib/kcl/bindings/ArtifactId'
|
||||
|
||||
export type { Artifact } from 'wasm-lib/kcl/bindings/Artifact'
|
||||
export type { ArtifactId } from 'wasm-lib/kcl/bindings/ArtifactId'
|
||||
export type { Configuration } from 'wasm-lib/kcl/bindings/Configuration'
|
||||
export type { Program } from '../wasm-lib/kcl/bindings/Program'
|
||||
export type { Expr } from '../wasm-lib/kcl/bindings/Expr'
|
||||
@ -245,6 +249,7 @@ export const isPathToNodeNumber = (
|
||||
|
||||
export interface ExecState {
|
||||
memory: ProgramMemory
|
||||
artifacts: { [key in ArtifactId]?: Artifact }
|
||||
}
|
||||
|
||||
/**
|
||||
@ -254,12 +259,14 @@ export interface ExecState {
|
||||
export function emptyExecState(): ExecState {
|
||||
return {
|
||||
memory: ProgramMemory.empty(),
|
||||
artifacts: {},
|
||||
}
|
||||
}
|
||||
|
||||
function execStateFromRaw(raw: RawExecState): ExecState {
|
||||
return {
|
||||
memory: ProgramMemory.fromRaw(raw.modLocal.memory),
|
||||
artifacts: raw.global.artifacts,
|
||||
}
|
||||
}
|
||||
|
||||
|
47
src/wasm-lib/kcl/src/execution/artifact.rs
Normal file
47
src/wasm-lib/kcl/src/execution/artifact.rs
Normal file
@ -0,0 +1,47 @@
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::SourceRange;
|
||||
|
||||
#[derive(Debug, Clone, Copy, Deserialize, Serialize, PartialEq, Eq, Hash, ts_rs::TS, JsonSchema)]
|
||||
#[ts(export)]
|
||||
pub struct ArtifactId(Uuid);
|
||||
|
||||
impl ArtifactId {
|
||||
pub fn new(uuid: Uuid) -> Self {
|
||||
Self(uuid)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Uuid> for ArtifactId {
|
||||
fn from(uuid: Uuid) -> Self {
|
||||
Self::new(uuid)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&Uuid> for ArtifactId {
|
||||
fn from(uuid: &Uuid) -> Self {
|
||||
Self::new(*uuid)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||
#[ts(export)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Artifact {
|
||||
pub id: ArtifactId,
|
||||
#[serde(flatten)]
|
||||
pub inner: ArtifactInner,
|
||||
pub source_range: SourceRange,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||
#[ts(export)]
|
||||
#[serde(tag = "type")]
|
||||
pub enum ArtifactInner {
|
||||
#[serde(rename_all = "camelCase")]
|
||||
StartSketchOnFace { face_id: Uuid },
|
||||
#[serde(rename_all = "camelCase")]
|
||||
StartSketchOnPlane { plane_id: Uuid },
|
||||
}
|
@ -25,6 +25,7 @@ pub use kcl_value::{KclObjectFields, KclValue};
|
||||
use uuid::Uuid;
|
||||
|
||||
mod annotations;
|
||||
mod artifact;
|
||||
pub(crate) mod cache;
|
||||
mod cad_op;
|
||||
mod exec_ast;
|
||||
@ -47,6 +48,7 @@ use crate::{
|
||||
};
|
||||
|
||||
// Re-exports.
|
||||
pub use artifact::{Artifact, ArtifactId, ArtifactInner};
|
||||
pub use cad_op::Operation;
|
||||
|
||||
/// State for executing a program.
|
||||
@ -68,6 +70,8 @@ pub struct GlobalState {
|
||||
pub path_to_source_id: IndexMap<std::path::PathBuf, ModuleId>,
|
||||
/// Map from module ID to module info.
|
||||
pub module_infos: IndexMap<ModuleId, ModuleInfo>,
|
||||
/// Output map of UUIDs to artifacts.
|
||||
pub artifacts: IndexMap<ArtifactId, Artifact>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||
@ -134,6 +138,11 @@ impl ExecState {
|
||||
self.global.id_generator.next_uuid()
|
||||
}
|
||||
|
||||
pub fn add_artifact(&mut self, artifact: Artifact) {
|
||||
let id = artifact.id;
|
||||
self.global.artifacts.insert(id, artifact);
|
||||
}
|
||||
|
||||
async fn add_module(
|
||||
&mut self,
|
||||
path: std::path::PathBuf,
|
||||
@ -171,6 +180,7 @@ impl GlobalState {
|
||||
id_generator: Default::default(),
|
||||
path_to_source_id: Default::default(),
|
||||
module_infos: Default::default(),
|
||||
artifacts: Default::default(),
|
||||
};
|
||||
|
||||
// TODO(#4434): Use the top-level file's path.
|
||||
|
@ -11,6 +11,7 @@ use parse_display::{Display, FromStr};
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::execution::{Artifact, ArtifactId, ArtifactInner};
|
||||
use crate::{
|
||||
errors::{KclError, KclErrorDetails},
|
||||
execution::{
|
||||
@ -1075,7 +1076,17 @@ async fn inner_start_sketch_on(
|
||||
let plane = make_sketch_plane_from_orientation(plane_data, exec_state, args).await?;
|
||||
Ok(SketchSurface::Plane(plane))
|
||||
}
|
||||
SketchData::Plane(plane) => Ok(SketchSurface::Plane(plane)),
|
||||
SketchData::Plane(plane) => {
|
||||
// Create artifact used only by the UI, not the engine.
|
||||
let id = exec_state.next_uuid();
|
||||
exec_state.add_artifact(Artifact {
|
||||
id: ArtifactId::from(id),
|
||||
inner: ArtifactInner::StartSketchOnPlane { plane_id: plane.id },
|
||||
source_range: args.source_range,
|
||||
});
|
||||
|
||||
Ok(SketchSurface::Plane(plane))
|
||||
}
|
||||
SketchData::Solid(solid) => {
|
||||
let Some(tag) = tag else {
|
||||
return Err(KclError::Type(KclErrorDetails {
|
||||
@ -1084,6 +1095,15 @@ async fn inner_start_sketch_on(
|
||||
}));
|
||||
};
|
||||
let face = start_sketch_on_face(solid, tag, exec_state, args).await?;
|
||||
|
||||
// Create artifact used only by the UI, not the engine.
|
||||
let id = exec_state.next_uuid();
|
||||
exec_state.add_artifact(Artifact {
|
||||
id: ArtifactId::from(id),
|
||||
inner: ArtifactInner::StartSketchOnFace { face_id: face.id },
|
||||
source_range: args.source_range,
|
||||
});
|
||||
|
||||
Ok(SketchSurface::Face(face))
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user