Add 'remove constraining values' UI (#80)
This commit is contained in:
@ -2,6 +2,7 @@ import { useStore, toolTips } from './useStore'
|
|||||||
import { extrudeSketch, sketchOnExtrudedFace } from './lang/modifyAst'
|
import { extrudeSketch, sketchOnExtrudedFace } from './lang/modifyAst'
|
||||||
import { getNodePathFromSourceRange } from './lang/queryAst'
|
import { getNodePathFromSourceRange } from './lang/queryAst'
|
||||||
import { HorzVert } from './components/Toolbar/HorzVert'
|
import { HorzVert } from './components/Toolbar/HorzVert'
|
||||||
|
import { RemoveConstrainingValues } from './components/Toolbar/RemoveConstrainingValues'
|
||||||
import { EqualLength } from './components/Toolbar/EqualLength'
|
import { EqualLength } from './components/Toolbar/EqualLength'
|
||||||
import { EqualAngle } from './components/Toolbar/EqualAngle'
|
import { EqualAngle } from './components/Toolbar/EqualAngle'
|
||||||
import { Intersect } from './components/Toolbar/Intersect'
|
import { Intersect } from './components/Toolbar/Intersect'
|
||||||
@ -170,6 +171,7 @@ export const Toolbar = () => {
|
|||||||
<SetAngleLength angleOrLength="setAngle" />
|
<SetAngleLength angleOrLength="setAngle" />
|
||||||
<SetAngleLength angleOrLength="setLength" />
|
<SetAngleLength angleOrLength="setLength" />
|
||||||
<Intersect />
|
<Intersect />
|
||||||
|
<RemoveConstrainingValues />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
76
src/components/Toolbar/RemoveConstrainingValues.tsx
Normal file
76
src/components/Toolbar/RemoveConstrainingValues.tsx
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
import { useState, useEffect } from 'react'
|
||||||
|
import { toolTips, useStore } from '../../useStore'
|
||||||
|
import { Value } from '../../lang/abstractSyntaxTree'
|
||||||
|
import {
|
||||||
|
getNodePathFromSourceRange,
|
||||||
|
getNodeFromPath,
|
||||||
|
} from '../../lang/queryAst'
|
||||||
|
import {
|
||||||
|
TransformInfo,
|
||||||
|
getRemoveConstraintsTransforms,
|
||||||
|
transformAstSketchLines,
|
||||||
|
} from '../../lang/std/sketchcombos'
|
||||||
|
|
||||||
|
export const RemoveConstrainingValues = () => {
|
||||||
|
const { guiMode, selectionRanges, ast, programMemory, updateAst } = useStore(
|
||||||
|
(s) => ({
|
||||||
|
guiMode: s.guiMode,
|
||||||
|
ast: s.ast,
|
||||||
|
updateAst: s.updateAst,
|
||||||
|
selectionRanges: s.selectionRanges,
|
||||||
|
programMemory: s.programMemory,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
const [enableHorz, setEnableHorz] = useState(false)
|
||||||
|
const [transformInfos, setTransformInfos] = useState<TransformInfo[]>()
|
||||||
|
useEffect(() => {
|
||||||
|
if (!ast) return
|
||||||
|
const paths = selectionRanges.map((selectionRange) =>
|
||||||
|
getNodePathFromSourceRange(ast, selectionRange)
|
||||||
|
)
|
||||||
|
const nodes = paths.map(
|
||||||
|
(pathToNode) => getNodeFromPath<Value>(ast, pathToNode).node
|
||||||
|
)
|
||||||
|
const isAllTooltips = nodes.every(
|
||||||
|
(node) =>
|
||||||
|
node?.type === 'CallExpression' &&
|
||||||
|
toolTips.includes(node.callee.name as any)
|
||||||
|
)
|
||||||
|
|
||||||
|
const theTransforms = getRemoveConstraintsTransforms(
|
||||||
|
selectionRanges,
|
||||||
|
ast,
|
||||||
|
'removeConstrainingValues'
|
||||||
|
)
|
||||||
|
setTransformInfos(theTransforms)
|
||||||
|
|
||||||
|
const _enableHorz = isAllTooltips && theTransforms.every(Boolean)
|
||||||
|
setEnableHorz(_enableHorz)
|
||||||
|
}, [guiMode, selectionRanges])
|
||||||
|
if (guiMode.mode !== 'sketch') return null
|
||||||
|
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
onClick={() =>
|
||||||
|
transformInfos &&
|
||||||
|
ast &&
|
||||||
|
updateAst(
|
||||||
|
transformAstSketchLines({
|
||||||
|
ast,
|
||||||
|
selectionRanges,
|
||||||
|
transformInfos,
|
||||||
|
programMemory,
|
||||||
|
referenceSegName: '',
|
||||||
|
})?.modifiedAst
|
||||||
|
)
|
||||||
|
}
|
||||||
|
className={`border m-1 px-1 rounded text-xs ${
|
||||||
|
enableHorz ? 'bg-gray-50 text-gray-800' : 'bg-gray-200 text-gray-400'
|
||||||
|
}`}
|
||||||
|
disabled={!enableHorz}
|
||||||
|
title="yo dawg"
|
||||||
|
>
|
||||||
|
RemoveConstrainingValues
|
||||||
|
</button>
|
||||||
|
)
|
||||||
|
}
|
@ -1666,7 +1666,10 @@ function getFirstArgValuesForXYLineFns(callExpression: CallExpression): {
|
|||||||
if (length) {
|
if (length) {
|
||||||
return { val: length, tag }
|
return { val: length, tag }
|
||||||
}
|
}
|
||||||
throw new Error('expected ArrayExpression or ObjectExpression')
|
console.warn('expected ArrayExpression or ObjectExpression')
|
||||||
|
return {
|
||||||
|
val: createLiteral(1),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const getAngledLineThatIntersects = (
|
const getAngledLineThatIntersects = (
|
||||||
|
@ -45,6 +45,7 @@ export type ConstraintType =
|
|||||||
| 'setAngle'
|
| 'setAngle'
|
||||||
| 'setLength'
|
| 'setLength'
|
||||||
| 'intersect'
|
| 'intersect'
|
||||||
|
| 'removeConstrainingValues'
|
||||||
|
|
||||||
function createCallWrapper(
|
function createCallWrapper(
|
||||||
a: TooTip,
|
a: TooTip,
|
||||||
@ -939,6 +940,86 @@ const transformMap: TransformMap = {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getRemoveConstraintsTransform(
|
||||||
|
sketchFnExp: CallExpression,
|
||||||
|
constraintType: ConstraintType
|
||||||
|
): TransformInfo | false {
|
||||||
|
let name = sketchFnExp.callee.name as TooTip
|
||||||
|
if (!toolTips.includes(name)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
const xyLineMap: {
|
||||||
|
[key in TooTip]?: TooTip
|
||||||
|
} = {
|
||||||
|
xLine: 'line',
|
||||||
|
yLine: 'line',
|
||||||
|
xLineTo: 'lineTo',
|
||||||
|
yLineTo: 'lineTo',
|
||||||
|
}
|
||||||
|
|
||||||
|
const _name = xyLineMap[name]
|
||||||
|
if (_name) {
|
||||||
|
name = _name
|
||||||
|
}
|
||||||
|
|
||||||
|
const transformInfo: TransformInfo = {
|
||||||
|
tooltip: 'line',
|
||||||
|
// tooltip: name,
|
||||||
|
createNode:
|
||||||
|
({ tag, referenceSegName }) =>
|
||||||
|
(args) => {
|
||||||
|
return createCallWrapper('line', args, tag)
|
||||||
|
// The following commented changes values to hardcode, but keeps the line type the same, maybe that's useful?
|
||||||
|
|
||||||
|
// if (name === 'angledLineThatIntersects') {
|
||||||
|
// return intersectCallWrapper({
|
||||||
|
// fnName: name,
|
||||||
|
// angleVal: args[0],
|
||||||
|
// offsetVal: args[1],
|
||||||
|
// intersectTag: createLiteral(referenceSegName),
|
||||||
|
// tag,
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
// return createCallWrapper(name, args, tag)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if the function is locked down and so can't be transformed
|
||||||
|
const firstArg = getFirstArg(sketchFnExp)
|
||||||
|
if (Array.isArray(firstArg.val)) {
|
||||||
|
const [a, b] = firstArg.val
|
||||||
|
if (a?.type !== 'Literal' && b?.type !== 'Literal') {
|
||||||
|
return transformInfo
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (firstArg.val?.type !== 'Literal') {
|
||||||
|
return transformInfo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if the function has no constraints
|
||||||
|
const isTwoValFree =
|
||||||
|
Array.isArray(firstArg.val) &&
|
||||||
|
firstArg.val?.[0]?.type === 'Literal' &&
|
||||||
|
firstArg.val?.[1]?.type === 'Literal'
|
||||||
|
if (isTwoValFree) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
const isOneValFree =
|
||||||
|
!Array.isArray(firstArg.val) && firstArg.val?.type === 'Literal'
|
||||||
|
if (isOneValFree) {
|
||||||
|
return transformInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
// check what constraints the function has
|
||||||
|
const lineInputType = getConstraintType(firstArg.val, name)
|
||||||
|
if (lineInputType) {
|
||||||
|
return transformInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
export function getTransformMapPath(
|
export function getTransformMapPath(
|
||||||
sketchFnExp: CallExpression,
|
sketchFnExp: CallExpression,
|
||||||
constraintType: ConstraintType
|
constraintType: ConstraintType
|
||||||
@ -1068,6 +1149,28 @@ export function getTransformInfos(
|
|||||||
return theTransforms
|
return theTransforms
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getRemoveConstraintsTransforms(
|
||||||
|
selectionRanges: Ranges,
|
||||||
|
ast: Program,
|
||||||
|
constraintType: ConstraintType
|
||||||
|
): TransformInfo[] {
|
||||||
|
// return ()
|
||||||
|
const paths = selectionRanges.map((selectionRange) =>
|
||||||
|
getNodePathFromSourceRange(ast, selectionRange)
|
||||||
|
)
|
||||||
|
const nodes = paths.map(
|
||||||
|
(pathToNode) => getNodeFromPath<Value>(ast, pathToNode).node
|
||||||
|
)
|
||||||
|
|
||||||
|
const theTransforms = nodes.map((node) => {
|
||||||
|
if (node?.type === 'CallExpression')
|
||||||
|
return getRemoveConstraintsTransform(node, constraintType)
|
||||||
|
|
||||||
|
return false
|
||||||
|
}) as TransformInfo[]
|
||||||
|
return theTransforms
|
||||||
|
}
|
||||||
|
|
||||||
export function transformSecondarySketchLinesTagFirst({
|
export function transformSecondarySketchLinesTagFirst({
|
||||||
ast,
|
ast,
|
||||||
selectionRanges,
|
selectionRanges,
|
||||||
@ -1151,6 +1254,17 @@ export function transformAstSketchLines({
|
|||||||
const varDec = getNode<VariableDeclarator>('VariableDeclarator').node
|
const varDec = getNode<VariableDeclarator>('VariableDeclarator').node
|
||||||
|
|
||||||
const { val, tag: callBackTag } = getFirstArg(callExp)
|
const { val, tag: callBackTag } = getFirstArg(callExp)
|
||||||
|
const _referencedSegmentNameVal =
|
||||||
|
callExp.arguments[0]?.type === 'ObjectExpression' &&
|
||||||
|
callExp.arguments[0].properties?.find(
|
||||||
|
(prop) => prop.key.name === 'intersectTag'
|
||||||
|
)?.value
|
||||||
|
const _referencedSegmentName =
|
||||||
|
referenceSegName ||
|
||||||
|
(_referencedSegmentNameVal &&
|
||||||
|
_referencedSegmentNameVal.type === 'Literal' &&
|
||||||
|
String(_referencedSegmentNameVal.value)) ||
|
||||||
|
''
|
||||||
const [varValA, varValB] = Array.isArray(val) ? val : [val, val]
|
const [varValA, varValB] = Array.isArray(val) ? val : [val, val]
|
||||||
|
|
||||||
const varName = varDec.id.name
|
const varName = varDec.id.name
|
||||||
@ -1160,7 +1274,7 @@ export function transformAstSketchLines({
|
|||||||
const seg = getSketchSegmentFromSourceRange(sketchGroup, range)
|
const seg = getSketchSegmentFromSourceRange(sketchGroup, range)
|
||||||
const referencedSegment = referencedSegmentRange
|
const referencedSegment = referencedSegmentRange
|
||||||
? getSketchSegmentFromSourceRange(sketchGroup, referencedSegmentRange)
|
? getSketchSegmentFromSourceRange(sketchGroup, referencedSegmentRange)
|
||||||
: sketchGroup.value.find((path) => path.name === referenceSegName)
|
: sketchGroup.value.find((path) => path.name === _referencedSegmentName)
|
||||||
const { to, from } = seg
|
const { to, from } = seg
|
||||||
const { modifiedAst, valueUsedInTransform } = replaceSketchLine({
|
const { modifiedAst, valueUsedInTransform } = replaceSketchLine({
|
||||||
node: node,
|
node: node,
|
||||||
@ -1171,7 +1285,7 @@ export function transformAstSketchLines({
|
|||||||
to,
|
to,
|
||||||
from,
|
from,
|
||||||
createCallback: callBack({
|
createCallback: callBack({
|
||||||
referenceSegName,
|
referenceSegName: _referencedSegmentName,
|
||||||
varValA,
|
varValA,
|
||||||
varValB,
|
varValB,
|
||||||
tag: callBackTag,
|
tag: callBackTag,
|
||||||
|
Reference in New Issue
Block a user