Remove KclValue::SketchGroup variant (#3446)
We can store Rust types like `SketchGroup` as their own variant of `KclValue`, or as `KclValue::UserVal`. Sometimes we store in one and try to read from the other, which fails. This causes bugs, like #3338. Instead, we should use either ::SketchGroup or ::UserVal, and stop using the other. If we stopped using ::UserVal, we'd need a new variant for every Rust type we wanted to build, including user-defined types. So I don't think that's practical. Instead, we should store every KCL value by de/serializing it into UserVal. This is a first step along that path, removing just the SketchGroup variants. If it goes well, we can remove the other specialized variants too. My only concern is there might be performance implications from how frequently we convert between serde_json::Value and Rust types via Serde. But I'm not too worried -- there's no parsing JSON strings, just traversing serde_json::Value trees. This isn't great for performance but I think it'll probably be miniscule in comparison to doing all the API calls.
This commit is contained in:
@ -50,6 +50,7 @@ import {
|
||||
ExtrudeGroup,
|
||||
VariableDeclaration,
|
||||
VariableDeclarator,
|
||||
sketchGroupFromKclValue,
|
||||
} from 'lang/wasm'
|
||||
import {
|
||||
engineCommandManager,
|
||||
@ -588,10 +589,12 @@ export class SceneEntities {
|
||||
const variableDeclarationName =
|
||||
_node1.node?.declarations?.[0]?.id?.name || ''
|
||||
|
||||
const sg = kclManager.programMemory.get(
|
||||
const sg = sketchGroupFromKclValue(
|
||||
kclManager.programMemory.get(variableDeclarationName),
|
||||
variableDeclarationName
|
||||
) as SketchGroup
|
||||
const lastSeg = sg?.value?.slice(-1)[0] || sg.start
|
||||
)
|
||||
if (err(sg)) return sg
|
||||
const lastSeg = sg.value?.slice(-1)[0] || sg.start
|
||||
|
||||
const index = sg.value.length // because we've added a new segment that's not in the memory yet, no need for `-1`
|
||||
|
||||
@ -786,9 +789,11 @@ export class SceneEntities {
|
||||
programMemoryOverride,
|
||||
})
|
||||
this.sceneProgramMemory = programMemory
|
||||
const sketchGroup = programMemory.get(
|
||||
const sketchGroup = sketchGroupFromKclValue(
|
||||
programMemory.get(variableDeclarationName),
|
||||
variableDeclarationName
|
||||
) as SketchGroup
|
||||
)
|
||||
if (err(sketchGroup)) return sketchGroup
|
||||
const sgPaths = sketchGroup.value
|
||||
const orthoFactor = orthoScale(sceneInfra.camControls.camera)
|
||||
|
||||
@ -840,9 +845,11 @@ export class SceneEntities {
|
||||
|
||||
// Prepare to update the THREEjs scene
|
||||
this.sceneProgramMemory = programMemory
|
||||
const sketchGroup = programMemory.get(
|
||||
const sketchGroup = sketchGroupFromKclValue(
|
||||
programMemory.get(variableDeclarationName),
|
||||
variableDeclarationName
|
||||
) as SketchGroup
|
||||
)
|
||||
if (err(sketchGroup)) return sketchGroup
|
||||
const sgPaths = sketchGroup.value
|
||||
const orthoFactor = orthoScale(sceneInfra.camControls.camera)
|
||||
|
||||
@ -1111,8 +1118,12 @@ export class SceneEntities {
|
||||
|
||||
const maybeSketchGroup = programMemory.get(variableDeclarationName)
|
||||
let sketchGroup = undefined
|
||||
if (maybeSketchGroup?.type === 'SketchGroup') {
|
||||
sketchGroup = maybeSketchGroup
|
||||
const sg = sketchGroupFromKclValue(
|
||||
maybeSketchGroup,
|
||||
variableDeclarationName
|
||||
)
|
||||
if (!err(sg)) {
|
||||
sketchGroup = sg
|
||||
} else if ((maybeSketchGroup as ExtrudeGroup).sketchGroup) {
|
||||
sketchGroup = (maybeSketchGroup as ExtrudeGroup).sketchGroup
|
||||
}
|
||||
@ -1656,9 +1667,12 @@ function prepareTruncatedMemoryAndAst(
|
||||
)
|
||||
if (err(_node)) return _node
|
||||
const variableDeclarationName = _node.node?.declarations?.[0]?.id?.name || ''
|
||||
const lastSeg = (
|
||||
programMemory.get(variableDeclarationName) as SketchGroup
|
||||
).value.slice(-1)[0]
|
||||
const sg = sketchGroupFromKclValue(
|
||||
programMemory.get(variableDeclarationName),
|
||||
variableDeclarationName
|
||||
)
|
||||
if (err(sg)) return sg
|
||||
const lastSeg = sg?.value.slice(-1)[0]
|
||||
if (draftSegment) {
|
||||
// truncatedAst needs to setup with another segment at the end
|
||||
let newSegment
|
||||
@ -1782,10 +1796,11 @@ export function sketchGroupFromPathToNode({
|
||||
if (result?.type === 'ExtrudeGroup') {
|
||||
return result.sketchGroup
|
||||
}
|
||||
if (result?.type === 'SketchGroup') {
|
||||
return result
|
||||
}
|
||||
const sg = sketchGroupFromKclValue(result, varDec?.id?.name)
|
||||
if (err(sg)) {
|
||||
return null
|
||||
}
|
||||
return sg
|
||||
}
|
||||
|
||||
function colorSegment(object: any, color: number) {
|
||||
|
@ -1,11 +1,16 @@
|
||||
import toast from 'react-hot-toast'
|
||||
import ReactJson from 'react-json-view'
|
||||
import { useMemo } from 'react'
|
||||
import { ProgramMemory, Path, ExtrudeSurface } from 'lang/wasm'
|
||||
import {
|
||||
ProgramMemory,
|
||||
Path,
|
||||
ExtrudeSurface,
|
||||
sketchGroupFromKclValue,
|
||||
} from 'lang/wasm'
|
||||
import { useKclContext } from 'lang/KclProvider'
|
||||
import { useResolvedTheme } from 'hooks/useResolvedTheme'
|
||||
import { ActionButton } from 'components/ActionButton'
|
||||
import { trap } from 'lib/trap'
|
||||
import { err, trap } from 'lib/trap'
|
||||
import Tooltip from 'components/Tooltip'
|
||||
import { useModelingContext } from 'hooks/useModelingContext'
|
||||
|
||||
@ -84,8 +89,9 @@ export const processMemory = (programMemory: ProgramMemory) => {
|
||||
const processedMemory: any = {}
|
||||
for (const [key, val] of programMemory?.visibleEntries()) {
|
||||
if (typeof val.value !== 'function') {
|
||||
if (val.type === 'SketchGroup') {
|
||||
processedMemory[key] = val.value.map(({ __geoMeta, ...rest }: Path) => {
|
||||
const sg = sketchGroupFromKclValue(val, null)
|
||||
if (!err(sg)) {
|
||||
processedMemory[key] = sg.value.map(({ __geoMeta, ...rest }: Path) => {
|
||||
return rest
|
||||
})
|
||||
} else if (val.type === 'ExtrudeGroup') {
|
||||
|
@ -18,6 +18,9 @@ const mySketch001 = startSketchOn('XY')
|
||||
// @ts-ignore
|
||||
const sketch001 = programMemory?.get('mySketch001')
|
||||
expect(sketch001).toEqual({
|
||||
type: 'UserVal',
|
||||
__meta: [{ sourceRange: [46, 71] }],
|
||||
value: {
|
||||
type: 'SketchGroup',
|
||||
on: expect.any(Object),
|
||||
start: {
|
||||
@ -53,6 +56,7 @@ const mySketch001 = startSketchOn('XY')
|
||||
],
|
||||
id: expect.any(String),
|
||||
__meta: [{ sourceRange: [46, 71] }],
|
||||
},
|
||||
})
|
||||
})
|
||||
test('extrude artifacts', async () => {
|
||||
|
@ -1,6 +1,12 @@
|
||||
import fs from 'node:fs'
|
||||
|
||||
import { parse, ProgramMemory, SketchGroup, initPromise } from './wasm'
|
||||
import {
|
||||
parse,
|
||||
ProgramMemory,
|
||||
SketchGroup,
|
||||
initPromise,
|
||||
sketchGroupFromKclValue,
|
||||
} from './wasm'
|
||||
import { enginelessExecutor } from '../lib/testHelpers'
|
||||
import { KCLError } from './errors'
|
||||
|
||||
@ -52,7 +58,7 @@ const newVar = myVar + 1`
|
||||
`
|
||||
const mem = await exe(code)
|
||||
// geo is three js buffer geometry and is very bloated to have in tests
|
||||
const minusGeo = mem.get('mySketch')?.value
|
||||
const minusGeo = mem.get('mySketch')?.value?.value
|
||||
expect(minusGeo).toEqual([
|
||||
{
|
||||
type: 'ToPoint',
|
||||
@ -146,6 +152,8 @@ const newVar = myVar + 1`
|
||||
].join('\n')
|
||||
const mem = await exe(code)
|
||||
expect(mem.get('mySk1')).toEqual({
|
||||
type: 'UserVal',
|
||||
value: {
|
||||
type: 'SketchGroup',
|
||||
on: expect.any(Object),
|
||||
start: {
|
||||
@ -209,6 +217,8 @@ const newVar = myVar + 1`
|
||||
],
|
||||
id: expect.any(String),
|
||||
__meta: [{ sourceRange: [39, 63] }],
|
||||
},
|
||||
__meta: [{ sourceRange: [39, 63] }],
|
||||
})
|
||||
})
|
||||
it('execute array expression', async () => {
|
||||
@ -358,7 +368,7 @@ describe('testing math operators', () => {
|
||||
'|> line([-2.21, -legLen(5, min(3, 999))], %)',
|
||||
].join('\n')
|
||||
const mem = await exe(code)
|
||||
const sketch = mem.get('part001')
|
||||
const sketch = sketchGroupFromKclValue(mem.get('part001'), 'part001')
|
||||
// result of `-legLen(5, min(3, 999))` should be -4
|
||||
const yVal = (sketch as SketchGroup).value?.[0]?.to?.[1]
|
||||
expect(yVal).toBe(-4)
|
||||
@ -376,7 +386,7 @@ describe('testing math operators', () => {
|
||||
``,
|
||||
].join('\n')
|
||||
const mem = await exe(code)
|
||||
const sketch = mem.get('part001')
|
||||
const sketch = sketchGroupFromKclValue(mem.get('part001'), 'part001')
|
||||
// expect -legLen(segLen('seg01'), myVar) to equal -4 setting the y value back to 0
|
||||
expect((sketch as SketchGroup).value?.[1]?.from).toEqual([3, 4])
|
||||
expect((sketch as SketchGroup).value?.[1]?.to).toEqual([6, 0])
|
||||
@ -385,7 +395,10 @@ describe('testing math operators', () => {
|
||||
`legLen(segLen(seg01), myVar)`
|
||||
)
|
||||
const removedUnaryExpMem = await exe(removedUnaryExp)
|
||||
const removedUnaryExpMemSketch = removedUnaryExpMem.get('part001')
|
||||
const removedUnaryExpMemSketch = sketchGroupFromKclValue(
|
||||
removedUnaryExpMem.get('part001'),
|
||||
'part001'
|
||||
)
|
||||
|
||||
// without the minus sign, the y value should be 8
|
||||
expect((removedUnaryExpMemSketch as SketchGroup).value?.[1]?.to).toEqual([
|
||||
|
@ -17,7 +17,7 @@ import {
|
||||
PathToNode,
|
||||
ProgramMemory,
|
||||
SourceRange,
|
||||
SketchGroup,
|
||||
sketchGroupFromKclValue,
|
||||
} from './wasm'
|
||||
import {
|
||||
isNodeSafeToReplacePath,
|
||||
@ -981,7 +981,11 @@ export async function deleteFromSelection(
|
||||
if (err(parent)) {
|
||||
return
|
||||
}
|
||||
const sketchToPreserve = programMemory.get(sketchName) as SketchGroup
|
||||
const sketchToPreserve = sketchGroupFromKclValue(
|
||||
programMemory.get(sketchName),
|
||||
sketchName
|
||||
)
|
||||
if (err(sketchToPreserve)) return sketchToPreserve
|
||||
console.log('sketchName', sketchName)
|
||||
// Can't kick off multiple requests at once as getFaceDetails
|
||||
// is three engine calls in one and they conflict
|
||||
|
@ -10,12 +10,12 @@ import {
|
||||
Program,
|
||||
ProgramMemory,
|
||||
ReturnStatement,
|
||||
SketchGroup,
|
||||
SourceRange,
|
||||
SyntaxType,
|
||||
Expr,
|
||||
VariableDeclaration,
|
||||
VariableDeclarator,
|
||||
sketchGroupFromKclValue,
|
||||
} from './wasm'
|
||||
import { createIdentifier, splitPathAtLastIndex } from './modifyAst'
|
||||
import { getSketchSegmentFromSourceRange } from './std/sketchConstraints'
|
||||
@ -661,15 +661,16 @@ export function isLinesParallelAndConstrained(
|
||||
if (err(_varDec)) return _varDec
|
||||
const varDec = _varDec.node
|
||||
const varName = (varDec as VariableDeclaration)?.declarations[0]?.id?.name
|
||||
const path = programMemory?.get(varName) as SketchGroup
|
||||
const sg = sketchGroupFromKclValue(programMemory?.get(varName), varName)
|
||||
if (err(sg)) return sg
|
||||
const _primarySegment = getSketchSegmentFromSourceRange(
|
||||
path,
|
||||
sg,
|
||||
primaryLine.range
|
||||
)
|
||||
if (err(_primarySegment)) return _primarySegment
|
||||
const primarySegment = _primarySegment.segment
|
||||
|
||||
const _segment = getSketchSegmentFromSourceRange(path, secondaryLine.range)
|
||||
const _segment = getSketchSegmentFromSourceRange(sg, secondaryLine.range)
|
||||
if (err(_segment)) return _segment
|
||||
const { segment: secondarySegment, index: secondaryIndex } = _segment
|
||||
const primaryAngle = getAngle(primarySegment.from, primarySegment.to)
|
||||
@ -708,9 +709,7 @@ export function isLinesParallelAndConstrained(
|
||||
constraintType === 'angle' || constraintLevel === 'full'
|
||||
|
||||
// get the previous segment
|
||||
const prevSegment = (programMemory.get(varName) as SketchGroup).value[
|
||||
secondaryIndex - 1
|
||||
]
|
||||
const prevSegment = sg.value[secondaryIndex - 1]
|
||||
const prevSourceRange = prevSegment.__geoMeta.sourceRange
|
||||
|
||||
const isParallelAndConstrained =
|
||||
@ -779,7 +778,10 @@ export function hasExtrudeSketchGroup({
|
||||
if (varDec.type !== 'VariableDeclaration') return false
|
||||
const varName = varDec.declarations[0].id.name
|
||||
const varValue = programMemory?.get(varName)
|
||||
return varValue?.type === 'ExtrudeGroup' || varValue?.type === 'SketchGroup'
|
||||
return (
|
||||
varValue?.type === 'ExtrudeGroup' ||
|
||||
!err(sketchGroupFromKclValue(varValue, varName))
|
||||
)
|
||||
}
|
||||
|
||||
export function isSingleCursorInPipe(
|
||||
|
@ -12,6 +12,7 @@ import {
|
||||
Literal,
|
||||
VariableDeclaration,
|
||||
Identifier,
|
||||
sketchGroupFromKclValue,
|
||||
} from 'lang/wasm'
|
||||
import {
|
||||
getNodeFromPath,
|
||||
@ -1009,9 +1010,12 @@ export const angledLineOfXLength: SketchLineHelper = {
|
||||
const { node: varDec } = nodeMeta2
|
||||
|
||||
const variableName = varDec.id.name
|
||||
const sketch = previousProgramMemory?.get(variableName)
|
||||
if (!sketch || sketch.type !== 'SketchGroup') {
|
||||
return new Error('not a SketchGroup')
|
||||
const sketch = sketchGroupFromKclValue(
|
||||
previousProgramMemory?.get(variableName),
|
||||
variableName
|
||||
)
|
||||
if (err(sketch)) {
|
||||
return sketch
|
||||
}
|
||||
const angle = createLiteral(roundOff(getAngle(from, to), 0))
|
||||
const xLength = createLiteral(roundOff(Math.abs(from[0] - to[0]), 2) || 0.1)
|
||||
@ -1105,10 +1109,11 @@ export const angledLineOfYLength: SketchLineHelper = {
|
||||
if (err(nodeMeta2)) return nodeMeta2
|
||||
const { node: varDec } = nodeMeta2
|
||||
const variableName = varDec.id.name
|
||||
const sketch = previousProgramMemory?.get(variableName)
|
||||
if (!sketch || sketch.type !== 'SketchGroup') {
|
||||
return new Error('not a SketchGroup')
|
||||
}
|
||||
const sketch = sketchGroupFromKclValue(
|
||||
previousProgramMemory?.get(variableName),
|
||||
variableName
|
||||
)
|
||||
if (err(sketch)) return sketch
|
||||
|
||||
const angle = createLiteral(roundOff(getAngle(from, to), 0))
|
||||
const yLength = createLiteral(roundOff(Math.abs(from[1] - to[1]), 2) || 0.1)
|
||||
@ -1443,7 +1448,11 @@ export const angledLineThatIntersects: SketchLineHelper = {
|
||||
|
||||
const { node: varDec } = nodeMeta2
|
||||
const varName = varDec.declarations[0].id.name
|
||||
const sketchGroup = previousProgramMemory.get(varName) as SketchGroup
|
||||
const sketchGroup = sketchGroupFromKclValue(
|
||||
previousProgramMemory.get(varName),
|
||||
varName
|
||||
)
|
||||
if (err(sketchGroup)) return sketchGroup
|
||||
const intersectPath = sketchGroup.value.find(
|
||||
({ tag }: Path) => tag && tag.value === intersectTagName
|
||||
)
|
||||
|
@ -1,4 +1,10 @@
|
||||
import { parse, SketchGroup, recast, initPromise } from '../wasm'
|
||||
import {
|
||||
parse,
|
||||
SketchGroup,
|
||||
recast,
|
||||
initPromise,
|
||||
sketchGroupFromKclValue,
|
||||
} from '../wasm'
|
||||
import {
|
||||
ConstraintType,
|
||||
getTransformInfos,
|
||||
@ -362,10 +368,11 @@ const part001 = startSketchOn('XY')
|
||||
it('normal case works', async () => {
|
||||
const programMemory = await enginelessExecutor(parse(code))
|
||||
const index = code.indexOf('// normal-segment') - 7
|
||||
const _segment = getSketchSegmentFromSourceRange(
|
||||
programMemory.get('part001') as SketchGroup,
|
||||
[index, index]
|
||||
)
|
||||
const sg = sketchGroupFromKclValue(
|
||||
programMemory.get('part001'),
|
||||
'part001'
|
||||
) as SketchGroup
|
||||
const _segment = getSketchSegmentFromSourceRange(sg, [index, index])
|
||||
if (err(_segment)) throw _segment
|
||||
const { __geoMeta, ...segment } = _segment.segment
|
||||
expect(segment).toEqual({
|
||||
@ -379,7 +386,10 @@ const part001 = startSketchOn('XY')
|
||||
const programMemory = await enginelessExecutor(parse(code))
|
||||
const index = code.indexOf('// segment-in-start') - 7
|
||||
const _segment = getSketchSegmentFromSourceRange(
|
||||
programMemory.get('part001') as SketchGroup,
|
||||
sketchGroupFromKclValue(
|
||||
programMemory.get('part001'),
|
||||
'part001'
|
||||
) as SketchGroup,
|
||||
[index, index]
|
||||
)
|
||||
if (err(_segment)) throw _segment
|
||||
|
@ -10,6 +10,7 @@ import {
|
||||
VariableDeclarator,
|
||||
PathToNode,
|
||||
ProgramMemory,
|
||||
sketchGroupFromKclValue,
|
||||
} from '../wasm'
|
||||
import {
|
||||
getNodeFromPath,
|
||||
@ -1636,12 +1637,16 @@ export function transformAstSketchLines({
|
||||
})
|
||||
|
||||
const varName = varDec.node.id.name
|
||||
let sketchGroup = programMemory.get(varName)
|
||||
if (sketchGroup?.type === 'ExtrudeGroup') {
|
||||
sketchGroup = sketchGroup.sketchGroup
|
||||
let kclVal = programMemory.get(varName)
|
||||
let sketchGroup
|
||||
if (kclVal?.type === 'ExtrudeGroup') {
|
||||
sketchGroup = kclVal.sketchGroup
|
||||
} else {
|
||||
sketchGroup = sketchGroupFromKclValue(kclVal, varName)
|
||||
if (err(sketchGroup)) {
|
||||
return
|
||||
}
|
||||
}
|
||||
if (!sketchGroup || sketchGroup.type !== 'SketchGroup')
|
||||
return new Error('not a sketch group')
|
||||
const segMeta = getSketchSegmentFromPathToNode(
|
||||
sketchGroup,
|
||||
ast,
|
||||
|
@ -38,6 +38,7 @@ import { err } from 'lib/trap'
|
||||
import { Configuration } from 'wasm-lib/kcl/bindings/Configuration'
|
||||
import { DeepPartial } from 'lib/types'
|
||||
import { ProjectConfiguration } from 'wasm-lib/kcl/bindings/ProjectConfiguration'
|
||||
import { SketchGroup } from '../wasm-lib/kcl/bindings/SketchGroup'
|
||||
|
||||
export type { Program } from '../wasm-lib/kcl/bindings/Program'
|
||||
export type { Expr } from '../wasm-lib/kcl/bindings/Expr'
|
||||
@ -126,6 +127,7 @@ export const parse = (code: string | Error): Program | Error => {
|
||||
const program: Program = parse_wasm(code)
|
||||
return program
|
||||
} catch (e: any) {
|
||||
// throw e
|
||||
const parsed: RustKclError = JSON.parse(e.toString())
|
||||
return new KCLError(
|
||||
parsed.kind,
|
||||
@ -312,7 +314,7 @@ export class ProgramMemory {
|
||||
*/
|
||||
hasSketchOrExtrudeGroup(): boolean {
|
||||
for (const node of this.visibleEntries().values()) {
|
||||
if (node.type === 'ExtrudeGroup' || node.type === 'SketchGroup') {
|
||||
if (node.type === 'ExtrudeGroup' || node.value?.type === 'SketchGroup') {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@ -332,6 +334,25 @@ export class ProgramMemory {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: In the future, make the parameter be a KclValue.
|
||||
export function sketchGroupFromKclValue(
|
||||
obj: any,
|
||||
varName: string | null
|
||||
): SketchGroup | Error {
|
||||
if (obj?.value?.type === 'SketchGroup') return obj.value
|
||||
if (!varName) {
|
||||
varName = 'a KCL value'
|
||||
}
|
||||
const actualType = obj?.value?.type ?? obj?.type
|
||||
if (actualType) {
|
||||
return new Error(
|
||||
`Expected ${varName} to be a sketchGroup, but it was ${actualType} instead.`
|
||||
)
|
||||
} else {
|
||||
return new Error(`Expected ${varName} to be a sketchGroup, but it wasn't.`)
|
||||
}
|
||||
}
|
||||
|
||||
export const executor = async (
|
||||
node: Program,
|
||||
programMemory: ProgramMemory | Error = ProgramMemory.empty(),
|
||||
|
@ -4,6 +4,7 @@ import {
|
||||
VariableDeclarator,
|
||||
parse,
|
||||
recast,
|
||||
sketchGroupFromKclValue,
|
||||
} from 'lang/wasm'
|
||||
import { Axis, Selection, Selections, updateSelections } from 'lib/selections'
|
||||
import { assign, createMachine } from 'xstate'
|
||||
@ -1187,8 +1188,11 @@ export const modelingMachine = createMachine(
|
||||
)
|
||||
if (err(varDecNode)) return
|
||||
const sketchVar = varDecNode.node.declarations[0].id.name
|
||||
const sketchGroup = kclManager.programMemory.get(sketchVar)
|
||||
if (sketchGroup?.type !== 'SketchGroup') return
|
||||
const sketchGroup = sketchGroupFromKclValue(
|
||||
kclManager.programMemory.get(sketchVar),
|
||||
sketchVar
|
||||
)
|
||||
if (trap(sketchGroup)) return
|
||||
const extrusion = getExtrusionFromSuspectedPath(
|
||||
sketchGroup.id,
|
||||
engineCommandManager.artifactGraph
|
||||
|
@ -23,7 +23,7 @@ use crate::{
|
||||
docs::StdLibFn,
|
||||
errors::{KclError, KclErrorDetails},
|
||||
executor::{
|
||||
BodyType, DynamicState, ExecutorContext, KclValue, Metadata, PipeInfo, ProgramMemory, SourceRange,
|
||||
BodyType, DynamicState, ExecutorContext, KclValue, Metadata, PipeInfo, ProgramMemory, SketchGroup, SourceRange,
|
||||
StatementKind, TagEngineInfo, TagIdentifier, UserVal,
|
||||
},
|
||||
parser::PIPE_OPERATOR,
|
||||
@ -1377,10 +1377,13 @@ impl CallExpression {
|
||||
// TODO: This could probably be done in a better way, but as of now this was my only idea
|
||||
// and it works.
|
||||
match result {
|
||||
KclValue::SketchGroup(ref sketch_group) => {
|
||||
KclValue::UserVal(ref mut uval) => {
|
||||
uval.mutate(|sketch_group: &mut SketchGroup| {
|
||||
for (_, tag) in sketch_group.tags.iter() {
|
||||
memory.update_tag(&tag.value, tag.clone())?;
|
||||
}
|
||||
Ok::<_, KclError>(())
|
||||
})?;
|
||||
}
|
||||
KclValue::ExtrudeGroup(ref mut extrude_group) => {
|
||||
for value in &extrude_group.value {
|
||||
|
@ -203,13 +203,22 @@ impl Environment {
|
||||
}
|
||||
|
||||
for (_, val) in self.bindings.iter_mut() {
|
||||
if let KclValue::SketchGroup(ref mut sketch_group) = val {
|
||||
let KclValue::UserVal(v) = val else { continue };
|
||||
let meta = v.meta.clone();
|
||||
let maybe_sg: Result<SketchGroup, _> = serde_json::from_value(v.value.clone());
|
||||
let Ok(mut sketch_group) = maybe_sg else {
|
||||
continue;
|
||||
};
|
||||
|
||||
if sketch_group.original_id == sg.original_id {
|
||||
for tag in sg.tags.iter() {
|
||||
sketch_group.tags.insert(tag.0.clone(), tag.1.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
*val = KclValue::UserVal(UserVal {
|
||||
meta,
|
||||
value: serde_json::to_value(sketch_group).expect("can always turn SketchGroup into JSON"),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -268,10 +277,7 @@ pub enum KclValue {
|
||||
TagDeclarator(Box<TagDeclarator>),
|
||||
Plane(Box<Plane>),
|
||||
Face(Box<Face>),
|
||||
SketchGroup(Box<SketchGroup>),
|
||||
SketchGroups {
|
||||
value: Vec<Box<SketchGroup>>,
|
||||
},
|
||||
|
||||
ExtrudeGroup(Box<ExtrudeGroup>),
|
||||
ExtrudeGroups {
|
||||
value: Vec<Box<ExtrudeGroup>>,
|
||||
@ -289,27 +295,8 @@ pub enum KclValue {
|
||||
}
|
||||
|
||||
impl KclValue {
|
||||
pub(crate) fn get_sketch_group_set(&self) -> Result<SketchGroupSet> {
|
||||
match self {
|
||||
KclValue::SketchGroup(s) => Ok(SketchGroupSet::SketchGroup(s.clone())),
|
||||
KclValue::SketchGroups { value } => Ok(SketchGroupSet::SketchGroups(value.clone())),
|
||||
KclValue::UserVal(value) => {
|
||||
let value = value.value.clone();
|
||||
match value {
|
||||
JValue::Null | JValue::Bool(_) | JValue::Number(_) | JValue::String(_) => Err(anyhow::anyhow!(
|
||||
"Failed to deserialize sketch group set from JSON {}",
|
||||
human_friendly_type(&value)
|
||||
)),
|
||||
JValue::Array(_) => serde_json::from_value::<Vec<Box<SketchGroup>>>(value)
|
||||
.map(SketchGroupSet::from)
|
||||
.map_err(|e| anyhow::anyhow!("Failed to deserialize array of sketch groups from JSON: {}", e)),
|
||||
JValue::Object(_) => serde_json::from_value::<Box<SketchGroup>>(value)
|
||||
.map(SketchGroupSet::from)
|
||||
.map_err(|e| anyhow::anyhow!("Failed to deserialize sketch group from JSON: {}", e)),
|
||||
}
|
||||
}
|
||||
_ => anyhow::bail!("Not a sketch group or sketch groups: {:?}", self),
|
||||
}
|
||||
pub(crate) fn new_user_val<T: Serialize>(meta: Vec<Metadata>, val: T) -> Self {
|
||||
Self::UserVal(UserVal::set(meta, val))
|
||||
}
|
||||
|
||||
pub(crate) fn get_extrude_group_set(&self) -> Result<ExtrudeGroupSet> {
|
||||
@ -342,8 +329,6 @@ impl KclValue {
|
||||
KclValue::UserVal(u) => human_friendly_type(&u.value),
|
||||
KclValue::TagDeclarator(_) => "TagDeclarator",
|
||||
KclValue::TagIdentifier(_) => "TagIdentifier",
|
||||
KclValue::SketchGroup(_) => "SketchGroup",
|
||||
KclValue::SketchGroups { .. } => "SketchGroups",
|
||||
KclValue::ExtrudeGroup(_) => "ExtrudeGroup",
|
||||
KclValue::ExtrudeGroups { .. } => "ExtrudeGroups",
|
||||
KclValue::ImportedGeometry(_) => "ImportedGeometry",
|
||||
@ -356,20 +341,14 @@ impl KclValue {
|
||||
|
||||
impl From<SketchGroupSet> for KclValue {
|
||||
fn from(sg: SketchGroupSet) -> Self {
|
||||
match sg {
|
||||
SketchGroupSet::SketchGroup(sg) => KclValue::SketchGroup(sg),
|
||||
SketchGroupSet::SketchGroups(sgs) => KclValue::SketchGroups { value: sgs },
|
||||
}
|
||||
KclValue::UserVal(UserVal::set(sg.meta(), sg))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Vec<Box<SketchGroup>>> for KclValue {
|
||||
fn from(sg: Vec<Box<SketchGroup>>) -> Self {
|
||||
if sg.len() == 1 {
|
||||
KclValue::SketchGroup(sg[0].clone())
|
||||
} else {
|
||||
KclValue::SketchGroups { value: sg }
|
||||
}
|
||||
let meta = sg.iter().flat_map(|sg| sg.meta.clone()).collect();
|
||||
KclValue::UserVal(UserVal::set(meta, sg))
|
||||
}
|
||||
}
|
||||
|
||||
@ -428,6 +407,24 @@ pub enum SketchGroupSet {
|
||||
SketchGroups(Vec<Box<SketchGroup>>),
|
||||
}
|
||||
|
||||
impl SketchGroupSet {
|
||||
pub fn meta(&self) -> Vec<Metadata> {
|
||||
match self {
|
||||
SketchGroupSet::SketchGroup(sg) => sg.meta.clone(),
|
||||
SketchGroupSet::SketchGroups(sg) => sg.iter().flat_map(|sg| sg.meta.clone()).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SketchGroupSet> for Vec<SketchGroup> {
|
||||
fn from(value: SketchGroupSet) -> Self {
|
||||
match value {
|
||||
SketchGroupSet::SketchGroup(sg) => vec![*sg],
|
||||
SketchGroupSet::SketchGroups(sgs) => sgs.into_iter().map(|sg| *sg).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SketchGroup> for SketchGroupSet {
|
||||
fn from(sg: SketchGroup) -> Self {
|
||||
SketchGroupSet::SketchGroup(Box::new(sg))
|
||||
@ -641,6 +638,43 @@ pub struct UserVal {
|
||||
pub meta: Vec<Metadata>,
|
||||
}
|
||||
|
||||
impl UserVal {
|
||||
/// If the UserVal matches the type `T`, return it.
|
||||
pub fn get<T: serde::de::DeserializeOwned>(&self) -> Option<(T, Vec<Metadata>)> {
|
||||
let meta = self.meta.clone();
|
||||
// TODO: This clone might cause performance problems, it'll happen a lot.
|
||||
let res: Result<T, _> = serde_json::from_value(self.value.clone());
|
||||
if let Ok(t) = res {
|
||||
Some((t, meta))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// If the UserVal matches the type `T`, then mutate it via the given closure.
|
||||
/// If the closure returns Err, the mutation won't be applied.
|
||||
pub fn mutate<T, F, E>(&mut self, mutate: F) -> Result<(), E>
|
||||
where
|
||||
T: serde::de::DeserializeOwned + Serialize,
|
||||
F: FnOnce(&mut T) -> Result<(), E>,
|
||||
{
|
||||
let Some((mut val, meta)) = self.get::<T>() else {
|
||||
return Ok(());
|
||||
};
|
||||
mutate(&mut val)?;
|
||||
*self = Self::set(meta, val);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Put the given value into this UserVal.
|
||||
pub fn set<T: serde::Serialize>(meta: Vec<Metadata>, val: T) -> Self {
|
||||
Self {
|
||||
meta,
|
||||
value: serde_json::to_value(val).expect("all KCL values should be compatible with JSON"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||
#[ts(export)]
|
||||
#[serde(tag = "type", rename_all = "camelCase")]
|
||||
@ -720,11 +754,6 @@ impl From<KclValue> for Vec<SourceRange> {
|
||||
KclValue::UserVal(u) => u.meta.iter().map(|m| m.source_range).collect(),
|
||||
KclValue::TagDeclarator(t) => t.into(),
|
||||
KclValue::TagIdentifier(t) => t.meta.iter().map(|m| m.source_range).collect(),
|
||||
KclValue::SketchGroup(s) => s.meta.iter().map(|m| m.source_range).collect(),
|
||||
KclValue::SketchGroups { value } => value
|
||||
.iter()
|
||||
.flat_map(|sg| sg.meta.iter().map(|m| m.source_range))
|
||||
.collect(),
|
||||
KclValue::ExtrudeGroup(e) => e.meta.iter().map(|m| m.source_range).collect(),
|
||||
KclValue::ExtrudeGroups { value } => value
|
||||
.iter()
|
||||
@ -1274,7 +1303,7 @@ impl Point2d {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, PartialEq, Clone, ts_rs::TS, JsonSchema)]
|
||||
#[derive(Debug, Deserialize, Serialize, PartialEq, Clone, ts_rs::TS, JsonSchema, Default)]
|
||||
#[ts(export)]
|
||||
pub struct Point3d {
|
||||
pub x: f64,
|
||||
@ -2085,6 +2114,39 @@ mod tests {
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn how_does_sketchgroup_serialize() {
|
||||
let sg = SketchGroup {
|
||||
id: uuid::Uuid::new_v4(),
|
||||
value: vec![],
|
||||
on: SketchSurface::Plane(Box::new(Plane {
|
||||
id: uuid::Uuid::new_v4(),
|
||||
value: PlaneType::XY,
|
||||
origin: Point3d::default(),
|
||||
x_axis: Point3d::default(),
|
||||
y_axis: Point3d::default(),
|
||||
z_axis: Point3d::default(),
|
||||
meta: Vec::new(),
|
||||
})),
|
||||
start: BasePath {
|
||||
from: [0.0, 0.0],
|
||||
to: [0.0, 0.0],
|
||||
tag: None,
|
||||
geo_meta: GeoMeta {
|
||||
id: uuid::Uuid::new_v4(),
|
||||
metadata: Metadata {
|
||||
source_range: SourceRange([0, 0]),
|
||||
},
|
||||
},
|
||||
},
|
||||
tags: HashMap::new(),
|
||||
original_id: uuid::Uuid::new_v4(),
|
||||
meta: Vec::new(),
|
||||
};
|
||||
let jstr = serde_json::to_string_pretty(&sg).unwrap();
|
||||
println!("{jstr}");
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn test_execute_assign_two_variables() {
|
||||
let ast = r#"const myVar = 5
|
||||
|
@ -251,11 +251,11 @@ impl Args {
|
||||
FromArgs::from_args(self, 0)
|
||||
}
|
||||
|
||||
pub(crate) fn get_sketch_groups(&self) -> Result<(SketchGroupSet, Box<SketchGroup>), KclError> {
|
||||
pub(crate) fn get_sketch_groups(&self) -> Result<(SketchGroupSet, SketchGroup), KclError> {
|
||||
FromArgs::from_args(self, 0)
|
||||
}
|
||||
|
||||
pub(crate) fn get_sketch_group(&self) -> Result<Box<SketchGroup>, KclError> {
|
||||
pub(crate) fn get_sketch_group(&self) -> Result<SketchGroup, KclError> {
|
||||
FromArgs::from_args(self, 0)
|
||||
}
|
||||
|
||||
@ -270,9 +270,7 @@ impl Args {
|
||||
FromArgs::from_args(self, 0)
|
||||
}
|
||||
|
||||
pub(crate) fn get_sketch_group_and_optional_tag(
|
||||
&self,
|
||||
) -> Result<(Box<SketchGroup>, Option<TagDeclarator>), KclError> {
|
||||
pub(crate) fn get_sketch_group_and_optional_tag(&self) -> Result<(SketchGroup, Option<TagDeclarator>), KclError> {
|
||||
FromArgs::from_args(self, 0)
|
||||
}
|
||||
|
||||
@ -283,7 +281,7 @@ impl Args {
|
||||
FromArgs::from_args(self, 0)
|
||||
}
|
||||
|
||||
pub(crate) fn get_data_and_sketch_group<'a, T>(&'a self) -> Result<(T, Box<SketchGroup>), KclError>
|
||||
pub(crate) fn get_data_and_sketch_group<'a, T>(&'a self) -> Result<(T, SketchGroup), KclError>
|
||||
where
|
||||
T: serde::de::DeserializeOwned + FromArgs<'a>,
|
||||
{
|
||||
@ -299,7 +297,7 @@ impl Args {
|
||||
|
||||
pub(crate) fn get_data_and_sketch_group_and_tag<'a, T>(
|
||||
&'a self,
|
||||
) -> Result<(T, Box<SketchGroup>, Option<TagDeclarator>), KclError>
|
||||
) -> Result<(T, SketchGroup, Option<TagDeclarator>), KclError>
|
||||
where
|
||||
T: serde::de::DeserializeOwned + FromKclValue<'a> + Sized,
|
||||
{
|
||||
@ -338,7 +336,7 @@ impl Args {
|
||||
FromArgs::from_args(self, 0)
|
||||
}
|
||||
|
||||
pub(crate) fn get_tag_to_number_sketch_group(&self) -> Result<(TagIdentifier, f64, Box<SketchGroup>), KclError> {
|
||||
pub(crate) fn get_tag_to_number_sketch_group(&self) -> Result<(TagIdentifier, f64, SketchGroup), KclError> {
|
||||
FromArgs::from_args(self, 0)
|
||||
}
|
||||
|
||||
@ -550,15 +548,6 @@ impl<'a> FromKclValue<'a> for TagIdentifier {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> FromKclValue<'a> for &'a SketchGroup {
|
||||
fn from_mem_item(arg: &'a KclValue) -> Option<Self> {
|
||||
let KclValue::SketchGroup(s) = arg else {
|
||||
return None;
|
||||
};
|
||||
Some(s.as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_from_arg_via_json {
|
||||
($typ:path) => {
|
||||
impl<'a> FromKclValue<'a> for $typ {
|
||||
@ -608,6 +597,7 @@ impl_from_arg_via_json!(super::revolve::RevolveData);
|
||||
impl_from_arg_via_json!(super::sketch::SketchData);
|
||||
impl_from_arg_via_json!(crate::std::import::ImportFormat);
|
||||
impl_from_arg_via_json!(crate::std::polar::PolarCoordsData);
|
||||
impl_from_arg_via_json!(SketchGroup);
|
||||
impl_from_arg_via_json!(FaceTag);
|
||||
impl_from_arg_via_json!(String);
|
||||
impl_from_arg_via_json!(u32);
|
||||
@ -618,21 +608,16 @@ impl_from_arg_via_json!(bool);
|
||||
impl_from_arg_for_array!(2);
|
||||
impl_from_arg_for_array!(3);
|
||||
|
||||
impl<'a> FromKclValue<'a> for &'a Box<SketchGroup> {
|
||||
impl<'a> FromKclValue<'a> for SketchGroupSet {
|
||||
fn from_mem_item(arg: &'a KclValue) -> Option<Self> {
|
||||
let KclValue::SketchGroup(s) = arg else {
|
||||
let KclValue::UserVal(uv) = arg else {
|
||||
return None;
|
||||
};
|
||||
Some(s)
|
||||
if let Some((x, _meta)) = uv.get::<SketchGroup>() {
|
||||
Some(SketchGroupSet::from(x))
|
||||
} else {
|
||||
uv.get::<Vec<SketchGroup>>().map(|x| x.0).map(SketchGroupSet::from)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> FromKclValue<'a> for Box<SketchGroup> {
|
||||
fn from_mem_item(arg: &'a KclValue) -> Option<Self> {
|
||||
let KclValue::SketchGroup(s) = arg else {
|
||||
return None;
|
||||
};
|
||||
Some(s.to_owned())
|
||||
}
|
||||
}
|
||||
|
||||
@ -656,15 +641,16 @@ impl<'a> FromKclValue<'a> for ExtrudeGroupSet {
|
||||
arg.get_extrude_group_set().ok()
|
||||
}
|
||||
}
|
||||
impl<'a> FromKclValue<'a> for SketchGroupSet {
|
||||
fn from_mem_item(arg: &'a KclValue) -> Option<Self> {
|
||||
arg.get_sketch_group_set().ok()
|
||||
}
|
||||
}
|
||||
impl<'a> FromKclValue<'a> for SketchSurfaceOrGroup {
|
||||
fn from_mem_item(arg: &'a KclValue) -> Option<Self> {
|
||||
match arg {
|
||||
KclValue::SketchGroup(sg) => Some(Self::SketchGroup(sg.clone())),
|
||||
KclValue::UserVal(uv) => {
|
||||
if let Some((sg, _meta)) = uv.get() {
|
||||
Some(Self::SketchGroup(sg))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
KclValue::Plane(sg) => Some(Self::SketchSurface(SketchSurface::Plane(sg.clone()))),
|
||||
KclValue::Face(sg) => Some(Self::SketchSurface(SketchSurface::Face(sg.clone()))),
|
||||
_ => None,
|
||||
|
@ -76,7 +76,7 @@ async fn inner_extrude(length: f64, sketch_group_set: SketchGroupSet, args: Args
|
||||
let id = uuid::Uuid::new_v4();
|
||||
|
||||
// Extrude the element(s).
|
||||
let sketch_groups: Vec<Box<SketchGroup>> = sketch_group_set.into();
|
||||
let sketch_groups: Vec<SketchGroup> = sketch_group_set.into();
|
||||
let mut extrude_groups = Vec::new();
|
||||
for sketch_group in &sketch_groups {
|
||||
// Before we extrude, we need to enable the sketch mode.
|
||||
@ -118,7 +118,7 @@ async fn inner_extrude(length: f64, sketch_group_set: SketchGroupSet, args: Args
|
||||
}
|
||||
|
||||
pub(crate) async fn do_post_extrude(
|
||||
sketch_group: Box<SketchGroup>,
|
||||
sketch_group: SketchGroup,
|
||||
length: f64,
|
||||
id: Uuid,
|
||||
args: Args,
|
||||
@ -155,7 +155,7 @@ pub(crate) async fn do_post_extrude(
|
||||
}));
|
||||
};
|
||||
|
||||
let mut sketch_group = *sketch_group.clone();
|
||||
let mut sketch_group = sketch_group.clone();
|
||||
|
||||
// If we were sketching on a face, we need the original face id.
|
||||
if let SketchSurface::Face(ref face) = sketch_group.on {
|
||||
|
@ -102,7 +102,7 @@ impl RevolveAxisAndOrigin {
|
||||
|
||||
/// Revolve a sketch around an axis.
|
||||
pub async fn revolve(args: Args) -> Result<KclValue, KclError> {
|
||||
let (data, sketch_group): (RevolveData, Box<SketchGroup>) = args.get_data_and_sketch_group()?;
|
||||
let (data, sketch_group): (RevolveData, SketchGroup) = args.get_data_and_sketch_group()?;
|
||||
|
||||
let extrude_group = inner_revolve(data, sketch_group, args).await?;
|
||||
Ok(KclValue::ExtrudeGroup(extrude_group))
|
||||
@ -249,7 +249,7 @@ pub async fn revolve(args: Args) -> Result<KclValue, KclError> {
|
||||
}]
|
||||
async fn inner_revolve(
|
||||
data: RevolveData,
|
||||
sketch_group: Box<SketchGroup>,
|
||||
sketch_group: SketchGroup,
|
||||
args: Args,
|
||||
) -> Result<Box<ExtrudeGroup>, KclError> {
|
||||
if let Some(angle) = data.angle {
|
||||
|
@ -108,7 +108,7 @@ pub async fn last_segment_x(args: Args) -> Result<KclValue, KclError> {
|
||||
#[stdlib {
|
||||
name = "lastSegX",
|
||||
}]
|
||||
fn inner_last_segment_x(sketch_group: Box<SketchGroup>, args: Args) -> Result<f64, KclError> {
|
||||
fn inner_last_segment_x(sketch_group: SketchGroup, args: Args) -> Result<f64, KclError> {
|
||||
let last_line = sketch_group
|
||||
.value
|
||||
.last()
|
||||
@ -151,7 +151,7 @@ pub async fn last_segment_y(args: Args) -> Result<KclValue, KclError> {
|
||||
#[stdlib {
|
||||
name = "lastSegY",
|
||||
}]
|
||||
fn inner_last_segment_y(sketch_group: Box<SketchGroup>, args: Args) -> Result<f64, KclError> {
|
||||
fn inner_last_segment_y(sketch_group: SketchGroup, args: Args) -> Result<f64, KclError> {
|
||||
let last_line = sketch_group
|
||||
.value
|
||||
.last()
|
||||
@ -281,7 +281,7 @@ pub async fn angle_to_match_length_x(args: Args) -> Result<KclValue, KclError> {
|
||||
fn inner_angle_to_match_length_x(
|
||||
tag: &TagIdentifier,
|
||||
to: f64,
|
||||
sketch_group: Box<SketchGroup>,
|
||||
sketch_group: SketchGroup,
|
||||
args: Args,
|
||||
) -> Result<f64, KclError> {
|
||||
let line = args.get_tag_engine_info(tag)?;
|
||||
@ -347,7 +347,7 @@ pub async fn angle_to_match_length_y(args: Args) -> Result<KclValue, KclError> {
|
||||
fn inner_angle_to_match_length_y(
|
||||
tag: &TagIdentifier,
|
||||
to: f64,
|
||||
sketch_group: Box<SketchGroup>,
|
||||
sketch_group: SketchGroup,
|
||||
args: Args,
|
||||
) -> Result<f64, KclError> {
|
||||
let line = args.get_tag_engine_info(tag)?;
|
||||
|
@ -27,7 +27,7 @@ pub async fn circle(args: Args) -> Result<KclValue, KclError> {
|
||||
args.get_circle_args()?;
|
||||
|
||||
let sketch_group = inner_circle(center, radius, sketch_surface_or_group, tag, args).await?;
|
||||
Ok(KclValue::SketchGroup(sketch_group))
|
||||
Ok(KclValue::new_user_val(sketch_group.meta.clone(), sketch_group))
|
||||
}
|
||||
|
||||
/// Construct a 2-dimensional circle, of the specified radius, centered at
|
||||
@ -60,7 +60,7 @@ async fn inner_circle(
|
||||
sketch_surface_or_group: SketchSurfaceOrGroup,
|
||||
tag: Option<TagDeclarator>,
|
||||
args: Args,
|
||||
) -> Result<Box<SketchGroup>, KclError> {
|
||||
) -> Result<SketchGroup, KclError> {
|
||||
let sketch_surface = match sketch_surface_or_group {
|
||||
SketchSurfaceOrGroup::SketchSurface(surface) => surface,
|
||||
SketchSurfaceOrGroup::SketchGroup(group) => group.on,
|
||||
|
@ -90,11 +90,11 @@ pub enum StartOrEnd {
|
||||
|
||||
/// Draw a line to a point.
|
||||
pub async fn line_to(args: Args) -> Result<KclValue, KclError> {
|
||||
let (to, sketch_group, tag): ([f64; 2], Box<SketchGroup>, Option<TagDeclarator>) =
|
||||
let (to, sketch_group, tag): ([f64; 2], SketchGroup, Option<TagDeclarator>) =
|
||||
args.get_data_and_sketch_group_and_tag()?;
|
||||
|
||||
let new_sketch_group = inner_line_to(to, sketch_group, tag, args).await?;
|
||||
Ok(KclValue::SketchGroup(new_sketch_group))
|
||||
Ok(KclValue::new_user_val(new_sketch_group.meta.clone(), new_sketch_group))
|
||||
}
|
||||
|
||||
/// Draw a line from the current origin to some absolute (x, y) point.
|
||||
@ -114,10 +114,10 @@ pub async fn line_to(args: Args) -> Result<KclValue, KclError> {
|
||||
}]
|
||||
async fn inner_line_to(
|
||||
to: [f64; 2],
|
||||
sketch_group: Box<SketchGroup>,
|
||||
sketch_group: SketchGroup,
|
||||
tag: Option<TagDeclarator>,
|
||||
args: Args,
|
||||
) -> Result<Box<SketchGroup>, KclError> {
|
||||
) -> Result<SketchGroup, KclError> {
|
||||
let from = sketch_group.current_pen_position()?;
|
||||
let id = uuid::Uuid::new_v4();
|
||||
|
||||
@ -161,11 +161,11 @@ async fn inner_line_to(
|
||||
|
||||
/// Draw a line to a point on the x-axis.
|
||||
pub async fn x_line_to(args: Args) -> Result<KclValue, KclError> {
|
||||
let (to, sketch_group, tag): (f64, Box<SketchGroup>, Option<TagDeclarator>) =
|
||||
let (to, sketch_group, tag): (f64, SketchGroup, Option<TagDeclarator>) =
|
||||
args.get_data_and_sketch_group_and_tag()?;
|
||||
|
||||
let new_sketch_group = inner_x_line_to(to, sketch_group, tag, args).await?;
|
||||
Ok(KclValue::SketchGroup(new_sketch_group))
|
||||
Ok(KclValue::new_user_val(new_sketch_group.meta.clone(), new_sketch_group))
|
||||
}
|
||||
|
||||
/// Draw a line parallel to the X axis, that ends at the given X.
|
||||
@ -196,10 +196,10 @@ pub async fn x_line_to(args: Args) -> Result<KclValue, KclError> {
|
||||
}]
|
||||
async fn inner_x_line_to(
|
||||
to: f64,
|
||||
sketch_group: Box<SketchGroup>,
|
||||
sketch_group: SketchGroup,
|
||||
tag: Option<TagDeclarator>,
|
||||
args: Args,
|
||||
) -> Result<Box<SketchGroup>, KclError> {
|
||||
) -> Result<SketchGroup, KclError> {
|
||||
let from = sketch_group.current_pen_position()?;
|
||||
|
||||
let new_sketch_group = inner_line_to([to, from.y], sketch_group, tag, args).await?;
|
||||
@ -209,11 +209,11 @@ async fn inner_x_line_to(
|
||||
|
||||
/// Draw a line to a point on the y-axis.
|
||||
pub async fn y_line_to(args: Args) -> Result<KclValue, KclError> {
|
||||
let (to, sketch_group, tag): (f64, Box<SketchGroup>, Option<TagDeclarator>) =
|
||||
let (to, sketch_group, tag): (f64, SketchGroup, Option<TagDeclarator>) =
|
||||
args.get_data_and_sketch_group_and_tag()?;
|
||||
|
||||
let new_sketch_group = inner_y_line_to(to, sketch_group, tag, args).await?;
|
||||
Ok(KclValue::SketchGroup(new_sketch_group))
|
||||
Ok(KclValue::new_user_val(new_sketch_group.meta.clone(), new_sketch_group))
|
||||
}
|
||||
|
||||
/// Draw a line parallel to the Y axis, that ends at the given Y.
|
||||
@ -237,10 +237,10 @@ pub async fn y_line_to(args: Args) -> Result<KclValue, KclError> {
|
||||
}]
|
||||
async fn inner_y_line_to(
|
||||
to: f64,
|
||||
sketch_group: Box<SketchGroup>,
|
||||
sketch_group: SketchGroup,
|
||||
tag: Option<TagDeclarator>,
|
||||
args: Args,
|
||||
) -> Result<Box<SketchGroup>, KclError> {
|
||||
) -> Result<SketchGroup, KclError> {
|
||||
let from = sketch_group.current_pen_position()?;
|
||||
|
||||
let new_sketch_group = inner_line_to([from.x, to], sketch_group, tag, args).await?;
|
||||
@ -249,11 +249,11 @@ async fn inner_y_line_to(
|
||||
|
||||
/// Draw a line.
|
||||
pub async fn line(args: Args) -> Result<KclValue, KclError> {
|
||||
let (delta, sketch_group, tag): ([f64; 2], Box<SketchGroup>, Option<TagDeclarator>) =
|
||||
let (delta, sketch_group, tag): ([f64; 2], SketchGroup, Option<TagDeclarator>) =
|
||||
args.get_data_and_sketch_group_and_tag()?;
|
||||
|
||||
let new_sketch_group = inner_line(delta, sketch_group, tag, args).await?;
|
||||
Ok(KclValue::SketchGroup(new_sketch_group))
|
||||
Ok(KclValue::new_user_val(new_sketch_group.meta.clone(), new_sketch_group))
|
||||
}
|
||||
|
||||
/// Draw a line relative to the current origin to a specified (x, y) away
|
||||
@ -285,10 +285,10 @@ pub async fn line(args: Args) -> Result<KclValue, KclError> {
|
||||
}]
|
||||
async fn inner_line(
|
||||
delta: [f64; 2],
|
||||
sketch_group: Box<SketchGroup>,
|
||||
sketch_group: SketchGroup,
|
||||
tag: Option<TagDeclarator>,
|
||||
args: Args,
|
||||
) -> Result<Box<SketchGroup>, KclError> {
|
||||
) -> Result<SketchGroup, KclError> {
|
||||
let from = sketch_group.current_pen_position()?;
|
||||
let to = [from.x + delta[0], from.y + delta[1]];
|
||||
|
||||
@ -334,11 +334,11 @@ async fn inner_line(
|
||||
|
||||
/// Draw a line on the x-axis.
|
||||
pub async fn x_line(args: Args) -> Result<KclValue, KclError> {
|
||||
let (length, sketch_group, tag): (f64, Box<SketchGroup>, Option<TagDeclarator>) =
|
||||
let (length, sketch_group, tag): (f64, SketchGroup, Option<TagDeclarator>) =
|
||||
args.get_data_and_sketch_group_and_tag()?;
|
||||
|
||||
let new_sketch_group = inner_x_line(length, sketch_group, tag, args).await?;
|
||||
Ok(KclValue::SketchGroup(new_sketch_group))
|
||||
Ok(KclValue::new_user_val(new_sketch_group.meta.clone(), new_sketch_group))
|
||||
}
|
||||
|
||||
/// Draw a line relative to the current origin to a specified distance away
|
||||
@ -368,20 +368,20 @@ pub async fn x_line(args: Args) -> Result<KclValue, KclError> {
|
||||
}]
|
||||
async fn inner_x_line(
|
||||
length: f64,
|
||||
sketch_group: Box<SketchGroup>,
|
||||
sketch_group: SketchGroup,
|
||||
tag: Option<TagDeclarator>,
|
||||
args: Args,
|
||||
) -> Result<Box<SketchGroup>, KclError> {
|
||||
) -> Result<SketchGroup, KclError> {
|
||||
inner_line([length, 0.0], sketch_group, tag, args).await
|
||||
}
|
||||
|
||||
/// Draw a line on the y-axis.
|
||||
pub async fn y_line(args: Args) -> Result<KclValue, KclError> {
|
||||
let (length, sketch_group, tag): (f64, Box<SketchGroup>, Option<TagDeclarator>) =
|
||||
let (length, sketch_group, tag): (f64, SketchGroup, Option<TagDeclarator>) =
|
||||
args.get_data_and_sketch_group_and_tag()?;
|
||||
|
||||
let new_sketch_group = inner_y_line(length, sketch_group, tag, args).await?;
|
||||
Ok(KclValue::SketchGroup(new_sketch_group))
|
||||
Ok(KclValue::new_user_val(new_sketch_group.meta.clone(), new_sketch_group))
|
||||
}
|
||||
|
||||
/// Draw a line relative to the current origin to a specified distance away
|
||||
@ -406,10 +406,10 @@ pub async fn y_line(args: Args) -> Result<KclValue, KclError> {
|
||||
}]
|
||||
async fn inner_y_line(
|
||||
length: f64,
|
||||
sketch_group: Box<SketchGroup>,
|
||||
sketch_group: SketchGroup,
|
||||
tag: Option<TagDeclarator>,
|
||||
args: Args,
|
||||
) -> Result<Box<SketchGroup>, KclError> {
|
||||
) -> Result<SketchGroup, KclError> {
|
||||
inner_line([0.0, length], sketch_group, tag, args).await
|
||||
}
|
||||
|
||||
@ -431,11 +431,11 @@ pub enum AngledLineData {
|
||||
|
||||
/// Draw an angled line.
|
||||
pub async fn angled_line(args: Args) -> Result<KclValue, KclError> {
|
||||
let (data, sketch_group, tag): (AngledLineData, Box<SketchGroup>, Option<TagDeclarator>) =
|
||||
let (data, sketch_group, tag): (AngledLineData, SketchGroup, Option<TagDeclarator>) =
|
||||
args.get_data_and_sketch_group_and_tag()?;
|
||||
|
||||
let new_sketch_group = inner_angled_line(data, sketch_group, tag, args).await?;
|
||||
Ok(KclValue::SketchGroup(new_sketch_group))
|
||||
Ok(KclValue::new_user_val(new_sketch_group.meta.clone(), new_sketch_group))
|
||||
}
|
||||
|
||||
/// Draw a line segment relative to the current origin using the polar
|
||||
@ -460,10 +460,10 @@ pub async fn angled_line(args: Args) -> Result<KclValue, KclError> {
|
||||
}]
|
||||
async fn inner_angled_line(
|
||||
data: AngledLineData,
|
||||
sketch_group: Box<SketchGroup>,
|
||||
sketch_group: SketchGroup,
|
||||
tag: Option<TagDeclarator>,
|
||||
args: Args,
|
||||
) -> Result<Box<SketchGroup>, KclError> {
|
||||
) -> Result<SketchGroup, KclError> {
|
||||
let from = sketch_group.current_pen_position()?;
|
||||
let (angle, length) = match data {
|
||||
AngledLineData::AngleAndLengthNamed { angle, length } => (angle, length),
|
||||
@ -520,11 +520,11 @@ async fn inner_angled_line(
|
||||
|
||||
/// Draw an angled line of a given x length.
|
||||
pub async fn angled_line_of_x_length(args: Args) -> Result<KclValue, KclError> {
|
||||
let (data, sketch_group, tag): (AngledLineData, Box<SketchGroup>, Option<TagDeclarator>) =
|
||||
let (data, sketch_group, tag): (AngledLineData, SketchGroup, Option<TagDeclarator>) =
|
||||
args.get_data_and_sketch_group_and_tag()?;
|
||||
|
||||
let new_sketch_group = inner_angled_line_of_x_length(data, sketch_group, tag, args).await?;
|
||||
Ok(KclValue::SketchGroup(new_sketch_group))
|
||||
Ok(KclValue::new_user_val(new_sketch_group.meta.clone(), new_sketch_group))
|
||||
}
|
||||
|
||||
/// Create a line segment from the current 2-dimensional sketch origin
|
||||
@ -545,10 +545,10 @@ pub async fn angled_line_of_x_length(args: Args) -> Result<KclValue, KclError> {
|
||||
}]
|
||||
async fn inner_angled_line_of_x_length(
|
||||
data: AngledLineData,
|
||||
sketch_group: Box<SketchGroup>,
|
||||
sketch_group: SketchGroup,
|
||||
tag: Option<TagDeclarator>,
|
||||
args: Args,
|
||||
) -> Result<Box<SketchGroup>, KclError> {
|
||||
) -> Result<SketchGroup, KclError> {
|
||||
let (angle, length) = match data {
|
||||
AngledLineData::AngleAndLengthNamed { angle, length } => (angle, length),
|
||||
AngledLineData::AngleAndLengthPair(pair) => (pair[0], pair[1]),
|
||||
@ -588,11 +588,11 @@ pub struct AngledLineToData {
|
||||
|
||||
/// Draw an angled line to a given x coordinate.
|
||||
pub async fn angled_line_to_x(args: Args) -> Result<KclValue, KclError> {
|
||||
let (data, sketch_group, tag): (AngledLineToData, Box<SketchGroup>, Option<TagDeclarator>) =
|
||||
let (data, sketch_group, tag): (AngledLineToData, SketchGroup, Option<TagDeclarator>) =
|
||||
args.get_data_and_sketch_group_and_tag()?;
|
||||
|
||||
let new_sketch_group = inner_angled_line_to_x(data, sketch_group, tag, args).await?;
|
||||
Ok(KclValue::SketchGroup(new_sketch_group))
|
||||
Ok(KclValue::new_user_val(new_sketch_group.meta.clone(), new_sketch_group))
|
||||
}
|
||||
|
||||
/// Create a line segment from the current 2-dimensional sketch origin
|
||||
@ -614,10 +614,10 @@ pub async fn angled_line_to_x(args: Args) -> Result<KclValue, KclError> {
|
||||
}]
|
||||
async fn inner_angled_line_to_x(
|
||||
data: AngledLineToData,
|
||||
sketch_group: Box<SketchGroup>,
|
||||
sketch_group: SketchGroup,
|
||||
tag: Option<TagDeclarator>,
|
||||
args: Args,
|
||||
) -> Result<Box<SketchGroup>, KclError> {
|
||||
) -> Result<SketchGroup, KclError> {
|
||||
let from = sketch_group.current_pen_position()?;
|
||||
let AngledLineToData { angle, to: x_to } = data;
|
||||
|
||||
@ -645,12 +645,12 @@ async fn inner_angled_line_to_x(
|
||||
|
||||
/// Draw an angled line of a given y length.
|
||||
pub async fn angled_line_of_y_length(args: Args) -> Result<KclValue, KclError> {
|
||||
let (data, sketch_group, tag): (AngledLineData, Box<SketchGroup>, Option<TagDeclarator>) =
|
||||
let (data, sketch_group, tag): (AngledLineData, SketchGroup, Option<TagDeclarator>) =
|
||||
args.get_data_and_sketch_group_and_tag()?;
|
||||
|
||||
let new_sketch_group = inner_angled_line_of_y_length(data, sketch_group, tag, args).await?;
|
||||
|
||||
Ok(KclValue::SketchGroup(new_sketch_group))
|
||||
Ok(KclValue::new_user_val(new_sketch_group.meta.clone(), new_sketch_group))
|
||||
}
|
||||
|
||||
/// Create a line segment from the current 2-dimensional sketch origin
|
||||
@ -673,10 +673,10 @@ pub async fn angled_line_of_y_length(args: Args) -> Result<KclValue, KclError> {
|
||||
}]
|
||||
async fn inner_angled_line_of_y_length(
|
||||
data: AngledLineData,
|
||||
sketch_group: Box<SketchGroup>,
|
||||
sketch_group: SketchGroup,
|
||||
tag: Option<TagDeclarator>,
|
||||
args: Args,
|
||||
) -> Result<Box<SketchGroup>, KclError> {
|
||||
) -> Result<SketchGroup, KclError> {
|
||||
let (angle, length) = match data {
|
||||
AngledLineData::AngleAndLengthNamed { angle, length } => (angle, length),
|
||||
AngledLineData::AngleAndLengthPair(pair) => (pair[0], pair[1]),
|
||||
@ -705,11 +705,11 @@ async fn inner_angled_line_of_y_length(
|
||||
|
||||
/// Draw an angled line to a given y coordinate.
|
||||
pub async fn angled_line_to_y(args: Args) -> Result<KclValue, KclError> {
|
||||
let (data, sketch_group, tag): (AngledLineToData, Box<SketchGroup>, Option<TagDeclarator>) =
|
||||
let (data, sketch_group, tag): (AngledLineToData, SketchGroup, Option<TagDeclarator>) =
|
||||
args.get_data_and_sketch_group_and_tag()?;
|
||||
|
||||
let new_sketch_group = inner_angled_line_to_y(data, sketch_group, tag, args).await?;
|
||||
Ok(KclValue::SketchGroup(new_sketch_group))
|
||||
Ok(KclValue::new_user_val(new_sketch_group.meta.clone(), new_sketch_group))
|
||||
}
|
||||
|
||||
/// Create a line segment from the current 2-dimensional sketch origin
|
||||
@ -731,10 +731,10 @@ pub async fn angled_line_to_y(args: Args) -> Result<KclValue, KclError> {
|
||||
}]
|
||||
async fn inner_angled_line_to_y(
|
||||
data: AngledLineToData,
|
||||
sketch_group: Box<SketchGroup>,
|
||||
sketch_group: SketchGroup,
|
||||
tag: Option<TagDeclarator>,
|
||||
args: Args,
|
||||
) -> Result<Box<SketchGroup>, KclError> {
|
||||
) -> Result<SketchGroup, KclError> {
|
||||
let from = sketch_group.current_pen_position()?;
|
||||
let AngledLineToData { angle, to: y_to } = data;
|
||||
|
||||
@ -776,10 +776,10 @@ pub struct AngledLineThatIntersectsData {
|
||||
|
||||
/// Draw an angled line that intersects with a given line.
|
||||
pub async fn angled_line_that_intersects(args: Args) -> Result<KclValue, KclError> {
|
||||
let (data, sketch_group, tag): (AngledLineThatIntersectsData, Box<SketchGroup>, Option<TagDeclarator>) =
|
||||
let (data, sketch_group, tag): (AngledLineThatIntersectsData, SketchGroup, Option<TagDeclarator>) =
|
||||
args.get_data_and_sketch_group_and_tag()?;
|
||||
let new_sketch_group = inner_angled_line_that_intersects(data, sketch_group, tag, args).await?;
|
||||
Ok(KclValue::SketchGroup(new_sketch_group))
|
||||
Ok(KclValue::new_user_val(new_sketch_group.meta.clone(), new_sketch_group))
|
||||
}
|
||||
|
||||
/// Draw an angled line from the current origin, constructing a line segment
|
||||
@ -806,10 +806,10 @@ pub async fn angled_line_that_intersects(args: Args) -> Result<KclValue, KclErro
|
||||
}]
|
||||
async fn inner_angled_line_that_intersects(
|
||||
data: AngledLineThatIntersectsData,
|
||||
sketch_group: Box<SketchGroup>,
|
||||
sketch_group: SketchGroup,
|
||||
tag: Option<TagDeclarator>,
|
||||
args: Args,
|
||||
) -> Result<Box<SketchGroup>, KclError> {
|
||||
) -> Result<SketchGroup, KclError> {
|
||||
let intersect_path = args.get_tag_engine_info(&data.intersect_tag)?;
|
||||
let path = intersect_path.path.clone().ok_or_else(|| {
|
||||
KclError::Type(KclErrorDetails {
|
||||
@ -835,7 +835,7 @@ pub async fn start_sketch_at(args: Args) -> Result<KclValue, KclError> {
|
||||
let data: [f64; 2] = args.get_data()?;
|
||||
|
||||
let sketch_group = inner_start_sketch_at(data, args).await?;
|
||||
Ok(KclValue::SketchGroup(sketch_group))
|
||||
Ok(KclValue::new_user_val(sketch_group.meta.clone(), sketch_group))
|
||||
}
|
||||
|
||||
/// Start a new 2-dimensional sketch at a given point on the 'XY' plane.
|
||||
@ -872,7 +872,7 @@ pub async fn start_sketch_at(args: Args) -> Result<KclValue, KclError> {
|
||||
#[stdlib {
|
||||
name = "startSketchAt",
|
||||
}]
|
||||
async fn inner_start_sketch_at(data: [f64; 2], args: Args) -> Result<Box<SketchGroup>, KclError> {
|
||||
async fn inner_start_sketch_at(data: [f64; 2], args: Args) -> Result<SketchGroup, KclError> {
|
||||
// Let's assume it's the XY plane for now, this is just for backwards compatibility.
|
||||
let xy_plane = PlaneData::XY;
|
||||
let sketch_surface = inner_start_sketch_on(SketchData::Plane(xy_plane), None, args.clone()).await?;
|
||||
@ -1204,7 +1204,7 @@ pub async fn start_profile_at(args: Args) -> Result<KclValue, KclError> {
|
||||
args.get_data_and_sketch_surface()?;
|
||||
|
||||
let sketch_group = inner_start_profile_at(start, sketch_surface, tag, args).await?;
|
||||
Ok(KclValue::SketchGroup(sketch_group))
|
||||
Ok(KclValue::new_user_val(sketch_group.meta.clone(), sketch_group))
|
||||
}
|
||||
|
||||
/// Start a new profile at a given point.
|
||||
@ -1249,7 +1249,7 @@ pub(crate) async fn inner_start_profile_at(
|
||||
sketch_surface: SketchSurface,
|
||||
tag: Option<TagDeclarator>,
|
||||
args: Args,
|
||||
) -> Result<Box<SketchGroup>, KclError> {
|
||||
) -> Result<SketchGroup, KclError> {
|
||||
if let SketchSurface::Face(face) = &sketch_surface {
|
||||
// Flush the batch for our fillets/chamfers if there are any.
|
||||
// If we do not do these for sketch on face, things will fail with face does not exist.
|
||||
@ -1324,12 +1324,12 @@ pub(crate) async fn inner_start_profile_at(
|
||||
},
|
||||
start: current_path,
|
||||
};
|
||||
Ok(Box::new(sketch_group))
|
||||
Ok(sketch_group)
|
||||
}
|
||||
|
||||
/// Returns the X component of the sketch profile start point.
|
||||
pub async fn profile_start_x(args: Args) -> Result<KclValue, KclError> {
|
||||
let sketch_group: Box<SketchGroup> = args.get_sketch_group()?;
|
||||
let sketch_group: SketchGroup = args.get_sketch_group()?;
|
||||
let x = inner_profile_start_x(sketch_group)?;
|
||||
args.make_user_val_from_f64(x)
|
||||
}
|
||||
@ -1347,13 +1347,13 @@ pub async fn profile_start_x(args: Args) -> Result<KclValue, KclError> {
|
||||
#[stdlib {
|
||||
name = "profileStartX"
|
||||
}]
|
||||
pub(crate) fn inner_profile_start_x(sketch_group: Box<SketchGroup>) -> Result<f64, KclError> {
|
||||
pub(crate) fn inner_profile_start_x(sketch_group: SketchGroup) -> Result<f64, KclError> {
|
||||
Ok(sketch_group.start.to[0])
|
||||
}
|
||||
|
||||
/// Returns the Y component of the sketch profile start point.
|
||||
pub async fn profile_start_y(args: Args) -> Result<KclValue, KclError> {
|
||||
let sketch_group: Box<SketchGroup> = args.get_sketch_group()?;
|
||||
let sketch_group: SketchGroup = args.get_sketch_group()?;
|
||||
let x = inner_profile_start_y(sketch_group)?;
|
||||
args.make_user_val_from_f64(x)
|
||||
}
|
||||
@ -1370,13 +1370,13 @@ pub async fn profile_start_y(args: Args) -> Result<KclValue, KclError> {
|
||||
#[stdlib {
|
||||
name = "profileStartY"
|
||||
}]
|
||||
pub(crate) fn inner_profile_start_y(sketch_group: Box<SketchGroup>) -> Result<f64, KclError> {
|
||||
pub(crate) fn inner_profile_start_y(sketch_group: SketchGroup) -> Result<f64, KclError> {
|
||||
Ok(sketch_group.start.to[1])
|
||||
}
|
||||
|
||||
/// Returns the sketch profile start point.
|
||||
pub async fn profile_start(args: Args) -> Result<KclValue, KclError> {
|
||||
let sketch_group: Box<SketchGroup> = args.get_sketch_group()?;
|
||||
let sketch_group: SketchGroup = args.get_sketch_group()?;
|
||||
let point = inner_profile_start(sketch_group)?;
|
||||
Ok(KclValue::UserVal(UserVal {
|
||||
value: serde_json::to_value(point).map_err(|e| {
|
||||
@ -1404,17 +1404,17 @@ pub async fn profile_start(args: Args) -> Result<KclValue, KclError> {
|
||||
#[stdlib {
|
||||
name = "profileStart"
|
||||
}]
|
||||
pub(crate) fn inner_profile_start(sketch_group: Box<SketchGroup>) -> Result<[f64; 2], KclError> {
|
||||
pub(crate) fn inner_profile_start(sketch_group: SketchGroup) -> Result<[f64; 2], KclError> {
|
||||
Ok(sketch_group.start.to)
|
||||
}
|
||||
|
||||
/// Close the current sketch.
|
||||
pub async fn close(args: Args) -> Result<KclValue, KclError> {
|
||||
let (sketch_group, tag): (Box<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?;
|
||||
|
||||
Ok(KclValue::SketchGroup(new_sketch_group))
|
||||
Ok(KclValue::new_user_val(new_sketch_group.meta.clone(), new_sketch_group))
|
||||
}
|
||||
|
||||
/// Construct a line segment from the current origin back to the profile's
|
||||
@ -1442,10 +1442,10 @@ pub async fn close(args: Args) -> Result<KclValue, KclError> {
|
||||
name = "close",
|
||||
}]
|
||||
pub(crate) async fn inner_close(
|
||||
sketch_group: Box<SketchGroup>,
|
||||
sketch_group: SketchGroup,
|
||||
tag: Option<TagDeclarator>,
|
||||
args: Args,
|
||||
) -> Result<Box<SketchGroup>, KclError> {
|
||||
) -> Result<SketchGroup, KclError> {
|
||||
let from = sketch_group.current_pen_position()?;
|
||||
let to: Point2d = sketch_group.start.from.into();
|
||||
|
||||
@ -1517,11 +1517,11 @@ pub enum ArcData {
|
||||
|
||||
/// Draw an arc.
|
||||
pub async fn arc(args: Args) -> Result<KclValue, KclError> {
|
||||
let (data, sketch_group, tag): (ArcData, Box<SketchGroup>, Option<TagDeclarator>) =
|
||||
let (data, sketch_group, tag): (ArcData, SketchGroup, Option<TagDeclarator>) =
|
||||
args.get_data_and_sketch_group_and_tag()?;
|
||||
|
||||
let new_sketch_group = inner_arc(data, sketch_group, tag, args).await?;
|
||||
Ok(KclValue::SketchGroup(new_sketch_group))
|
||||
Ok(KclValue::new_user_val(new_sketch_group.meta.clone(), new_sketch_group))
|
||||
}
|
||||
|
||||
/// Starting at the current sketch's origin, draw a curved line segment along
|
||||
@ -1553,10 +1553,10 @@ pub async fn arc(args: Args) -> Result<KclValue, KclError> {
|
||||
}]
|
||||
pub(crate) async fn inner_arc(
|
||||
data: ArcData,
|
||||
sketch_group: Box<SketchGroup>,
|
||||
sketch_group: SketchGroup,
|
||||
tag: Option<TagDeclarator>,
|
||||
args: Args,
|
||||
) -> Result<Box<SketchGroup>, KclError> {
|
||||
) -> Result<SketchGroup, KclError> {
|
||||
let from: Point2d = sketch_group.current_pen_position()?;
|
||||
|
||||
let (center, angle_start, angle_end, radius, end) = match &data {
|
||||
@ -1640,11 +1640,11 @@ pub enum TangentialArcData {
|
||||
|
||||
/// Draw a tangential arc.
|
||||
pub async fn tangential_arc(args: Args) -> Result<KclValue, KclError> {
|
||||
let (data, sketch_group, tag): (TangentialArcData, Box<SketchGroup>, Option<TagDeclarator>) =
|
||||
let (data, sketch_group, tag): (TangentialArcData, SketchGroup, Option<TagDeclarator>) =
|
||||
args.get_data_and_sketch_group_and_tag()?;
|
||||
|
||||
let new_sketch_group = inner_tangential_arc(data, sketch_group, tag, args).await?;
|
||||
Ok(KclValue::SketchGroup(new_sketch_group))
|
||||
Ok(KclValue::new_user_val(new_sketch_group.meta.clone(), new_sketch_group))
|
||||
}
|
||||
|
||||
/// Starting at the current sketch's origin, draw a curved line segment along
|
||||
@ -1676,10 +1676,10 @@ pub async fn tangential_arc(args: Args) -> Result<KclValue, KclError> {
|
||||
}]
|
||||
async fn inner_tangential_arc(
|
||||
data: TangentialArcData,
|
||||
sketch_group: Box<SketchGroup>,
|
||||
sketch_group: SketchGroup,
|
||||
tag: Option<TagDeclarator>,
|
||||
args: Args,
|
||||
) -> Result<Box<SketchGroup>, KclError> {
|
||||
) -> Result<SketchGroup, KclError> {
|
||||
let from: Point2d = sketch_group.current_pen_position()?;
|
||||
// next set of lines is some undocumented voodoo from get_tangential_arc_to_info
|
||||
let tangent_info = sketch_group.get_tangential_info_from_paths(); //this function desperately needs some documentation
|
||||
@ -1793,7 +1793,7 @@ pub async fn tangential_arc_to(args: Args) -> Result<KclValue, KclError> {
|
||||
// Get arguments to function call
|
||||
let mut it = args.args.iter();
|
||||
let to: [f64; 2] = get_arg(&mut it, src)?.get_json()?;
|
||||
let sketch_group: Box<SketchGroup> = get_arg(&mut it, src)?.get_json()?;
|
||||
let sketch_group: SketchGroup = get_arg(&mut it, src)?.get_json()?;
|
||||
let tag = if let Ok(memory_item) = get_arg(&mut it, src) {
|
||||
memory_item.get_json_opt()?
|
||||
} else {
|
||||
@ -1801,7 +1801,7 @@ pub async fn tangential_arc_to(args: Args) -> Result<KclValue, KclError> {
|
||||
};
|
||||
|
||||
let new_sketch_group = inner_tangential_arc_to(to, sketch_group, tag, args).await?;
|
||||
Ok(KclValue::SketchGroup(new_sketch_group))
|
||||
Ok(KclValue::new_user_val(new_sketch_group.meta.clone(), new_sketch_group))
|
||||
}
|
||||
|
||||
/// Starting at the current sketch's origin, draw a curved line segment along
|
||||
@ -1826,10 +1826,10 @@ pub async fn tangential_arc_to(args: Args) -> Result<KclValue, KclError> {
|
||||
}]
|
||||
async fn inner_tangential_arc_to(
|
||||
to: [f64; 2],
|
||||
sketch_group: Box<SketchGroup>,
|
||||
sketch_group: SketchGroup,
|
||||
tag: Option<TagDeclarator>,
|
||||
args: Args,
|
||||
) -> Result<Box<SketchGroup>, KclError> {
|
||||
) -> Result<SketchGroup, KclError> {
|
||||
let from: Point2d = sketch_group.current_pen_position()?;
|
||||
let tangent_info = sketch_group.get_tangential_info_from_paths();
|
||||
let tan_previous_point = if tangent_info.is_center {
|
||||
@ -1888,11 +1888,11 @@ pub struct BezierData {
|
||||
|
||||
/// Draw a bezier curve.
|
||||
pub async fn bezier_curve(args: Args) -> Result<KclValue, KclError> {
|
||||
let (data, sketch_group, tag): (BezierData, Box<SketchGroup>, Option<TagDeclarator>) =
|
||||
let (data, sketch_group, tag): (BezierData, SketchGroup, Option<TagDeclarator>) =
|
||||
args.get_data_and_sketch_group_and_tag()?;
|
||||
|
||||
let new_sketch_group = inner_bezier_curve(data, sketch_group, tag, args).await?;
|
||||
Ok(KclValue::SketchGroup(new_sketch_group))
|
||||
Ok(KclValue::new_user_val(new_sketch_group.meta.clone(), new_sketch_group))
|
||||
}
|
||||
|
||||
/// Draw a smooth, continuous, curved line segment from the current origin to
|
||||
@ -1918,10 +1918,10 @@ pub async fn bezier_curve(args: Args) -> Result<KclValue, KclError> {
|
||||
}]
|
||||
async fn inner_bezier_curve(
|
||||
data: BezierData,
|
||||
sketch_group: Box<SketchGroup>,
|
||||
sketch_group: SketchGroup,
|
||||
tag: Option<TagDeclarator>,
|
||||
args: Args,
|
||||
) -> Result<Box<SketchGroup>, KclError> {
|
||||
) -> Result<SketchGroup, KclError> {
|
||||
let from = sketch_group.current_pen_position()?;
|
||||
|
||||
let relative = true;
|
||||
@ -1980,10 +1980,10 @@ async fn inner_bezier_curve(
|
||||
|
||||
/// Use a sketch to cut a hole in another sketch.
|
||||
pub async fn hole(args: Args) -> Result<KclValue, KclError> {
|
||||
let (hole_sketch_group, sketch_group): (SketchGroupSet, Box<SketchGroup>) = args.get_sketch_groups()?;
|
||||
let (hole_sketch_group, sketch_group): (SketchGroupSet, SketchGroup) = args.get_sketch_groups()?;
|
||||
|
||||
let new_sketch_group = inner_hole(hole_sketch_group, sketch_group, args).await?;
|
||||
Ok(KclValue::SketchGroup(new_sketch_group))
|
||||
Ok(KclValue::new_user_val(new_sketch_group.meta.clone(), new_sketch_group))
|
||||
}
|
||||
|
||||
/// Use a 2-dimensional sketch to cut a hole in another 2-dimensional sketch.
|
||||
@ -2022,10 +2022,10 @@ pub async fn hole(args: Args) -> Result<KclValue, KclError> {
|
||||
}]
|
||||
async fn inner_hole(
|
||||
hole_sketch_group: SketchGroupSet,
|
||||
sketch_group: Box<SketchGroup>,
|
||||
sketch_group: SketchGroup,
|
||||
args: Args,
|
||||
) -> Result<Box<SketchGroup>, KclError> {
|
||||
let hole_sketch_groups: Vec<Box<SketchGroup>> = hole_sketch_group.into();
|
||||
) -> Result<SketchGroup, KclError> {
|
||||
let hole_sketch_groups: Vec<SketchGroup> = hole_sketch_group.into();
|
||||
for hole_sketch_group in hole_sketch_groups {
|
||||
args.batch_modeling_cmd(
|
||||
uuid::Uuid::new_v4(),
|
||||
|
@ -1,7 +1,7 @@
|
||||
use anyhow::Result;
|
||||
use kcl_lib::{
|
||||
ast::{modify::modify_ast_for_sketch, types::Program},
|
||||
executor::{ExecutorContext, KclValue, PlaneType, SourceRange},
|
||||
executor::{ExecutorContext, KclValue, PlaneType, SketchGroup, SourceRange},
|
||||
};
|
||||
use kittycad::types::{ModelingCmd, Point3D};
|
||||
use pretty_assertions::assert_eq;
|
||||
@ -39,9 +39,12 @@ async fn setup(code: &str, name: &str) -> Result<(ExecutorContext, Program, uuid
|
||||
|
||||
// We need to get the sketch ID.
|
||||
// Get the sketch group ID from memory.
|
||||
let KclValue::SketchGroup(sketch_group) = memory.get(name, SourceRange::default()).unwrap() else {
|
||||
let KclValue::UserVal(user_val) = memory.get(name, SourceRange::default()).unwrap() else {
|
||||
anyhow::bail!("part001 not found in memory: {:?}", memory);
|
||||
};
|
||||
let Some((sketch_group, _meta)) = user_val.get::<SketchGroup>() else {
|
||||
anyhow::bail!("part001 was not a SketchGroup");
|
||||
};
|
||||
let sketch_id = sketch_group.id;
|
||||
|
||||
let plane_id = uuid::Uuid::new_v4();
|
||||
|
Reference in New Issue
Block a user