Horz/Vert distance constraint with modal workflow (#43)
* button style tweak * Remove duplication constraint ast transforms * giveSketchFnCallTag to return if line already had a tag * remove duplication * update tag name to referenceSegName * Update transform shape to return key details about the transform * add modal to hor vert distance workflow * fix browser env stuff from breaking tests * fmt
This commit is contained in:
@ -4,6 +4,7 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/lang-javascript": "^6.1.1",
|
"@codemirror/lang-javascript": "^6.1.1",
|
||||||
|
"@headlessui/react": "^1.7.13",
|
||||||
"@react-three/drei": "^9.42.0",
|
"@react-three/drei": "^9.42.0",
|
||||||
"@react-three/fiber": "^8.9.1",
|
"@react-three/fiber": "^8.9.1",
|
||||||
"@testing-library/jest-dom": "^5.14.1",
|
"@testing-library/jest-dom": "^5.14.1",
|
||||||
@ -19,6 +20,7 @@
|
|||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-json-view": "^1.21.3",
|
"react-json-view": "^1.21.3",
|
||||||
|
"react-modal-promise": "^1.0.2",
|
||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
"swr": "^2.0.4",
|
"swr": "^2.0.4",
|
||||||
"three": "^0.146.0",
|
"three": "^0.146.0",
|
||||||
|
@ -23,6 +23,7 @@ import { PanelHeader } from './components/PanelHeader'
|
|||||||
import { MemoryPanel } from './components/MemoryPanel'
|
import { MemoryPanel } from './components/MemoryPanel'
|
||||||
import { useHotKeyListener } from './hooks/useHotKeyListener'
|
import { useHotKeyListener } from './hooks/useHotKeyListener'
|
||||||
import { Stream } from './components/Stream'
|
import { Stream } from './components/Stream'
|
||||||
|
import ModalContainer from 'react-modal-promise'
|
||||||
|
|
||||||
const OrrthographicCamera = OrthographicCamera as any
|
const OrrthographicCamera = OrthographicCamera as any
|
||||||
|
|
||||||
@ -140,6 +141,7 @@ function App() {
|
|||||||
}, [code])
|
}, [code])
|
||||||
return (
|
return (
|
||||||
<div className="h-screen">
|
<div className="h-screen">
|
||||||
|
<ModalContainer />
|
||||||
<Allotment snap={true}>
|
<Allotment snap={true}>
|
||||||
<Allotment vertical defaultSizes={[4, 1, 1]} minSize={20}>
|
<Allotment vertical defaultSizes={[4, 1, 1]} minSize={20}>
|
||||||
<div className="h-full flex flex-col items-start">
|
<div className="h-full flex flex-col items-start">
|
||||||
|
@ -32,7 +32,7 @@ export const Toolbar = () => {
|
|||||||
sketchMode: 'selectFace',
|
sketchMode: 'selectFace',
|
||||||
})
|
})
|
||||||
}}
|
}}
|
||||||
className="border m-1 px-1 rounded"
|
className="border m-1 px-1 rounded text-xs"
|
||||||
>
|
>
|
||||||
Start Sketch
|
Start Sketch
|
||||||
</button>
|
</button>
|
||||||
@ -52,7 +52,7 @@ export const Toolbar = () => {
|
|||||||
)
|
)
|
||||||
updateAst(modifiedAst)
|
updateAst(modifiedAst)
|
||||||
}}
|
}}
|
||||||
className="border m-1 px-1 rounded"
|
className="border m-1 px-1 rounded text-xs"
|
||||||
>
|
>
|
||||||
SketchOnFace
|
SketchOnFace
|
||||||
</button>
|
</button>
|
||||||
@ -68,7 +68,7 @@ export const Toolbar = () => {
|
|||||||
position: guiMode.position,
|
position: guiMode.position,
|
||||||
})
|
})
|
||||||
}}
|
}}
|
||||||
className="border m-1 px-1 rounded"
|
className="border m-1 px-1 rounded text-xs"
|
||||||
>
|
>
|
||||||
Edit Sketch
|
Edit Sketch
|
||||||
</button>
|
</button>
|
||||||
@ -88,7 +88,7 @@ export const Toolbar = () => {
|
|||||||
)
|
)
|
||||||
updateAst(modifiedAst, pathToExtrudeArg)
|
updateAst(modifiedAst, pathToExtrudeArg)
|
||||||
}}
|
}}
|
||||||
className="border m-1 px-1 rounded"
|
className="border m-1 px-1 rounded text-xs"
|
||||||
>
|
>
|
||||||
ExtrudeSketch
|
ExtrudeSketch
|
||||||
</button>
|
</button>
|
||||||
@ -106,7 +106,7 @@ export const Toolbar = () => {
|
|||||||
)
|
)
|
||||||
updateAst(modifiedAst, pathToExtrudeArg)
|
updateAst(modifiedAst, pathToExtrudeArg)
|
||||||
}}
|
}}
|
||||||
className="border m-1 px-1 rounded"
|
className="border m-1 px-1 rounded text-xs"
|
||||||
>
|
>
|
||||||
ExtrudeSketch (w/o pipe)
|
ExtrudeSketch (w/o pipe)
|
||||||
</button>
|
</button>
|
||||||
@ -116,7 +116,7 @@ export const Toolbar = () => {
|
|||||||
{guiMode.mode === 'sketch' && (
|
{guiMode.mode === 'sketch' && (
|
||||||
<button
|
<button
|
||||||
onClick={() => setGuiMode({ mode: 'default' })}
|
onClick={() => setGuiMode({ mode: 'default' })}
|
||||||
className="border m-1 px-1 rounded"
|
className="border m-1 px-1 rounded text-xs"
|
||||||
>
|
>
|
||||||
Exit sketch
|
Exit sketch
|
||||||
</button>
|
</button>
|
||||||
@ -130,7 +130,7 @@ export const Toolbar = () => {
|
|||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
key={sketchFnName}
|
key={sketchFnName}
|
||||||
className={`border m-1 px-1 rounded ${
|
className={`border m-0.5 px-0.5 rounded text-xs ${
|
||||||
guiMode.sketchMode === sketchFnName && 'bg-gray-400'
|
guiMode.sketchMode === sketchFnName && 'bg-gray-400'
|
||||||
}`}
|
}`}
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
|
110
src/components/GetInfoModal.tsx
Normal file
110
src/components/GetInfoModal.tsx
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
import { Dialog, Transition } from '@headlessui/react'
|
||||||
|
import { Fragment, useState } from 'react'
|
||||||
|
|
||||||
|
export const GetInfoModal = ({
|
||||||
|
isOpen,
|
||||||
|
onResolve,
|
||||||
|
onReject,
|
||||||
|
// fields: initialFields,
|
||||||
|
segName: initialSegName,
|
||||||
|
isSegNameEditable,
|
||||||
|
value: initialValue,
|
||||||
|
}: {
|
||||||
|
isOpen: boolean
|
||||||
|
onResolve: (a: any) => void
|
||||||
|
onReject: (a: any) => void
|
||||||
|
segName: string
|
||||||
|
isSegNameEditable: boolean
|
||||||
|
value: number
|
||||||
|
}) => {
|
||||||
|
const [segName, setSegName] = useState(initialSegName)
|
||||||
|
const [value, setValue] = useState(initialValue)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Transition appear show={isOpen} as={Fragment}>
|
||||||
|
<Dialog as="div" className="relative z-10" onClose={onResolve}>
|
||||||
|
<Transition.Child
|
||||||
|
as={Fragment}
|
||||||
|
enter="ease-out duration-300"
|
||||||
|
enterFrom="opacity-0"
|
||||||
|
enterTo="opacity-100"
|
||||||
|
leave="ease-in duration-200"
|
||||||
|
leaveFrom="opacity-100"
|
||||||
|
leaveTo="opacity-0"
|
||||||
|
>
|
||||||
|
<div className="fixed inset-0 bg-black bg-opacity-25" />
|
||||||
|
</Transition.Child>
|
||||||
|
|
||||||
|
<div className="fixed inset-0 overflow-y-auto">
|
||||||
|
<div className="flex min-h-full items-center justify-center p-4 text-center">
|
||||||
|
<Transition.Child
|
||||||
|
as={Fragment}
|
||||||
|
enter="ease-out duration-300"
|
||||||
|
enterFrom="opacity-0 scale-95"
|
||||||
|
enterTo="opacity-100 scale-100"
|
||||||
|
leave="ease-in duration-200"
|
||||||
|
leaveFrom="opacity-100 scale-100"
|
||||||
|
leaveTo="opacity-0 scale-95"
|
||||||
|
>
|
||||||
|
<Dialog.Panel className="w-full max-w-md transform overflow-hidden rounded-2xl bg-white p-6 text-left align-middle shadow-xl transition-all">
|
||||||
|
<Dialog.Title
|
||||||
|
as="h3"
|
||||||
|
className="text-lg font-medium leading-6 text-gray-900"
|
||||||
|
>
|
||||||
|
Constraint details
|
||||||
|
</Dialog.Title>
|
||||||
|
<label
|
||||||
|
htmlFor="val"
|
||||||
|
className="block text-sm font-medium text-gray-700 mt-3 font-mono"
|
||||||
|
>
|
||||||
|
Distance
|
||||||
|
</label>
|
||||||
|
<div className="mt-1">
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
name="val"
|
||||||
|
id="val"
|
||||||
|
className="shadow-sm focus:ring-blue-500 focus:border-blue-500 block w-full sm:text-sm border-gray-300 rounded-md font-mono"
|
||||||
|
value={value}
|
||||||
|
onChange={(e) => {
|
||||||
|
setValue(Number(e.target.value))
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<label
|
||||||
|
htmlFor="segName"
|
||||||
|
className="block text-sm font-medium text-gray-700 mt-3 font-mono"
|
||||||
|
>
|
||||||
|
Segment Name
|
||||||
|
</label>
|
||||||
|
<div className="mt-1">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
name="segName"
|
||||||
|
id="segName"
|
||||||
|
disabled={!isSegNameEditable}
|
||||||
|
className="shadow-sm focus:ring-blue-500 focus:border-blue-500 block w-full sm:text-sm border-gray-300 rounded-md font-mono"
|
||||||
|
value={segName}
|
||||||
|
onChange={(e) => {
|
||||||
|
setSegName(e.target.value)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mt-4">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="inline-flex justify-center rounded-md border border-transparent bg-blue-100 px-4 py-2 text-sm font-medium text-blue-900 hover:bg-blue-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2"
|
||||||
|
onClick={() => onResolve({ segName, value })}
|
||||||
|
>
|
||||||
|
Add constraining value
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</Dialog.Panel>
|
||||||
|
</Transition.Child>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Dialog>
|
||||||
|
</Transition>
|
||||||
|
)
|
||||||
|
}
|
@ -5,6 +5,11 @@ export const Stream = () => {
|
|||||||
const videoRef = useRef<HTMLVideoElement>(null)
|
const videoRef = useRef<HTMLVideoElement>(null)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (
|
||||||
|
typeof window === 'undefined' ||
|
||||||
|
typeof RTCPeerConnection === 'undefined'
|
||||||
|
)
|
||||||
|
return
|
||||||
const url = 'wss://dev.api.kittycad.io/ws/channel'
|
const url = 'wss://dev.api.kittycad.io/ws/channel'
|
||||||
const [pc, socket] = [new RTCPeerConnection(), new WebSocket(url)]
|
const [pc, socket] = [new RTCPeerConnection(), new WebSocket(url)]
|
||||||
// Connection opened
|
// Connection opened
|
||||||
@ -41,15 +46,15 @@ export const Stream = () => {
|
|||||||
iceServers: message.ice_servers,
|
iceServers: message.ice_servers,
|
||||||
})
|
})
|
||||||
pc.ontrack = function (event) {
|
pc.ontrack = function (event) {
|
||||||
const el = document.createElement(
|
console.log('has element?', videoRef.current)
|
||||||
event.track.kind
|
setTimeout(() => {
|
||||||
) as HTMLVideoElement
|
console.log('has element in timeout?', videoRef.current)
|
||||||
|
|
||||||
if (videoRef.current) {
|
if (videoRef.current) {
|
||||||
videoRef.current.srcObject = event.streams[0]
|
videoRef.current.srcObject = event.streams[0]
|
||||||
videoRef.current.autoplay = true
|
videoRef.current.autoplay = true
|
||||||
videoRef.current.controls = true
|
videoRef.current.controls = true
|
||||||
}
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
pc.oniceconnectionstatechange = (e) =>
|
pc.oniceconnectionstatechange = (e) =>
|
||||||
console.log(pc.iceConnectionState)
|
console.log(pc.iceConnectionState)
|
||||||
|
@ -8,7 +8,7 @@ import {
|
|||||||
import { isSketchVariablesLinked } from '../../lang/std/sketchConstraints'
|
import { isSketchVariablesLinked } from '../../lang/std/sketchConstraints'
|
||||||
import {
|
import {
|
||||||
TransformInfo,
|
TransformInfo,
|
||||||
transformAstForSketchLines,
|
transformSecondarySketchLinesTagFirst,
|
||||||
getTransformInfos,
|
getTransformInfos,
|
||||||
} from '../../lang/std/sketchcombos'
|
} from '../../lang/std/sketchcombos'
|
||||||
|
|
||||||
@ -73,7 +73,7 @@ export const Equal = () => {
|
|||||||
transformInfos &&
|
transformInfos &&
|
||||||
ast &&
|
ast &&
|
||||||
updateAst(
|
updateAst(
|
||||||
transformAstForSketchLines({
|
transformSecondarySketchLinesTagFirst({
|
||||||
ast,
|
ast,
|
||||||
selectionRanges,
|
selectionRanges,
|
||||||
transformInfos,
|
transformInfos,
|
||||||
@ -81,7 +81,7 @@ export const Equal = () => {
|
|||||||
})?.modifiedAst
|
})?.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'
|
enableEqual ? 'bg-gray-50 text-gray-800' : 'bg-gray-200 text-gray-400'
|
||||||
}`}
|
}`}
|
||||||
disabled={!enableEqual}
|
disabled={!enableEqual}
|
||||||
|
@ -8,7 +8,7 @@ import {
|
|||||||
import {
|
import {
|
||||||
TransformInfo,
|
TransformInfo,
|
||||||
getTransformInfos,
|
getTransformInfos,
|
||||||
transformAstForHorzVert,
|
transformAstSketchLines,
|
||||||
} from '../../lang/std/sketchcombos'
|
} from '../../lang/std/sketchcombos'
|
||||||
|
|
||||||
export const HorzVert = ({
|
export const HorzVert = ({
|
||||||
@ -55,15 +55,16 @@ export const HorzVert = ({
|
|||||||
transformInfos &&
|
transformInfos &&
|
||||||
ast &&
|
ast &&
|
||||||
updateAst(
|
updateAst(
|
||||||
transformAstForHorzVert({
|
transformAstSketchLines({
|
||||||
ast,
|
ast,
|
||||||
selectionRanges,
|
selectionRanges,
|
||||||
transformInfos,
|
transformInfos,
|
||||||
programMemory,
|
programMemory,
|
||||||
|
referenceSegName: '',
|
||||||
})?.modifiedAst
|
})?.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'
|
enableHorz ? 'bg-gray-50 text-gray-800' : 'bg-gray-200 text-gray-400'
|
||||||
}`}
|
}`}
|
||||||
disabled={!enableHorz}
|
disabled={!enableHorz}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { useState, useEffect } from 'react'
|
import { useState, useEffect } from 'react'
|
||||||
|
import { create } from 'react-modal-promise'
|
||||||
import { toolTips, useStore } from '../../useStore'
|
import { toolTips, useStore } from '../../useStore'
|
||||||
import { Value, VariableDeclarator } from '../../lang/abstractSyntaxTree'
|
import { Value, VariableDeclarator } from '../../lang/abstractSyntaxTree'
|
||||||
import {
|
import {
|
||||||
@ -8,9 +9,13 @@ import {
|
|||||||
import { isSketchVariablesLinked } from '../../lang/std/sketchConstraints'
|
import { isSketchVariablesLinked } from '../../lang/std/sketchConstraints'
|
||||||
import {
|
import {
|
||||||
TransformInfo,
|
TransformInfo,
|
||||||
transformAstForSketchLines,
|
transformSecondarySketchLinesTagFirst,
|
||||||
getTransformInfos,
|
getTransformInfos,
|
||||||
} from '../../lang/std/sketchcombos'
|
} from '../../lang/std/sketchcombos'
|
||||||
|
import { GetInfoModal } from '../GetInfoModal'
|
||||||
|
import { createLiteral } from '../../lang/modifyAst'
|
||||||
|
|
||||||
|
const getModalInfo = create(GetInfoModal as any)
|
||||||
|
|
||||||
export const SetHorzDistance = ({
|
export const SetHorzDistance = ({
|
||||||
horOrVert,
|
horOrVert,
|
||||||
@ -73,23 +78,41 @@ export const SetHorzDistance = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
onClick={() =>
|
onClick={async () => {
|
||||||
transformInfos &&
|
if (transformInfos && ast) {
|
||||||
ast &&
|
const { modifiedAst, tagInfo, valueUsedInTransform } =
|
||||||
updateAst(
|
transformSecondarySketchLinesTagFirst({
|
||||||
transformAstForSketchLines({
|
ast: JSON.parse(JSON.stringify(ast)),
|
||||||
|
selectionRanges,
|
||||||
|
transformInfos,
|
||||||
|
programMemory,
|
||||||
|
})
|
||||||
|
const { segName, value }: { segName: string; value: number } =
|
||||||
|
await getModalInfo({
|
||||||
|
segName: tagInfo?.tag,
|
||||||
|
isSegNameEditable: !tagInfo?.isTagExisting,
|
||||||
|
value: valueUsedInTransform,
|
||||||
|
} as any)
|
||||||
|
if (segName === tagInfo?.tag && value === valueUsedInTransform) {
|
||||||
|
updateAst(modifiedAst)
|
||||||
|
} else {
|
||||||
|
// transform again but forcing certain values
|
||||||
|
const { modifiedAst } = transformSecondarySketchLinesTagFirst({
|
||||||
ast,
|
ast,
|
||||||
selectionRanges,
|
selectionRanges,
|
||||||
transformInfos,
|
transformInfos,
|
||||||
programMemory,
|
programMemory,
|
||||||
})?.modifiedAst
|
forceSegName: segName,
|
||||||
)
|
forceValueUsedInTransform: createLiteral(value),
|
||||||
|
})
|
||||||
|
updateAst(modifiedAst)
|
||||||
}
|
}
|
||||||
className={`border m-1 px-1 rounded ${
|
}
|
||||||
|
}}
|
||||||
|
className={`border m-1 px-1 rounded text-xs ${
|
||||||
enable ? 'bg-gray-50 text-gray-800' : 'bg-gray-200 text-gray-400'
|
enable ? 'bg-gray-50 text-gray-800' : 'bg-gray-200 text-gray-400'
|
||||||
}`}
|
}`}
|
||||||
disabled={!enable}
|
disabled={!enable}
|
||||||
title="yo dawg"
|
|
||||||
>
|
>
|
||||||
{horOrVert}
|
{horOrVert}
|
||||||
</button>
|
</button>
|
||||||
|
@ -121,16 +121,16 @@ show(part001)`)
|
|||||||
function giveSketchFnCallTagTestHelper(
|
function giveSketchFnCallTagTestHelper(
|
||||||
code: string,
|
code: string,
|
||||||
searchStr: 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
|
// giveSketchFnCallTag inputs and outputs an ast, which is very verbose for testing
|
||||||
// this wrapper changes the input and output to code
|
// 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
|
// making it more of an integration test, but easier to read the test intention is the goal
|
||||||
const ast = abstractSyntaxTree(lexer(code))
|
const ast = abstractSyntaxTree(lexer(code))
|
||||||
const start = code.indexOf(searchStr)
|
const start = code.indexOf(searchStr)
|
||||||
const range: [number, number] = [start, start + searchStr.length]
|
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)
|
const newCode = recast(modifiedAst)
|
||||||
return { tag, newCode }
|
return { tag, newCode, isTagExisting }
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('Testing giveSketchFnCallTag', () => {
|
describe('Testing giveSketchFnCallTag', () => {
|
||||||
@ -140,33 +140,36 @@ describe('Testing giveSketchFnCallTag', () => {
|
|||||||
|> line([0.82, 0.34], %)
|
|> line([0.82, 0.34], %)
|
||||||
show(part001)`
|
show(part001)`
|
||||||
it('Should add tag to a sketch function call', () => {
|
it('Should add tag to a sketch function call', () => {
|
||||||
const { newCode, tag } = giveSketchFnCallTagTestHelper(
|
const { newCode, tag, isTagExisting } = giveSketchFnCallTagTestHelper(
|
||||||
code,
|
code,
|
||||||
'line([0, 0.83], %)'
|
'line([0, 0.83], %)'
|
||||||
)
|
)
|
||||||
expect(newCode).toContain("line({ to: [0, 0.83], tag: 'seg01' }, %)")
|
expect(newCode).toContain("line({ to: [0, 0.83], tag: 'seg01' }, %)")
|
||||||
expect(tag).toBe('seg01')
|
expect(tag).toBe('seg01')
|
||||||
|
expect(isTagExisting).toBe(false)
|
||||||
})
|
})
|
||||||
it('Should create a unique tag if seg01 already exists', () => {
|
it('Should create a unique tag if seg01 already exists', () => {
|
||||||
let _code = code.replace(
|
let _code = code.replace(
|
||||||
'line([-2.57, -0.13], %)',
|
'line([-2.57, -0.13], %)',
|
||||||
"line({ to: [-2.57, -0.13], tag: 'seg01' }, %)"
|
"line({ to: [-2.57, -0.13], tag: 'seg01' }, %)"
|
||||||
)
|
)
|
||||||
const { newCode, tag } = giveSketchFnCallTagTestHelper(
|
const { newCode, tag, isTagExisting } = giveSketchFnCallTagTestHelper(
|
||||||
_code,
|
_code,
|
||||||
'line([0, 0.83], %)'
|
'line([0, 0.83], %)'
|
||||||
)
|
)
|
||||||
expect(newCode).toContain("line({ to: [0, 0.83], tag: 'seg02' }, %)")
|
expect(newCode).toContain("line({ to: [0, 0.83], tag: 'seg02' }, %)")
|
||||||
expect(tag).toBe('seg02')
|
expect(tag).toBe('seg02')
|
||||||
|
expect(isTagExisting).toBe(false)
|
||||||
})
|
})
|
||||||
it('Should return existing tag if it already exists', () => {
|
it('Should return existing tag if it already exists', () => {
|
||||||
const lineButWithTag = "line({ to: [-2.57, -0.13], tag: 'butts' }, %)"
|
const lineButWithTag = "line({ to: [-2.57, -0.13], tag: 'butts' }, %)"
|
||||||
let _code = code.replace('line([-2.57, -0.13], %)', lineButWithTag)
|
let _code = code.replace('line([-2.57, -0.13], %)', lineButWithTag)
|
||||||
const { newCode, tag } = giveSketchFnCallTagTestHelper(
|
const { newCode, tag, isTagExisting } = giveSketchFnCallTagTestHelper(
|
||||||
_code,
|
_code,
|
||||||
lineButWithTag
|
lineButWithTag
|
||||||
)
|
)
|
||||||
expect(newCode).toContain(lineButWithTag) // no change
|
expect(newCode).toContain(lineButWithTag) // no change
|
||||||
expect(tag).toBe('butts')
|
expect(tag).toBe('butts')
|
||||||
|
expect(isTagExisting).toBe(true)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -481,15 +481,17 @@ export function createBinaryExpression([left, operator, right]: [
|
|||||||
|
|
||||||
export function giveSketchFnCallTag(
|
export function giveSketchFnCallTag(
|
||||||
ast: Program,
|
ast: Program,
|
||||||
range: Range
|
range: Range,
|
||||||
): { modifiedAst: Program; tag: string } {
|
tag?: string
|
||||||
|
): { modifiedAst: Program; tag: string; isTagExisting: boolean } {
|
||||||
const { node: primaryCallExp } = getNodeFromPath<CallExpression>(
|
const { node: primaryCallExp } = getNodeFromPath<CallExpression>(
|
||||||
ast,
|
ast,
|
||||||
getNodePathFromSourceRange(ast, range)
|
getNodePathFromSourceRange(ast, range)
|
||||||
)
|
)
|
||||||
const firstArg = getFirstArg(primaryCallExp)
|
const firstArg = getFirstArg(primaryCallExp)
|
||||||
|
const isTagExisting = !!firstArg.tag
|
||||||
const tagValue = (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 tagStr = String(tagValue.value)
|
||||||
const newFirstArg = createFirstArg(
|
const newFirstArg = createFirstArg(
|
||||||
primaryCallExp.callee.name as TooTip,
|
primaryCallExp.callee.name as TooTip,
|
||||||
@ -500,5 +502,6 @@ export function giveSketchFnCallTag(
|
|||||||
return {
|
return {
|
||||||
modifiedAst: ast,
|
modifiedAst: ast,
|
||||||
tag: tagStr,
|
tag: tagStr,
|
||||||
|
isTagExisting,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -154,15 +154,19 @@ export const lineTo: SketchLineHelper = {
|
|||||||
createLiteral(roundOff(to[1], 2)),
|
createLiteral(roundOff(to[1], 2)),
|
||||||
]
|
]
|
||||||
|
|
||||||
const newLine = createCallback
|
const newLine = createCallExpression('lineTo', [
|
||||||
? createCallback(newVals, referencedSegment)
|
|
||||||
: createCallExpression('lineTo', [
|
|
||||||
createArrayExpression(newVals),
|
createArrayExpression(newVals),
|
||||||
createPipeSubstitution(),
|
createPipeSubstitution(),
|
||||||
])
|
])
|
||||||
const callIndex = getLastIndex(pathToNode)
|
const callIndex = getLastIndex(pathToNode)
|
||||||
if (replaceExisting) {
|
if (replaceExisting && createCallback) {
|
||||||
pipe.body[callIndex] = newLine
|
const boop = createCallback(newVals, referencedSegment)
|
||||||
|
pipe.body[callIndex] = boop.callExp
|
||||||
|
return {
|
||||||
|
modifiedAst: _node,
|
||||||
|
pathToNode,
|
||||||
|
valueUsedInTransform: boop.valueUsedInTransform,
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
pipe.body = [...pipe.body, newLine]
|
pipe.body = [...pipe.body, newLine]
|
||||||
}
|
}
|
||||||
@ -269,7 +273,7 @@ export const line: SketchLineHelper = {
|
|||||||
const newYVal = createLiteral(roundOff(to[1] - from[1], 2))
|
const newYVal = createLiteral(roundOff(to[1] - from[1], 2))
|
||||||
|
|
||||||
const newLine = createCallback
|
const newLine = createCallback
|
||||||
? createCallback([newXVal, newYVal])
|
? createCallback([newXVal, newYVal]).callExp
|
||||||
: createCallExpression('line', [
|
: createCallExpression('line', [
|
||||||
createArrayExpression([newXVal, newYVal]),
|
createArrayExpression([newXVal, newYVal]),
|
||||||
createPipeSubstitution(),
|
createPipeSubstitution(),
|
||||||
@ -336,7 +340,7 @@ export const xLineTo: SketchLineHelper = {
|
|||||||
|
|
||||||
const newVal = createLiteral(roundOff(to[0], 2))
|
const newVal = createLiteral(roundOff(to[0], 2))
|
||||||
const newLine = createCallback
|
const newLine = createCallback
|
||||||
? createCallback([newVal, newVal])
|
? createCallback([newVal, newVal]).callExp
|
||||||
: createCallExpression('xLineTo', [newVal, createPipeSubstitution()])
|
: createCallExpression('xLineTo', [newVal, createPipeSubstitution()])
|
||||||
|
|
||||||
const callIndex = getLastIndex(pathToNode)
|
const callIndex = getLastIndex(pathToNode)
|
||||||
@ -397,7 +401,7 @@ export const yLineTo: SketchLineHelper = {
|
|||||||
|
|
||||||
const newVal = createLiteral(roundOff(to[1], 2))
|
const newVal = createLiteral(roundOff(to[1], 2))
|
||||||
const newLine = createCallback
|
const newLine = createCallback
|
||||||
? createCallback([newVal, newVal])
|
? createCallback([newVal, newVal]).callExp
|
||||||
: createCallExpression('yLineTo', [newVal, createPipeSubstitution()])
|
: createCallExpression('yLineTo', [newVal, createPipeSubstitution()])
|
||||||
const callIndex = getLastIndex(pathToNode)
|
const callIndex = getLastIndex(pathToNode)
|
||||||
if (replaceExisting) {
|
if (replaceExisting) {
|
||||||
@ -454,7 +458,7 @@ export const xLine: SketchLineHelper = {
|
|||||||
const newVal = createLiteral(roundOff(to[0] - from[0], 2))
|
const newVal = createLiteral(roundOff(to[0] - from[0], 2))
|
||||||
const firstArg = newVal
|
const firstArg = newVal
|
||||||
const newLine = createCallback
|
const newLine = createCallback
|
||||||
? createCallback([firstArg, firstArg])
|
? createCallback([firstArg, firstArg]).callExp
|
||||||
: createCallExpression('xLine', [firstArg, createPipeSubstitution()])
|
: createCallExpression('xLine', [firstArg, createPipeSubstitution()])
|
||||||
const callIndex = getLastIndex(pathToNode)
|
const callIndex = getLastIndex(pathToNode)
|
||||||
if (replaceExisting) {
|
if (replaceExisting) {
|
||||||
@ -507,7 +511,7 @@ export const yLine: SketchLineHelper = {
|
|||||||
const { node: pipe } = getNode<PipeExpression>('PipeExpression')
|
const { node: pipe } = getNode<PipeExpression>('PipeExpression')
|
||||||
const newVal = createLiteral(roundOff(to[1] - from[1], 2))
|
const newVal = createLiteral(roundOff(to[1] - from[1], 2))
|
||||||
const newLine = createCallback
|
const newLine = createCallback
|
||||||
? createCallback([newVal, newVal])
|
? createCallback([newVal, newVal]).callExp
|
||||||
: createCallExpression('yLine', [newVal, createPipeSubstitution()])
|
: createCallExpression('yLine', [newVal, createPipeSubstitution()])
|
||||||
const callIndex = getLastIndex(pathToNode)
|
const callIndex = getLastIndex(pathToNode)
|
||||||
if (replaceExisting) {
|
if (replaceExisting) {
|
||||||
@ -596,7 +600,7 @@ export const angledLine: SketchLineHelper = {
|
|||||||
const newAngleVal = createLiteral(roundOff(getAngle(from, to), 0))
|
const newAngleVal = createLiteral(roundOff(getAngle(from, to), 0))
|
||||||
const newLengthVal = createLiteral(roundOff(getLength(from, to), 2))
|
const newLengthVal = createLiteral(roundOff(getLength(from, to), 2))
|
||||||
const newLine = createCallback
|
const newLine = createCallback
|
||||||
? createCallback([newAngleVal, newLengthVal])
|
? createCallback([newAngleVal, newLengthVal]).callExp
|
||||||
: createCallExpression('angledLine', [
|
: createCallExpression('angledLine', [
|
||||||
createArrayExpression([newAngleVal, newLengthVal]),
|
createArrayExpression([newAngleVal, newLengthVal]),
|
||||||
createPipeSubstitution(),
|
createPipeSubstitution(),
|
||||||
@ -686,7 +690,7 @@ export const angledLineOfXLength: SketchLineHelper = {
|
|||||||
const angle = createLiteral(roundOff(getAngle(from, to), 0))
|
const angle = createLiteral(roundOff(getAngle(from, to), 0))
|
||||||
const xLength = createLiteral(roundOff(Math.abs(from[0] - to[0]), 2) || 0.1)
|
const xLength = createLiteral(roundOff(Math.abs(from[0] - to[0]), 2) || 0.1)
|
||||||
const newLine = createCallback
|
const newLine = createCallback
|
||||||
? createCallback([angle, xLength])
|
? createCallback([angle, xLength]).callExp
|
||||||
: createCallExpression('angledLineOfXLength', [
|
: createCallExpression('angledLineOfXLength', [
|
||||||
createArrayExpression([angle, xLength]),
|
createArrayExpression([angle, xLength]),
|
||||||
createPipeSubstitution(),
|
createPipeSubstitution(),
|
||||||
@ -780,7 +784,7 @@ export const angledLineOfYLength: SketchLineHelper = {
|
|||||||
const angle = createLiteral(roundOff(getAngle(from, to), 0))
|
const angle = createLiteral(roundOff(getAngle(from, to), 0))
|
||||||
const yLength = createLiteral(roundOff(Math.abs(from[1] - to[1]), 2) || 0.1)
|
const yLength = createLiteral(roundOff(Math.abs(from[1] - to[1]), 2) || 0.1)
|
||||||
const newLine = createCallback
|
const newLine = createCallback
|
||||||
? createCallback([angle, yLength])
|
? createCallback([angle, yLength]).callExp
|
||||||
: createCallExpression('angledLineOfYLength', [
|
: createCallExpression('angledLineOfYLength', [
|
||||||
createArrayExpression([angle, yLength]),
|
createArrayExpression([angle, yLength]),
|
||||||
createPipeSubstitution(),
|
createPipeSubstitution(),
|
||||||
@ -864,7 +868,7 @@ export const angledLineToX: SketchLineHelper = {
|
|||||||
const angle = createLiteral(roundOff(getAngle(from, to), 0))
|
const angle = createLiteral(roundOff(getAngle(from, to), 0))
|
||||||
const xArg = createLiteral(roundOff(to[0], 2))
|
const xArg = createLiteral(roundOff(to[0], 2))
|
||||||
const newLine = createCallback
|
const newLine = createCallback
|
||||||
? createCallback([angle, xArg])
|
? createCallback([angle, xArg]).callExp
|
||||||
: createCallExpression('angledLineToX', [
|
: createCallExpression('angledLineToX', [
|
||||||
createArrayExpression([angle, xArg]),
|
createArrayExpression([angle, xArg]),
|
||||||
createPipeSubstitution(),
|
createPipeSubstitution(),
|
||||||
@ -945,7 +949,7 @@ export const angledLineToY: SketchLineHelper = {
|
|||||||
const angle = createLiteral(roundOff(getAngle(from, to), 0))
|
const angle = createLiteral(roundOff(getAngle(from, to), 0))
|
||||||
const yArg = createLiteral(roundOff(to[1], 2))
|
const yArg = createLiteral(roundOff(to[1], 2))
|
||||||
const newLine = createCallback
|
const newLine = createCallback
|
||||||
? createCallback([angle, yArg])
|
? createCallback([angle, yArg]).callExp
|
||||||
: createCallExpression('angledLineToY', [
|
: createCallExpression('angledLineToY', [
|
||||||
createArrayExpression([angle, yArg]),
|
createArrayExpression([angle, yArg]),
|
||||||
createPipeSubstitution(),
|
createPipeSubstitution(),
|
||||||
@ -1088,13 +1092,13 @@ export function replaceSketchLine({
|
|||||||
from: [number, number]
|
from: [number, number]
|
||||||
createCallback: TransformCallback
|
createCallback: TransformCallback
|
||||||
referencedSegment?: Path
|
referencedSegment?: Path
|
||||||
}): { modifiedAst: Program } {
|
}): { modifiedAst: Program; valueUsedInTransform?: number } {
|
||||||
if (!toolTips.includes(fnName)) throw new Error('not a tooltip')
|
if (!toolTips.includes(fnName)) throw new Error('not a tooltip')
|
||||||
const _node = { ...node }
|
const _node = { ...node }
|
||||||
const thePath = getNodePathFromSourceRange(_node, sourceRange)
|
const thePath = getNodePathFromSourceRange(_node, sourceRange)
|
||||||
|
|
||||||
const { add } = sketchLineHelperMap[fnName]
|
const { add } = sketchLineHelperMap[fnName]
|
||||||
const { modifiedAst } = add({
|
const { modifiedAst, valueUsedInTransform } = add({
|
||||||
node: _node,
|
node: _node,
|
||||||
previousProgramMemory: programMemory,
|
previousProgramMemory: programMemory,
|
||||||
pathToNode: thePath,
|
pathToNode: thePath,
|
||||||
@ -1104,7 +1108,7 @@ export function replaceSketchLine({
|
|||||||
replaceExisting: true,
|
replaceExisting: true,
|
||||||
createCallback,
|
createCallback,
|
||||||
})
|
})
|
||||||
return { modifiedAst }
|
return { modifiedAst, valueUsedInTransform }
|
||||||
}
|
}
|
||||||
|
|
||||||
export function addTagForSketchOnFace(
|
export function addTagForSketchOnFace(
|
||||||
|
@ -4,7 +4,7 @@ import { lexer } from '../tokeniser'
|
|||||||
import {
|
import {
|
||||||
ConstraintType,
|
ConstraintType,
|
||||||
getTransformInfos,
|
getTransformInfos,
|
||||||
transformAstForHorzVert,
|
transformAstSketchLines,
|
||||||
} from './sketchcombos'
|
} from './sketchcombos'
|
||||||
import { recast } from '../recast'
|
import { recast } from '../recast'
|
||||||
import { initPromise } from '../rust'
|
import { initPromise } from '../rust'
|
||||||
@ -32,11 +32,12 @@ function testingSwapSketchFnCall({
|
|||||||
const transformInfos = getTransformInfos([range], ast, constraintType)
|
const transformInfos = getTransformInfos([range], ast, constraintType)
|
||||||
|
|
||||||
if (!transformInfos) throw new Error('nope')
|
if (!transformInfos) throw new Error('nope')
|
||||||
const { modifiedAst } = transformAstForHorzVert({
|
const { modifiedAst } = transformAstSketchLines({
|
||||||
ast,
|
ast,
|
||||||
programMemory,
|
programMemory,
|
||||||
selectionRanges: [range],
|
selectionRanges: [range],
|
||||||
transformInfos,
|
transformInfos,
|
||||||
|
referenceSegName: '',
|
||||||
})
|
})
|
||||||
return {
|
return {
|
||||||
newCode: recast(modifiedAst),
|
newCode: recast(modifiedAst),
|
||||||
|
@ -3,8 +3,8 @@ import { lexer } from '../tokeniser'
|
|||||||
import {
|
import {
|
||||||
getConstraintType,
|
getConstraintType,
|
||||||
getTransformInfos,
|
getTransformInfos,
|
||||||
transformAstForSketchLines,
|
transformAstSketchLines,
|
||||||
transformAstForHorzVert,
|
transformSecondarySketchLinesTagFirst,
|
||||||
ConstraintType,
|
ConstraintType,
|
||||||
} from './sketchcombos'
|
} from './sketchcombos'
|
||||||
import { initPromise } from '../rust'
|
import { initPromise } from '../rust'
|
||||||
@ -204,7 +204,7 @@ show(part001)`
|
|||||||
'equalLength'
|
'equalLength'
|
||||||
)
|
)
|
||||||
|
|
||||||
const newAst = transformAstForSketchLines({
|
const newAst = transformSecondarySketchLinesTagFirst({
|
||||||
ast,
|
ast,
|
||||||
selectionRanges,
|
selectionRanges,
|
||||||
transformInfos,
|
transformInfos,
|
||||||
@ -282,11 +282,12 @@ show(part001)`
|
|||||||
const programMemory = executor(ast)
|
const programMemory = executor(ast)
|
||||||
const transformInfos = getTransformInfos(selectionRanges, ast, 'horizontal')
|
const transformInfos = getTransformInfos(selectionRanges, ast, 'horizontal')
|
||||||
|
|
||||||
const newAst = transformAstForHorzVert({
|
const newAst = transformAstSketchLines({
|
||||||
ast,
|
ast,
|
||||||
selectionRanges,
|
selectionRanges,
|
||||||
transformInfos,
|
transformInfos,
|
||||||
programMemory,
|
programMemory,
|
||||||
|
referenceSegName: '',
|
||||||
})?.modifiedAst
|
})?.modifiedAst
|
||||||
const newCode = recast(newAst)
|
const newCode = recast(newAst)
|
||||||
expect(newCode).toBe(expectModifiedScript)
|
expect(newCode).toBe(expectModifiedScript)
|
||||||
@ -331,11 +332,12 @@ show(part001)`
|
|||||||
const programMemory = executor(ast)
|
const programMemory = executor(ast)
|
||||||
const transformInfos = getTransformInfos(selectionRanges, ast, 'vertical')
|
const transformInfos = getTransformInfos(selectionRanges, ast, 'vertical')
|
||||||
|
|
||||||
const newAst = transformAstForHorzVert({
|
const newAst = transformAstSketchLines({
|
||||||
ast,
|
ast,
|
||||||
selectionRanges,
|
selectionRanges,
|
||||||
transformInfos,
|
transformInfos,
|
||||||
programMemory,
|
programMemory,
|
||||||
|
referenceSegName: '',
|
||||||
})?.modifiedAst
|
})?.modifiedAst
|
||||||
const newCode = recast(newAst)
|
const newCode = recast(newAst)
|
||||||
expect(newCode).toBe(expectModifiedScript)
|
expect(newCode).toBe(expectModifiedScript)
|
||||||
@ -419,7 +421,7 @@ function helperThing(
|
|||||||
constraint
|
constraint
|
||||||
)
|
)
|
||||||
|
|
||||||
const newAst = transformAstForSketchLines({
|
const newAst = transformSecondarySketchLinesTagFirst({
|
||||||
ast,
|
ast,
|
||||||
selectionRanges,
|
selectionRanges,
|
||||||
transformInfos,
|
transformInfos,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { TransformCallback } from './stdTypes'
|
import { TransformCallback } from './stdTypes'
|
||||||
import { Range, Ranges, toolTips, TooTip } from '../../useStore'
|
import { Ranges, toolTips, TooTip } from '../../useStore'
|
||||||
import {
|
import {
|
||||||
BinaryPart,
|
BinaryPart,
|
||||||
CallExpression,
|
CallExpression,
|
||||||
@ -21,7 +21,7 @@ import {
|
|||||||
giveSketchFnCallTag,
|
giveSketchFnCallTag,
|
||||||
} from '../modifyAst'
|
} from '../modifyAst'
|
||||||
import { createFirstArg, getFirstArg, replaceSketchLine } from './sketch'
|
import { createFirstArg, getFirstArg, replaceSketchLine } from './sketch'
|
||||||
import { Path, ProgramMemory } from '../executor'
|
import { ProgramMemory } from '../executor'
|
||||||
import { getSketchSegmentIndexFromSourceRange } from './sketchConstraints'
|
import { getSketchSegmentIndexFromSourceRange } from './sketchConstraints'
|
||||||
import { roundOff } from '../../lib/utils'
|
import { roundOff } from '../../lib/utils'
|
||||||
|
|
||||||
@ -44,46 +44,16 @@ export type ConstraintType =
|
|||||||
function createCallWrapper(
|
function createCallWrapper(
|
||||||
a: TooTip,
|
a: TooTip,
|
||||||
val: [Value, Value] | Value,
|
val: [Value, Value] | Value,
|
||||||
tag?: Value
|
tag?: Value,
|
||||||
) {
|
valueUsedInTransform?: number
|
||||||
return createCallExpression(a, [
|
): ReturnType<TransformCallback> {
|
||||||
|
return {
|
||||||
|
callExp: createCallExpression(a, [
|
||||||
createFirstArg(a, val, tag),
|
createFirstArg(a, val, tag),
|
||||||
createPipeSubstitution(),
|
createPipeSubstitution(),
|
||||||
])
|
]),
|
||||||
}
|
valueUsedInTransform,
|
||||||
|
}
|
||||||
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>('VariableDeclarator').node
|
|
||||||
const callExp = getNode<CallExpression>('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 }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type TransformInfo = {
|
export type TransformInfo = {
|
||||||
@ -93,7 +63,8 @@ export type TransformInfo = {
|
|||||||
varValB: Value // y / length or x y for angledLineOfXlength etc
|
varValB: Value // y / length or x y for angledLineOfXlength etc
|
||||||
referenceSegName: string
|
referenceSegName: string
|
||||||
tag?: Value
|
tag?: Value
|
||||||
}) => (args: [Value, Value], referencedSegment?: Path) => Value
|
forceValueUsedInTransform?: Value
|
||||||
|
}) => TransformCallback
|
||||||
}
|
}
|
||||||
|
|
||||||
type TransformMap = {
|
type TransformMap = {
|
||||||
@ -172,23 +143,27 @@ const getAngleLengthSign = (arg: Value, legAngleVal: BinaryPart) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const setHorzVertDistanceCreateNode =
|
const setHorzVertDistanceCreateNode =
|
||||||
(isX = true): TransformInfo['createNode'] =>
|
(
|
||||||
({ referenceSegName, tag }) => {
|
xOrY: 'x' | 'y',
|
||||||
|
index = xOrY === 'x' ? 0 : 1
|
||||||
|
): TransformInfo['createNode'] =>
|
||||||
|
({ referenceSegName, tag, forceValueUsedInTransform }) => {
|
||||||
return (args, referencedSegment) => {
|
return (args, referencedSegment) => {
|
||||||
const makeBinExp = (index: 0 | 1) => {
|
const valueUsedInTransform = roundOff(
|
||||||
const arg = getArgLiteralVal(args?.[index])
|
getArgLiteralVal(args?.[index]) - (referencedSegment?.to?.[index] || 0),
|
||||||
return createBinaryExpression([
|
2
|
||||||
createSegEnd(referenceSegName, isX),
|
)
|
||||||
|
const makeBinExp = createBinaryExpression([
|
||||||
|
createSegEnd(referenceSegName, !index),
|
||||||
'+',
|
'+',
|
||||||
createLiteral(
|
(forceValueUsedInTransform as BinaryPart) ||
|
||||||
roundOff(arg - (referencedSegment?.to?.[index] || 0), 2)
|
createLiteral(valueUsedInTransform),
|
||||||
),
|
|
||||||
])
|
])
|
||||||
}
|
|
||||||
return createCallWrapper(
|
return createCallWrapper(
|
||||||
'lineTo',
|
'lineTo',
|
||||||
isX ? [makeBinExp(0), args[1]] : [args[0], makeBinExp(1)],
|
!index ? [makeBinExp, args[1]] : [args[0], makeBinExp],
|
||||||
tag
|
tag,
|
||||||
|
valueUsedInTransform
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -301,11 +276,11 @@ const transformMap: TransformMap = {
|
|||||||
},
|
},
|
||||||
setHorzDistance: {
|
setHorzDistance: {
|
||||||
tooltip: 'lineTo',
|
tooltip: 'lineTo',
|
||||||
createNode: setHorzVertDistanceCreateNode(true),
|
createNode: setHorzVertDistanceCreateNode('x'),
|
||||||
},
|
},
|
||||||
setVertDistance: {
|
setVertDistance: {
|
||||||
tooltip: 'lineTo',
|
tooltip: 'lineTo',
|
||||||
createNode: setHorzVertDistanceCreateNode(false),
|
createNode: setHorzVertDistanceCreateNode('y'),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -826,99 +801,120 @@ export function getTransformInfos(
|
|||||||
return theTransforms
|
return theTransforms
|
||||||
}
|
}
|
||||||
|
|
||||||
export function transformAstForSketchLines({
|
export function transformSecondarySketchLinesTagFirst({
|
||||||
ast,
|
ast,
|
||||||
selectionRanges,
|
selectionRanges,
|
||||||
transformInfos,
|
transformInfos,
|
||||||
programMemory,
|
programMemory,
|
||||||
|
forceSegName,
|
||||||
|
forceValueUsedInTransform,
|
||||||
}: {
|
}: {
|
||||||
ast: Program
|
ast: Program
|
||||||
selectionRanges: Ranges
|
selectionRanges: Ranges
|
||||||
transformInfos: TransformInfo[]
|
transformInfos: TransformInfo[]
|
||||||
programMemory: ProgramMemory
|
programMemory: ProgramMemory
|
||||||
}): { modifiedAst: Program } {
|
forceSegName?: string
|
||||||
// deep clone since we are mutating in a loop, of which any could fail
|
forceValueUsedInTransform?: Value
|
||||||
let node = JSON.parse(JSON.stringify(ast))
|
}): {
|
||||||
|
modifiedAst: Program
|
||||||
|
valueUsedInTransform?: number
|
||||||
|
tagInfo: {
|
||||||
|
tag: string
|
||||||
|
isTagExisting: boolean
|
||||||
|
}
|
||||||
|
} {
|
||||||
|
// let node = JSON.parse(JSON.stringify(ast))
|
||||||
const primarySelection = selectionRanges[0]
|
const primarySelection = selectionRanges[0]
|
||||||
|
|
||||||
const { modifiedAst, tag } = giveSketchFnCallTag(node, primarySelection)
|
const { modifiedAst, tag, isTagExisting } = giveSketchFnCallTag(
|
||||||
node = modifiedAst
|
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 callBack = transformInfos?.[index].createNode
|
||||||
const transformTo = transformInfos?.[index].tooltip
|
const transformTo = transformInfos?.[index].tooltip
|
||||||
if (!callBack || !transformTo) throw new Error('no callback helper')
|
if (!callBack || !transformTo) throw new Error('no callback helper')
|
||||||
|
|
||||||
const callExpPath = getNodePathFromSourceRange(node, range)
|
const getNode = getNodeFromPathCurry(
|
||||||
const callExp = getNodeFromPath<CallExpression>(
|
|
||||||
node,
|
node,
|
||||||
callExpPath,
|
getNodePathFromSourceRange(node, range)
|
||||||
'CallExpression'
|
)
|
||||||
)?.node
|
|
||||||
const { val } = getFirstArg(callExp)
|
const callExp = getNode<CallExpression>('CallExpression')?.node
|
||||||
|
const varDec = getNode<VariableDeclarator>('VariableDeclarator').node
|
||||||
|
|
||||||
|
const { val, tag: callBackTag } = getFirstArg(callExp)
|
||||||
const [varValA, varValB] = Array.isArray(val) ? val : [val, val]
|
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,
|
programMemory,
|
||||||
node,
|
sourceRange: range,
|
||||||
range,
|
referencedSegment,
|
||||||
transformTo,
|
fnName: transformTo || (callExp.callee.name as TooTip),
|
||||||
callBack({
|
to,
|
||||||
referenceSegName: tag,
|
from,
|
||||||
|
createCallback: callBack({
|
||||||
|
referenceSegName,
|
||||||
varValA,
|
varValA,
|
||||||
varValB,
|
varValB,
|
||||||
|
tag: callBackTag,
|
||||||
|
forceValueUsedInTransform,
|
||||||
}),
|
}),
|
||||||
tag
|
|
||||||
)
|
|
||||||
node = modifiedAst
|
|
||||||
})
|
})
|
||||||
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<CallExpression>(
|
|
||||||
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
|
node = modifiedAst
|
||||||
|
if (typeof valueUsedInTransform === 'number') {
|
||||||
|
_valueUsedInTransform = valueUsedInTransform
|
||||||
|
}
|
||||||
})
|
})
|
||||||
return { modifiedAst: node }
|
return { modifiedAst: node, valueUsedInTransform: _valueUsedInTransform }
|
||||||
}
|
}
|
||||||
|
|
||||||
function createSegLen(referenceSegName: string): Value {
|
function createSegLen(referenceSegName: string): Value {
|
||||||
|
@ -70,7 +70,10 @@ interface updateArgs extends ModifyAstBase {
|
|||||||
export type TransformCallback = (
|
export type TransformCallback = (
|
||||||
args: [Value, Value],
|
args: [Value, Value],
|
||||||
referencedSegment?: Path
|
referencedSegment?: Path
|
||||||
) => Value
|
) => {
|
||||||
|
callExp: Value
|
||||||
|
valueUsedInTransform?: number
|
||||||
|
}
|
||||||
|
|
||||||
export type SketchCallTransfromMap = {
|
export type SketchCallTransfromMap = {
|
||||||
[key in TooTip]: TransformCallback
|
[key in TooTip]: TransformCallback
|
||||||
@ -81,6 +84,7 @@ export interface SketchLineHelper {
|
|||||||
add: (a: addCall) => {
|
add: (a: addCall) => {
|
||||||
modifiedAst: Program
|
modifiedAst: Program
|
||||||
pathToNode: (string | number)[]
|
pathToNode: (string | number)[]
|
||||||
|
valueUsedInTransform?: number
|
||||||
}
|
}
|
||||||
updateArgs: (a: updateArgs) => {
|
updateArgs: (a: updateArgs) => {
|
||||||
modifiedAst: Program
|
modifiedAst: Program
|
||||||
|
17
yarn.lock
17
yarn.lock
@ -1559,6 +1559,13 @@
|
|||||||
minimatch "^3.1.2"
|
minimatch "^3.1.2"
|
||||||
strip-json-comments "^3.1.1"
|
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":
|
"@humanwhocodes/config-array@^0.11.6":
|
||||||
version "0.11.7"
|
version "0.11.7"
|
||||||
resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.7.tgz#38aec044c6c828f6ed51d5d7ae3d9b9faf6dbb0f"
|
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:
|
dependencies:
|
||||||
source-map "~0.6.0"
|
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:
|
cliui@^7.0.2:
|
||||||
version "7.0.4"
|
version "7.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f"
|
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"
|
resolved "https://registry.yarnpkg.com/react-merge-refs/-/react-merge-refs-1.1.0.tgz#73d88b892c6c68cbb7a66e0800faa374f4c38b06"
|
||||||
integrity sha512-alTKsjEL0dKH/ru1Iyn7vliS2QRcBp9zZPGoWxUOvRGWPUYgjo+V01is7p04It6KhgrzhJGnIj9GgX8W4bZoCQ==
|
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:
|
react-reconciler@^0.27.0:
|
||||||
version "0.27.0"
|
version "0.27.0"
|
||||||
resolved "https://registry.yarnpkg.com/react-reconciler/-/react-reconciler-0.27.0.tgz#360124fdf2d76447c7491ee5f0e04503ed9acf5b"
|
resolved "https://registry.yarnpkg.com/react-reconciler/-/react-reconciler-0.27.0.tgz#360124fdf2d76447c7491ee5f0e04503ed9acf5b"
|
||||||
|
Reference in New Issue
Block a user