diff --git a/package.json b/package.json index f32c308ca..278dbff2a 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "private": true, "dependencies": { "@codemirror/lang-javascript": "^6.1.1", + "@headlessui/react": "^1.7.13", "@react-three/drei": "^9.42.0", "@react-three/fiber": "^8.9.1", "@testing-library/jest-dom": "^5.14.1", @@ -19,6 +20,7 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "react-json-view": "^1.21.3", + "react-modal-promise": "^1.0.2", "react-scripts": "5.0.1", "swr": "^2.0.4", "three": "^0.146.0", diff --git a/src/App.tsx b/src/App.tsx index 6e6c6a378..e775e89d2 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -23,6 +23,7 @@ import { PanelHeader } from './components/PanelHeader' import { MemoryPanel } from './components/MemoryPanel' import { useHotKeyListener } from './hooks/useHotKeyListener' import { Stream } from './components/Stream' +import ModalContainer from 'react-modal-promise' const OrrthographicCamera = OrthographicCamera as any @@ -140,6 +141,7 @@ function App() { }, [code]) return (
+
diff --git a/src/Toolbar.tsx b/src/Toolbar.tsx index 3e69de67f..24f08d9c7 100644 --- a/src/Toolbar.tsx +++ b/src/Toolbar.tsx @@ -32,7 +32,7 @@ export const Toolbar = () => { sketchMode: 'selectFace', }) }} - className="border m-1 px-1 rounded" + className="border m-1 px-1 rounded text-xs" > Start Sketch @@ -52,7 +52,7 @@ export const Toolbar = () => { ) updateAst(modifiedAst) }} - className="border m-1 px-1 rounded" + className="border m-1 px-1 rounded text-xs" > SketchOnFace @@ -68,7 +68,7 @@ export const Toolbar = () => { position: guiMode.position, }) }} - className="border m-1 px-1 rounded" + className="border m-1 px-1 rounded text-xs" > Edit Sketch @@ -88,7 +88,7 @@ export const Toolbar = () => { ) updateAst(modifiedAst, pathToExtrudeArg) }} - className="border m-1 px-1 rounded" + className="border m-1 px-1 rounded text-xs" > ExtrudeSketch @@ -106,7 +106,7 @@ export const Toolbar = () => { ) updateAst(modifiedAst, pathToExtrudeArg) }} - className="border m-1 px-1 rounded" + className="border m-1 px-1 rounded text-xs" > ExtrudeSketch (w/o pipe) @@ -116,7 +116,7 @@ export const Toolbar = () => { {guiMode.mode === 'sketch' && ( @@ -130,7 +130,7 @@ export const Toolbar = () => { return ( +
+ + +
+ + + + ) +} diff --git a/src/components/Stream.tsx b/src/components/Stream.tsx index 2f2b014d4..ecb56402d 100644 --- a/src/components/Stream.tsx +++ b/src/components/Stream.tsx @@ -5,6 +5,11 @@ export const Stream = () => { const videoRef = useRef(null) useEffect(() => { + if ( + typeof window === 'undefined' || + typeof RTCPeerConnection === 'undefined' + ) + return const url = 'wss://dev.api.kittycad.io/ws/channel' const [pc, socket] = [new RTCPeerConnection(), new WebSocket(url)] // Connection opened @@ -41,15 +46,15 @@ export const Stream = () => { iceServers: message.ice_servers, }) pc.ontrack = function (event) { - const el = document.createElement( - event.track.kind - ) as HTMLVideoElement - - if (videoRef.current) { - videoRef.current.srcObject = event.streams[0] - videoRef.current.autoplay = true - videoRef.current.controls = true - } + console.log('has element?', videoRef.current) + setTimeout(() => { + console.log('has element in timeout?', videoRef.current) + if (videoRef.current) { + videoRef.current.srcObject = event.streams[0] + videoRef.current.autoplay = true + videoRef.current.controls = true + } + }) } pc.oniceconnectionstatechange = (e) => console.log(pc.iceConnectionState) diff --git a/src/components/Toolbar/Equal.tsx b/src/components/Toolbar/Equal.tsx index aee878380..397dd8698 100644 --- a/src/components/Toolbar/Equal.tsx +++ b/src/components/Toolbar/Equal.tsx @@ -8,7 +8,7 @@ import { import { isSketchVariablesLinked } from '../../lang/std/sketchConstraints' import { TransformInfo, - transformAstForSketchLines, + transformSecondarySketchLinesTagFirst, getTransformInfos, } from '../../lang/std/sketchcombos' @@ -73,7 +73,7 @@ export const Equal = () => { transformInfos && ast && updateAst( - transformAstForSketchLines({ + transformSecondarySketchLinesTagFirst({ ast, selectionRanges, transformInfos, @@ -81,7 +81,7 @@ export const Equal = () => { })?.modifiedAst ) } - className={`border m-1 px-1 rounded ${ + className={`border m-1 px-1 rounded text-xs ${ enableEqual ? 'bg-gray-50 text-gray-800' : 'bg-gray-200 text-gray-400' }`} disabled={!enableEqual} diff --git a/src/components/Toolbar/HorzVert.tsx b/src/components/Toolbar/HorzVert.tsx index 090ee1734..c3ee21942 100644 --- a/src/components/Toolbar/HorzVert.tsx +++ b/src/components/Toolbar/HorzVert.tsx @@ -8,7 +8,7 @@ import { import { TransformInfo, getTransformInfos, - transformAstForHorzVert, + transformAstSketchLines, } from '../../lang/std/sketchcombos' export const HorzVert = ({ @@ -55,15 +55,16 @@ export const HorzVert = ({ transformInfos && ast && updateAst( - transformAstForHorzVert({ + transformAstSketchLines({ ast, selectionRanges, transformInfos, programMemory, + referenceSegName: '', })?.modifiedAst ) } - className={`border m-1 px-1 rounded ${ + className={`border m-1 px-1 rounded text-xs ${ enableHorz ? 'bg-gray-50 text-gray-800' : 'bg-gray-200 text-gray-400' }`} disabled={!enableHorz} diff --git a/src/components/Toolbar/SetHorzDistance.tsx b/src/components/Toolbar/SetHorzDistance.tsx index 627f3cb56..e8c350db0 100644 --- a/src/components/Toolbar/SetHorzDistance.tsx +++ b/src/components/Toolbar/SetHorzDistance.tsx @@ -1,4 +1,5 @@ import { useState, useEffect } from 'react' +import { create } from 'react-modal-promise' import { toolTips, useStore } from '../../useStore' import { Value, VariableDeclarator } from '../../lang/abstractSyntaxTree' import { @@ -8,9 +9,13 @@ import { import { isSketchVariablesLinked } from '../../lang/std/sketchConstraints' import { TransformInfo, - transformAstForSketchLines, + transformSecondarySketchLinesTagFirst, getTransformInfos, } from '../../lang/std/sketchcombos' +import { GetInfoModal } from '../GetInfoModal' +import { createLiteral } from '../../lang/modifyAst' + +const getModalInfo = create(GetInfoModal as any) export const SetHorzDistance = ({ horOrVert, @@ -73,23 +78,41 @@ export const SetHorzDistance = ({ return ( diff --git a/src/lang/modifyAst.test.ts b/src/lang/modifyAst.test.ts index ec3e8660a..58decb29c 100644 --- a/src/lang/modifyAst.test.ts +++ b/src/lang/modifyAst.test.ts @@ -121,16 +121,16 @@ show(part001)`) function giveSketchFnCallTagTestHelper( code: string, searchStr: string -): { tag: string; newCode: string } { +): { tag: string; newCode: string; isTagExisting: boolean } { // giveSketchFnCallTag inputs and outputs an ast, which is very verbose for testing // this wrapper changes the input and output to code // making it more of an integration test, but easier to read the test intention is the goal const ast = abstractSyntaxTree(lexer(code)) const start = code.indexOf(searchStr) const range: [number, number] = [start, start + searchStr.length] - const { modifiedAst, tag } = giveSketchFnCallTag(ast, range) + const { modifiedAst, tag, isTagExisting } = giveSketchFnCallTag(ast, range) const newCode = recast(modifiedAst) - return { tag, newCode } + return { tag, newCode, isTagExisting } } describe('Testing giveSketchFnCallTag', () => { @@ -140,33 +140,36 @@ describe('Testing giveSketchFnCallTag', () => { |> line([0.82, 0.34], %) show(part001)` it('Should add tag to a sketch function call', () => { - const { newCode, tag } = giveSketchFnCallTagTestHelper( + const { newCode, tag, isTagExisting } = giveSketchFnCallTagTestHelper( code, 'line([0, 0.83], %)' ) expect(newCode).toContain("line({ to: [0, 0.83], tag: 'seg01' }, %)") expect(tag).toBe('seg01') + expect(isTagExisting).toBe(false) }) it('Should create a unique tag if seg01 already exists', () => { let _code = code.replace( 'line([-2.57, -0.13], %)', "line({ to: [-2.57, -0.13], tag: 'seg01' }, %)" ) - const { newCode, tag } = giveSketchFnCallTagTestHelper( + const { newCode, tag, isTagExisting } = giveSketchFnCallTagTestHelper( _code, 'line([0, 0.83], %)' ) expect(newCode).toContain("line({ to: [0, 0.83], tag: 'seg02' }, %)") expect(tag).toBe('seg02') + expect(isTagExisting).toBe(false) }) it('Should return existing tag if it already exists', () => { const lineButWithTag = "line({ to: [-2.57, -0.13], tag: 'butts' }, %)" let _code = code.replace('line([-2.57, -0.13], %)', lineButWithTag) - const { newCode, tag } = giveSketchFnCallTagTestHelper( + const { newCode, tag, isTagExisting } = giveSketchFnCallTagTestHelper( _code, lineButWithTag ) expect(newCode).toContain(lineButWithTag) // no change expect(tag).toBe('butts') + expect(isTagExisting).toBe(true) }) }) diff --git a/src/lang/modifyAst.ts b/src/lang/modifyAst.ts index beaf82a5c..b62b50122 100644 --- a/src/lang/modifyAst.ts +++ b/src/lang/modifyAst.ts @@ -481,15 +481,17 @@ export function createBinaryExpression([left, operator, right]: [ export function giveSketchFnCallTag( ast: Program, - range: Range -): { modifiedAst: Program; tag: string } { + range: Range, + tag?: string +): { modifiedAst: Program; tag: string; isTagExisting: boolean } { const { node: primaryCallExp } = getNodeFromPath( ast, getNodePathFromSourceRange(ast, range) ) const firstArg = getFirstArg(primaryCallExp) + const isTagExisting = !!firstArg.tag const tagValue = (firstArg.tag || - createLiteral(findUniqueName(ast, 'seg', 2))) as Literal + createLiteral(tag || findUniqueName(ast, 'seg', 2))) as Literal const tagStr = String(tagValue.value) const newFirstArg = createFirstArg( primaryCallExp.callee.name as TooTip, @@ -500,5 +502,6 @@ export function giveSketchFnCallTag( return { modifiedAst: ast, tag: tagStr, + isTagExisting, } } diff --git a/src/lang/std/sketch.ts b/src/lang/std/sketch.ts index 30354ac44..1f0a796f5 100644 --- a/src/lang/std/sketch.ts +++ b/src/lang/std/sketch.ts @@ -154,15 +154,19 @@ export const lineTo: SketchLineHelper = { createLiteral(roundOff(to[1], 2)), ] - const newLine = createCallback - ? createCallback(newVals, referencedSegment) - : createCallExpression('lineTo', [ - createArrayExpression(newVals), - createPipeSubstitution(), - ]) + const newLine = createCallExpression('lineTo', [ + createArrayExpression(newVals), + createPipeSubstitution(), + ]) const callIndex = getLastIndex(pathToNode) - if (replaceExisting) { - pipe.body[callIndex] = newLine + if (replaceExisting && createCallback) { + const boop = createCallback(newVals, referencedSegment) + pipe.body[callIndex] = boop.callExp + return { + modifiedAst: _node, + pathToNode, + valueUsedInTransform: boop.valueUsedInTransform, + } } else { pipe.body = [...pipe.body, newLine] } @@ -269,7 +273,7 @@ export const line: SketchLineHelper = { const newYVal = createLiteral(roundOff(to[1] - from[1], 2)) const newLine = createCallback - ? createCallback([newXVal, newYVal]) + ? createCallback([newXVal, newYVal]).callExp : createCallExpression('line', [ createArrayExpression([newXVal, newYVal]), createPipeSubstitution(), @@ -336,7 +340,7 @@ export const xLineTo: SketchLineHelper = { const newVal = createLiteral(roundOff(to[0], 2)) const newLine = createCallback - ? createCallback([newVal, newVal]) + ? createCallback([newVal, newVal]).callExp : createCallExpression('xLineTo', [newVal, createPipeSubstitution()]) const callIndex = getLastIndex(pathToNode) @@ -397,7 +401,7 @@ export const yLineTo: SketchLineHelper = { const newVal = createLiteral(roundOff(to[1], 2)) const newLine = createCallback - ? createCallback([newVal, newVal]) + ? createCallback([newVal, newVal]).callExp : createCallExpression('yLineTo', [newVal, createPipeSubstitution()]) const callIndex = getLastIndex(pathToNode) if (replaceExisting) { @@ -454,7 +458,7 @@ export const xLine: SketchLineHelper = { const newVal = createLiteral(roundOff(to[0] - from[0], 2)) const firstArg = newVal const newLine = createCallback - ? createCallback([firstArg, firstArg]) + ? createCallback([firstArg, firstArg]).callExp : createCallExpression('xLine', [firstArg, createPipeSubstitution()]) const callIndex = getLastIndex(pathToNode) if (replaceExisting) { @@ -507,7 +511,7 @@ export const yLine: SketchLineHelper = { const { node: pipe } = getNode('PipeExpression') const newVal = createLiteral(roundOff(to[1] - from[1], 2)) const newLine = createCallback - ? createCallback([newVal, newVal]) + ? createCallback([newVal, newVal]).callExp : createCallExpression('yLine', [newVal, createPipeSubstitution()]) const callIndex = getLastIndex(pathToNode) if (replaceExisting) { @@ -596,7 +600,7 @@ export const angledLine: SketchLineHelper = { const newAngleVal = createLiteral(roundOff(getAngle(from, to), 0)) const newLengthVal = createLiteral(roundOff(getLength(from, to), 2)) const newLine = createCallback - ? createCallback([newAngleVal, newLengthVal]) + ? createCallback([newAngleVal, newLengthVal]).callExp : createCallExpression('angledLine', [ createArrayExpression([newAngleVal, newLengthVal]), createPipeSubstitution(), @@ -686,7 +690,7 @@ export const angledLineOfXLength: SketchLineHelper = { const angle = createLiteral(roundOff(getAngle(from, to), 0)) const xLength = createLiteral(roundOff(Math.abs(from[0] - to[0]), 2) || 0.1) const newLine = createCallback - ? createCallback([angle, xLength]) + ? createCallback([angle, xLength]).callExp : createCallExpression('angledLineOfXLength', [ createArrayExpression([angle, xLength]), createPipeSubstitution(), @@ -780,7 +784,7 @@ export const angledLineOfYLength: SketchLineHelper = { const angle = createLiteral(roundOff(getAngle(from, to), 0)) const yLength = createLiteral(roundOff(Math.abs(from[1] - to[1]), 2) || 0.1) const newLine = createCallback - ? createCallback([angle, yLength]) + ? createCallback([angle, yLength]).callExp : createCallExpression('angledLineOfYLength', [ createArrayExpression([angle, yLength]), createPipeSubstitution(), @@ -864,7 +868,7 @@ 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]) + ? createCallback([angle, xArg]).callExp : createCallExpression('angledLineToX', [ createArrayExpression([angle, xArg]), createPipeSubstitution(), @@ -945,7 +949,7 @@ export const angledLineToY: SketchLineHelper = { const angle = createLiteral(roundOff(getAngle(from, to), 0)) const yArg = createLiteral(roundOff(to[1], 2)) const newLine = createCallback - ? createCallback([angle, yArg]) + ? createCallback([angle, yArg]).callExp : createCallExpression('angledLineToY', [ createArrayExpression([angle, yArg]), createPipeSubstitution(), @@ -1088,13 +1092,13 @@ export function replaceSketchLine({ from: [number, number] createCallback: TransformCallback referencedSegment?: Path -}): { modifiedAst: Program } { +}): { modifiedAst: Program; valueUsedInTransform?: number } { if (!toolTips.includes(fnName)) throw new Error('not a tooltip') const _node = { ...node } const thePath = getNodePathFromSourceRange(_node, sourceRange) const { add } = sketchLineHelperMap[fnName] - const { modifiedAst } = add({ + const { modifiedAst, valueUsedInTransform } = add({ node: _node, previousProgramMemory: programMemory, pathToNode: thePath, @@ -1104,7 +1108,7 @@ export function replaceSketchLine({ replaceExisting: true, createCallback, }) - return { modifiedAst } + return { modifiedAst, valueUsedInTransform } } export function addTagForSketchOnFace( diff --git a/src/lang/std/sketchConstraints.test.ts b/src/lang/std/sketchConstraints.test.ts index 72813ca73..510f97c74 100644 --- a/src/lang/std/sketchConstraints.test.ts +++ b/src/lang/std/sketchConstraints.test.ts @@ -4,7 +4,7 @@ import { lexer } from '../tokeniser' import { ConstraintType, getTransformInfos, - transformAstForHorzVert, + transformAstSketchLines, } from './sketchcombos' import { recast } from '../recast' import { initPromise } from '../rust' @@ -32,11 +32,12 @@ function testingSwapSketchFnCall({ const transformInfos = getTransformInfos([range], ast, constraintType) if (!transformInfos) throw new Error('nope') - const { modifiedAst } = transformAstForHorzVert({ + const { modifiedAst } = transformAstSketchLines({ ast, programMemory, selectionRanges: [range], transformInfos, + referenceSegName: '', }) return { newCode: recast(modifiedAst), diff --git a/src/lang/std/sketchcombos.test.ts b/src/lang/std/sketchcombos.test.ts index d57fffad4..d46217632 100644 --- a/src/lang/std/sketchcombos.test.ts +++ b/src/lang/std/sketchcombos.test.ts @@ -3,8 +3,8 @@ import { lexer } from '../tokeniser' import { getConstraintType, getTransformInfos, - transformAstForSketchLines, - transformAstForHorzVert, + transformAstSketchLines, + transformSecondarySketchLinesTagFirst, ConstraintType, } from './sketchcombos' import { initPromise } from '../rust' @@ -204,7 +204,7 @@ show(part001)` 'equalLength' ) - const newAst = transformAstForSketchLines({ + const newAst = transformSecondarySketchLinesTagFirst({ ast, selectionRanges, transformInfos, @@ -282,11 +282,12 @@ show(part001)` const programMemory = executor(ast) const transformInfos = getTransformInfos(selectionRanges, ast, 'horizontal') - const newAst = transformAstForHorzVert({ + const newAst = transformAstSketchLines({ ast, selectionRanges, transformInfos, programMemory, + referenceSegName: '', })?.modifiedAst const newCode = recast(newAst) expect(newCode).toBe(expectModifiedScript) @@ -331,11 +332,12 @@ show(part001)` const programMemory = executor(ast) const transformInfos = getTransformInfos(selectionRanges, ast, 'vertical') - const newAst = transformAstForHorzVert({ + const newAst = transformAstSketchLines({ ast, selectionRanges, transformInfos, programMemory, + referenceSegName: '', })?.modifiedAst const newCode = recast(newAst) expect(newCode).toBe(expectModifiedScript) @@ -419,7 +421,7 @@ function helperThing( constraint ) - const newAst = transformAstForSketchLines({ + const newAst = transformSecondarySketchLinesTagFirst({ ast, selectionRanges, transformInfos, diff --git a/src/lang/std/sketchcombos.ts b/src/lang/std/sketchcombos.ts index adb5149c6..37cb8f9fb 100644 --- a/src/lang/std/sketchcombos.ts +++ b/src/lang/std/sketchcombos.ts @@ -1,5 +1,5 @@ import { TransformCallback } from './stdTypes' -import { Range, Ranges, toolTips, TooTip } from '../../useStore' +import { Ranges, toolTips, TooTip } from '../../useStore' import { BinaryPart, CallExpression, @@ -21,7 +21,7 @@ import { giveSketchFnCallTag, } from '../modifyAst' import { createFirstArg, getFirstArg, replaceSketchLine } from './sketch' -import { Path, ProgramMemory } from '../executor' +import { ProgramMemory } from '../executor' import { getSketchSegmentIndexFromSourceRange } from './sketchConstraints' import { roundOff } from '../../lib/utils' @@ -44,46 +44,16 @@ export type ConstraintType = function createCallWrapper( a: TooTip, val: [Value, Value] | Value, - tag?: Value -) { - return createCallExpression(a, [ - createFirstArg(a, val, tag), - createPipeSubstitution(), - ]) -} - -export function replaceSketchCall( - programMemory: ProgramMemory, - ast: Program, - range: Range, - transformTo: TooTip, - createCallback: TransformCallback, - referenceSegName: string -): { modifiedAst: Program } { - const path = getNodePathFromSourceRange(ast, range) - const getNode = getNodeFromPathCurry(ast, path) - const varDec = getNode('VariableDeclarator').node - const callExp = getNode('CallExpression').node - const varName = varDec.id.name - const sketchGroup = programMemory.root?.[varName] - if (!sketchGroup || sketchGroup.type !== 'sketchGroup') - throw new Error('not a sketch group') - const seg = getSketchSegmentIndexFromSourceRange(sketchGroup, range) - const referencedSegment = sketchGroup.value.find( - (path) => path.name === referenceSegName - ) - const { to, from } = seg - const { modifiedAst } = replaceSketchLine({ - node: ast, - programMemory, - sourceRange: range, - referencedSegment, - fnName: transformTo || (callExp.callee.name as TooTip), - to, - from, - createCallback, - }) - return { modifiedAst } + tag?: Value, + valueUsedInTransform?: number +): ReturnType { + return { + callExp: createCallExpression(a, [ + createFirstArg(a, val, tag), + createPipeSubstitution(), + ]), + valueUsedInTransform, + } } export type TransformInfo = { @@ -93,7 +63,8 @@ export type TransformInfo = { varValB: Value // y / length or x y for angledLineOfXlength etc referenceSegName: string tag?: Value - }) => (args: [Value, Value], referencedSegment?: Path) => Value + forceValueUsedInTransform?: Value + }) => TransformCallback } type TransformMap = { @@ -172,23 +143,27 @@ const getAngleLengthSign = (arg: Value, legAngleVal: BinaryPart) => { } const setHorzVertDistanceCreateNode = - (isX = true): TransformInfo['createNode'] => - ({ referenceSegName, tag }) => { + ( + xOrY: 'x' | 'y', + index = xOrY === 'x' ? 0 : 1 + ): TransformInfo['createNode'] => + ({ referenceSegName, tag, forceValueUsedInTransform }) => { return (args, referencedSegment) => { - const makeBinExp = (index: 0 | 1) => { - const arg = getArgLiteralVal(args?.[index]) - return createBinaryExpression([ - createSegEnd(referenceSegName, isX), - '+', - createLiteral( - roundOff(arg - (referencedSegment?.to?.[index] || 0), 2) - ), - ]) - } + const valueUsedInTransform = roundOff( + getArgLiteralVal(args?.[index]) - (referencedSegment?.to?.[index] || 0), + 2 + ) + const makeBinExp = createBinaryExpression([ + createSegEnd(referenceSegName, !index), + '+', + (forceValueUsedInTransform as BinaryPart) || + createLiteral(valueUsedInTransform), + ]) return createCallWrapper( 'lineTo', - isX ? [makeBinExp(0), args[1]] : [args[0], makeBinExp(1)], - tag + !index ? [makeBinExp, args[1]] : [args[0], makeBinExp], + tag, + valueUsedInTransform ) } } @@ -301,11 +276,11 @@ const transformMap: TransformMap = { }, setHorzDistance: { tooltip: 'lineTo', - createNode: setHorzVertDistanceCreateNode(true), + createNode: setHorzVertDistanceCreateNode('x'), }, setVertDistance: { tooltip: 'lineTo', - createNode: setHorzVertDistanceCreateNode(false), + createNode: setHorzVertDistanceCreateNode('y'), }, }, }, @@ -826,99 +801,120 @@ export function getTransformInfos( return theTransforms } -export function transformAstForSketchLines({ +export function transformSecondarySketchLinesTagFirst({ ast, selectionRanges, transformInfos, programMemory, + forceSegName, + forceValueUsedInTransform, }: { ast: Program selectionRanges: Ranges transformInfos: TransformInfo[] programMemory: ProgramMemory -}): { modifiedAst: Program } { - // deep clone since we are mutating in a loop, of which any could fail - let node = JSON.parse(JSON.stringify(ast)) + forceSegName?: string + forceValueUsedInTransform?: Value +}): { + modifiedAst: Program + valueUsedInTransform?: number + tagInfo: { + tag: string + isTagExisting: boolean + } +} { + // let node = JSON.parse(JSON.stringify(ast)) const primarySelection = selectionRanges[0] - const { modifiedAst, tag } = giveSketchFnCallTag(node, primarySelection) - node = modifiedAst + const { modifiedAst, tag, isTagExisting } = giveSketchFnCallTag( + ast, + primarySelection, + forceSegName + ) - selectionRanges.slice(1).forEach((range, index) => { + return { + ...transformAstSketchLines({ + ast: modifiedAst, + selectionRanges: selectionRanges.slice(1), + transformInfos, + programMemory, + referenceSegName: tag, + forceValueUsedInTransform, + }), + tagInfo: { + tag, + isTagExisting, + }, + } +} + +export function transformAstSketchLines({ + ast, + selectionRanges, + transformInfos, + programMemory, + referenceSegName, + forceValueUsedInTransform, +}: { + ast: Program + selectionRanges: Ranges + transformInfos: TransformInfo[] + programMemory: ProgramMemory + referenceSegName: string + forceValueUsedInTransform?: Value +}): { modifiedAst: Program; valueUsedInTransform?: number } { + // deep clone since we are mutating in a loop, of which any could fail + let node = JSON.parse(JSON.stringify(ast)) + let _valueUsedInTransform // TODO should this be an array? + + selectionRanges.forEach((range, index) => { const callBack = transformInfos?.[index].createNode const transformTo = transformInfos?.[index].tooltip if (!callBack || !transformTo) throw new Error('no callback helper') - const callExpPath = getNodePathFromSourceRange(node, range) - const callExp = getNodeFromPath( + const getNode = getNodeFromPathCurry( node, - callExpPath, - 'CallExpression' - )?.node - const { val } = getFirstArg(callExp) + getNodePathFromSourceRange(node, range) + ) + + const callExp = getNode('CallExpression')?.node + const varDec = getNode('VariableDeclarator').node + + const { val, tag: callBackTag } = getFirstArg(callExp) const [varValA, varValB] = Array.isArray(val) ? val : [val, val] - const { modifiedAst } = replaceSketchCall( + const varName = varDec.id.name + const sketchGroup = programMemory.root?.[varName] + if (!sketchGroup || sketchGroup.type !== 'sketchGroup') + throw new Error('not a sketch group') + const seg = getSketchSegmentIndexFromSourceRange(sketchGroup, range) + const referencedSegment = sketchGroup.value.find( + (path) => path.name === referenceSegName + ) + const { to, from } = seg + const { modifiedAst, valueUsedInTransform } = replaceSketchLine({ + node: node, programMemory, - node, - range, - transformTo, - callBack({ - referenceSegName: tag, + sourceRange: range, + referencedSegment, + fnName: transformTo || (callExp.callee.name as TooTip), + to, + from, + createCallback: callBack({ + referenceSegName, varValA, varValB, + tag: callBackTag, + forceValueUsedInTransform, }), - tag - ) + }) + node = modifiedAst + if (typeof valueUsedInTransform === 'number') { + _valueUsedInTransform = valueUsedInTransform + } }) - return { modifiedAst: node } -} - -export function transformAstForHorzVert({ - ast, - selectionRanges, - transformInfos, - programMemory, -}: { - ast: Program - selectionRanges: Ranges - transformInfos: TransformInfo[] - programMemory: ProgramMemory -}): { modifiedAst: Program } { - // deep clone since we are mutating in a loop, of which any could fail - let node = JSON.parse(JSON.stringify(ast)) - - selectionRanges.forEach((range, index) => { - const callBack = transformInfos?.[index]?.createNode - const transformTo = transformInfos?.[index].tooltip - if (!callBack || !transformTo) throw new Error('no callback helper') - - const callExpPath = getNodePathFromSourceRange(node, range) - const callExp = getNodeFromPath( - node, - callExpPath, - 'CallExpression' - )?.node - const { val, tag } = getFirstArg(callExp) - const [varValA, varValB] = Array.isArray(val) ? val : [val, val] - - const { modifiedAst } = replaceSketchCall( - programMemory, - node, - range, - transformTo, - callBack({ - referenceSegName: '', - varValA, - varValB, - tag, - }), - tag?.type === 'Literal' ? String(tag.value) : '' - ) - node = modifiedAst - }) - return { modifiedAst: node } + return { modifiedAst: node, valueUsedInTransform: _valueUsedInTransform } } function createSegLen(referenceSegName: string): Value { diff --git a/src/lang/std/stdTypes.ts b/src/lang/std/stdTypes.ts index 98d203740..a2bd72550 100644 --- a/src/lang/std/stdTypes.ts +++ b/src/lang/std/stdTypes.ts @@ -70,7 +70,10 @@ interface updateArgs extends ModifyAstBase { export type TransformCallback = ( args: [Value, Value], referencedSegment?: Path -) => Value +) => { + callExp: Value + valueUsedInTransform?: number +} export type SketchCallTransfromMap = { [key in TooTip]: TransformCallback @@ -81,6 +84,7 @@ export interface SketchLineHelper { add: (a: addCall) => { modifiedAst: Program pathToNode: (string | number)[] + valueUsedInTransform?: number } updateArgs: (a: updateArgs) => { modifiedAst: Program diff --git a/yarn.lock b/yarn.lock index 2f21d5c1c..806d73f4e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1559,6 +1559,13 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" +"@headlessui/react@^1.7.13": + version "1.7.13" + resolved "https://registry.yarnpkg.com/@headlessui/react/-/react-1.7.13.tgz#fd150b394954e9f1d86ed2340cffd1217d6e7628" + integrity sha512-9n+EQKRtD9266xIHXdY5MfiXPDfYwl7zBM7KOx2Ae3Gdgxy8QML1FkCMjq6AsOf0l6N9uvI4HcFtuFlenaldKg== + dependencies: + client-only "^0.0.1" + "@humanwhocodes/config-array@^0.11.6": version "0.11.7" resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.7.tgz#38aec044c6c828f6ed51d5d7ae3d9b9faf6dbb0f" @@ -3752,6 +3759,11 @@ clean-css@^5.2.2: dependencies: source-map "~0.6.0" +client-only@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1" + integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA== + cliui@^7.0.2: version "7.0.4" resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" @@ -8708,6 +8720,11 @@ react-merge-refs@^1.1.0: resolved "https://registry.yarnpkg.com/react-merge-refs/-/react-merge-refs-1.1.0.tgz#73d88b892c6c68cbb7a66e0800faa374f4c38b06" integrity sha512-alTKsjEL0dKH/ru1Iyn7vliS2QRcBp9zZPGoWxUOvRGWPUYgjo+V01is7p04It6KhgrzhJGnIj9GgX8W4bZoCQ== +react-modal-promise@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/react-modal-promise/-/react-modal-promise-1.0.2.tgz#122620b7f19eec73683affadfa77c543d88edc40" + integrity sha512-dqT618ROhG8qh1+O6EZkia5ELw3zaZWGpMX2YfEH4bgwYENPuFonqKw1W70LFx3K/SCZvVBcD6UYEI12yzYXzg== + react-reconciler@^0.27.0: version "0.27.0" resolved "https://registry.yarnpkg.com/react-reconciler/-/react-reconciler-0.27.0.tgz#360124fdf2d76447c7491ee5f0e04503ed9acf5b"