diff --git a/src/components/RenderViewerArtifacts.tsx b/src/components/RenderViewerArtifacts.tsx index 4d427c3df..a639be787 100644 --- a/src/components/RenderViewerArtifacts.tsx +++ b/src/components/RenderViewerArtifacts.tsx @@ -240,6 +240,14 @@ function RenderViewerArtifact({ if (artifact.type === 'sketchGroup') { return ( <> + {artifact.start && ( + + )} {artifact.value.map((geoInfo, key) => ( {geoInfo.__geoMeta.geos.map((meta, i) => { - if (meta.type === 'line') { + if (meta.type === 'line') return ( ) - } - if (meta.type === 'lineEnd') { + if (meta.type === 'lineEnd') return ( ) - } + if (meta.type === 'sketchBase') + return ( + + ) })} ) diff --git a/src/components/Toolbar/SetHorzDistance.tsx b/src/components/Toolbar/SetHorzDistance.tsx index af4d659a2..089e0221e 100644 --- a/src/components/Toolbar/SetHorzDistance.tsx +++ b/src/components/Toolbar/SetHorzDistance.tsx @@ -60,7 +60,10 @@ export const SetHorzDistance = ({ const isAllTooltips = nodes.every( (node) => node?.type === 'CallExpression' && - toolTips.includes(node.callee.name as any) + [ + ...toolTips, + 'startSketchAt', // TODO probably a better place for this to live + ].includes(node.callee.name as any) ) const theTransforms = getTransformInfos( diff --git a/src/index.css b/src/index.css index 799de70de..2f1e8afda 100644 --- a/src/index.css +++ b/src/index.css @@ -25,5 +25,5 @@ code { #code-mirror-override .cm-cursor { display: block; width: 200px; - background: linear-gradient(to right, rgb(0, 55, 94) 0%, #0084e2ff 2%, #0084e255 5%, transparent 100%); + background: linear-gradient(to right, rgb(0, 55, 94) 0%, #0084e2ff 2%, #0084e255 5%, transparent 100%); } diff --git a/src/lang/artifact.test.ts b/src/lang/artifact.test.ts index 199e67e01..f54ad6969 100644 --- a/src/lang/artifact.test.ts +++ b/src/lang/artifact.test.ts @@ -21,7 +21,16 @@ show(mySketch001)` expect(artifactsWithoutGeos).toEqual([ { type: 'sketchGroup', - start: [0, 0], + start: { + type: 'base', + to: [0, 0], + from: [0, 0], + __geoMeta: { + sourceRange: [21, 42], + pathToNode: [], + geos: ['sketchBase'], + }, + }, value: [ { type: 'toPoint', @@ -275,6 +284,15 @@ function removeGeo(arts: (SketchGroup | ExtrudeGroup)[]): any { } return { ...art, + start: art.start + ? { + ...art.start, + __geoMeta: { + ...art.start.__geoMeta, + geos: art.start.__geoMeta.geos.map((g) => g.type), + }, + } + : {}, value: art.value.map((v) => ({ ...v, __geoMeta: { diff --git a/src/lang/engine.tsx b/src/lang/engine.tsx index 3037783fb..a8916dae0 100644 --- a/src/lang/engine.tsx +++ b/src/lang/engine.tsx @@ -88,6 +88,12 @@ export function lineGeo({ } } +export function sketchBaseGeo({ to }: { to: [number, number, number] }): { + base: BufferGeometry +} { + return { base: new SphereGeometry(0.25).translate(to[0], to[1], to[2]) } +} + export interface extrudeWallGeo { line: BufferGeometry tip: BufferGeometry diff --git a/src/lang/executor.test.ts b/src/lang/executor.test.ts index ee8364a7f..ef7ba0388 100644 --- a/src/lang/executor.test.ts +++ b/src/lang/executor.test.ts @@ -166,7 +166,16 @@ show(mySketch) const striptVersion = removeGeoFromSketch(root.mySk1 as SketchGroup) expect(striptVersion).toEqual({ type: 'sketchGroup', - start: [0, 0], + start: { + type: 'base', + to: [0, 0], + from: [0, 0], + __geoMeta: { + sourceRange: [14, 34], + pathToNode: [], + geos: ['sketchBase'], + }, + }, value: [ { type: 'toPoint', @@ -420,6 +429,15 @@ function exe( function removeGeoFromSketch(sketch: SketchGroup): SketchGroup { return { ...sketch, + start: !sketch.start + ? undefined + : { + ...sketch.start, + __geoMeta: { + ...sketch.start.__geoMeta, + geos: sketch.start.__geoMeta.geos.map((geo) => geo.type as any), + }, + }, value: removeGeoFromPaths(sketch.value), } } diff --git a/src/lang/executor.ts b/src/lang/executor.ts index 24f01e999..aaf862bd6 100644 --- a/src/lang/executor.ts +++ b/src/lang/executor.ts @@ -30,7 +30,7 @@ interface BasePath { __geoMeta: { geos: { geo: BufferGeometry - type: 'line' | 'lineEnd' + type: 'line' | 'lineEnd' | 'sketchBase' }[] sourceRange: SourceRange pathToNode: PathToNode @@ -41,6 +41,10 @@ export interface ToPoint extends BasePath { type: 'toPoint' } +export interface Base extends BasePath { + type: 'base' +} + export interface HorizontalLineTo extends BasePath { type: 'horizontalLineTo' x: number @@ -61,12 +65,12 @@ interface GeoMeta { } } -export type Path = ToPoint | HorizontalLineTo | AngledLineTo +export type Path = ToPoint | HorizontalLineTo | AngledLineTo | Base export interface SketchGroup { type: 'sketchGroup' value: Path[] - start?: Path['from'] + start?: Base position: Position rotation: Rotation __meta: Metadata[] diff --git a/src/lang/std/sketch.ts b/src/lang/std/sketch.ts index 9051b6931..247bc0785 100644 --- a/src/lang/std/sketch.ts +++ b/src/lang/std/sketch.ts @@ -18,7 +18,7 @@ import { getNodeFromPathCurry, getNodePathFromSourceRange, } from '../queryAst' -import { lineGeo } from '../engine' +import { lineGeo, sketchBaseGeo } from '../engine' import { GuiModes, toolTips, TooTip } from '../../useStore' import { getLastIndex } from '../modifyAst' @@ -46,7 +46,7 @@ export type Coords2d = [number, number] export function getCoordsFromPaths(skGroup: SketchGroup, index = 0): Coords2d { const currentPath = skGroup?.value?.[index] if (!currentPath && skGroup?.start) { - return skGroup.start + return skGroup.start.to } else if (!currentPath) { return [0, 0] } @@ -83,6 +83,8 @@ export function createFirstArg( return createObjectExpression({ length: val, tag }) if (['xLineTo', 'yLineTo'].includes(sketchFn)) return createObjectExpression({ to: val, tag }) + if (['startSketchAt'].includes(sketchFn)) + return createObjectExpression({ to: val, tag }) } throw new Error('all sketch line types should have been covered') } @@ -895,18 +897,22 @@ export const angledLineToX: SketchLineHelper = { ) const angle = createLiteral(roundOff(getAngle(from, to), 0)) const xArg = createLiteral(roundOff(to[0], 2)) - const newLine = createCallback - ? createCallback([angle, xArg]).callExp - : createCallExpression('angledLineToX', [ - createArrayExpression([angle, xArg]), - createPipeSubstitution(), - ]) - const callIndex = getLastIndex(pathToNode) - if (replaceExisting) { - pipe.body[callIndex] = newLine - } else { - pipe.body = [...pipe.body, newLine] + if (replaceExisting && createCallback) { + const { callExp, valueUsedInTransform } = createCallback([angle, xArg]) + const callIndex = getLastIndex(pathToNode) + pipe.body[callIndex] = callExp + return { + modifiedAst: _node, + pathToNode, + valueUsedInTransform, + } } + + const callExp = createCallExpression('angledLineToX', [ + createArrayExpression([angle, xArg]), + createPipeSubstitution(), + ]) + pipe.body = [...pipe.body, callExp] return { modifiedAst: _node, pathToNode, @@ -1288,14 +1294,20 @@ export const startSketchAt: InternalFn = ( } ): SketchGroup => { const to = 'to' in data ? data.to : data + const geo = sketchBaseGeo({ to: [...to, 0] }) const currentPath: Path = { - type: 'toPoint', + type: 'base', to, from: to, __geoMeta: { sourceRange, pathToNode: [], // TODO - geos: [], + geos: [ + { + type: 'sketchBase', + geo: geo.base, + }, + ], }, } if ('tag' in data) { @@ -1303,7 +1315,7 @@ export const startSketchAt: InternalFn = ( } return { type: 'sketchGroup', - start: to, + start: currentPath, value: [], position: [0, 0, 0], rotation: [0, 0, 0, 1], @@ -1393,7 +1405,7 @@ function getFirstArgValuesForXYLineFns(callExpression: CallExpression): { return { val: firstArg } } const tag = firstArg.properties.find((p) => p.key.name === 'tag')?.value - const secondArgName = ['xLineTo', 'yLineTo'].includes( + const secondArgName = ['xLineTo', 'yLineTo', 'startSketchAt'].includes( // const secondArgName = ['xLineTo', 'yLineTo', 'angledLineToX', 'angledLineToY'].includes( callExpression?.callee?.name ) @@ -1430,5 +1442,8 @@ export function getFirstArg(callExp: CallExpression): { if (['xLine', 'yLine', 'xLineTo', 'yLineTo'].includes(name)) { return getFirstArgValuesForXYLineFns(callExp) } + if (['startSketchAt'].includes(name)) { + return getFirstArgValuesForXYLineFns(callExp) + } throw new Error('unexpected call expression') } diff --git a/src/lang/std/sketchConstraints.ts b/src/lang/std/sketchConstraints.ts index 759d752c2..5ed5e8aae 100644 --- a/src/lang/std/sketchConstraints.ts +++ b/src/lang/std/sketchConstraints.ts @@ -35,7 +35,10 @@ export const segLen: InternalFn = ( function segEndFactory(which: 'x' | 'y'): InternalFn { return (_, segName: string, sketchGroup: SketchGroup): number => { - const line = sketchGroup?.value.find((seg) => seg.name === segName) + const line = + sketchGroup.start?.name === segName + ? sketchGroup.start + : sketchGroup?.value.find((seg) => seg.name === segName) // maybe this should throw, but the language doesn't have a way to handle errors yet if (!line) return 0 return which === 'x' ? line.to[0] : line.to[1]