Add constraint colour indications (#73)
This commit is contained in:
@ -17,6 +17,7 @@ import { useStore } from '../useStore'
|
||||
import { isOverlap, roundOff } from '../lib/utils'
|
||||
import { Vector3, DoubleSide, Quaternion } from 'three'
|
||||
import { useSetCursor } from '../hooks/useSetCursor'
|
||||
import { getConstraintLevelFromSourceRange } from '../lang/std/sketchcombos'
|
||||
|
||||
function MovingSphere({
|
||||
geo,
|
||||
@ -416,25 +417,43 @@ function LineRender({
|
||||
rotation: Rotation
|
||||
position: Position
|
||||
}) {
|
||||
const { setHighlightRange } = useStore((s) => ({
|
||||
const { setHighlightRange, guiMode, ast } = useStore((s) => ({
|
||||
setHighlightRange: s.setHighlightRange,
|
||||
guiMode: s.guiMode,
|
||||
ast: s.ast,
|
||||
}))
|
||||
const onClick = useSetCursor(sourceRange)
|
||||
// This reference will give us direct access to the mesh
|
||||
const ref = useRef<BufferGeometry | undefined>() as any
|
||||
const [hovered, setHover] = useState(false)
|
||||
|
||||
const [baseColor, setBaseColor] = useState('orange')
|
||||
useEffect(() => {
|
||||
if (!ast || guiMode.mode !== 'sketch') {
|
||||
setBaseColor('orange')
|
||||
return
|
||||
}
|
||||
const level = getConstraintLevelFromSourceRange(sourceRange, ast)
|
||||
if (level === 'free') {
|
||||
setBaseColor('orange')
|
||||
} else if (level === 'partial') {
|
||||
setBaseColor('IndianRed')
|
||||
} else if (level === 'full') {
|
||||
setBaseColor('lightgreen')
|
||||
}
|
||||
}, [guiMode, ast, sourceRange])
|
||||
|
||||
return (
|
||||
<>
|
||||
<mesh
|
||||
quaternion={rotation}
|
||||
position={position}
|
||||
ref={ref}
|
||||
onPointerOver={(event) => {
|
||||
onPointerOver={(e) => {
|
||||
setHover(true)
|
||||
setHighlightRange(sourceRange)
|
||||
}}
|
||||
onPointerOut={(event) => {
|
||||
onPointerOut={(e) => {
|
||||
setHover(false)
|
||||
setHighlightRange([0, 0])
|
||||
}}
|
||||
@ -442,7 +461,7 @@ function LineRender({
|
||||
>
|
||||
<primitive object={geo} />
|
||||
<meshStandardMaterial
|
||||
color={hovered ? 'hotpink' : forceHighlight ? 'skyblue' : 'orange'}
|
||||
color={hovered ? 'hotpink' : forceHighlight ? 'skyblue' : baseColor}
|
||||
/>
|
||||
</mesh>
|
||||
</>
|
||||
|
@ -6,6 +6,7 @@ import {
|
||||
transformAstSketchLines,
|
||||
transformSecondarySketchLinesTagFirst,
|
||||
ConstraintType,
|
||||
getConstraintLevelFromSourceRange,
|
||||
} from './sketchcombos'
|
||||
import { initPromise } from '../rust'
|
||||
import { TooTip } from '../../useStore'
|
||||
@ -429,3 +430,64 @@ function helperThing(
|
||||
})?.modifiedAst
|
||||
return recast(newAst)
|
||||
}
|
||||
|
||||
describe('testing getConstraintLevelFromSourceRange', () => {
|
||||
it('should devide up lines into free, partial and fully contrained', () => {
|
||||
const code = `const baseLength = 3
|
||||
const baseThick = 1
|
||||
const armThick = 0.5
|
||||
const totalHeight = 4
|
||||
const armAngle = 60
|
||||
const totalLength = 9.74
|
||||
const yDatum = 0
|
||||
|
||||
const baseThickHalf = baseThick / 2
|
||||
const halfHeight = totalHeight / 2
|
||||
const halfArmAngle = armAngle / 2
|
||||
|
||||
const part001 = startSketchAt([-0.01, -0.05])
|
||||
|> line([0.01, 0.94 + 0], %) // partial
|
||||
|> xLine(3.03, %) // partial
|
||||
|> angledLine({
|
||||
angle: halfArmAngle,
|
||||
length: 2.45,
|
||||
tag: 'seg01bing'
|
||||
}, %) // partial
|
||||
|> xLine(4.4, %) // partial
|
||||
|> yLine(-1, %) // partial
|
||||
|> xLine(-4.2 + 0, %) // full
|
||||
|> angledLine([segAng('seg01bing', %) + 180, 1.79], %) // partial
|
||||
|> line([1.44, -0.74], %) // free
|
||||
|> xLine(3.36, %) // partial
|
||||
|> line([-1.49, 1.06], %) // free
|
||||
|> xLine(-3.43 + 0, %) // full
|
||||
|> angledLineOfXLength([243 + 0, 1.2 + 0], %) // full
|
||||
show(part001)`
|
||||
const ast = abstractSyntaxTree(lexer(code))
|
||||
const constraintLevels: ReturnType<
|
||||
typeof getConstraintLevelFromSourceRange
|
||||
>[] = ['full', 'partial', 'free']
|
||||
constraintLevels.forEach((constraintLevel) => {
|
||||
const recursivelySeachCommentsAndCheckConstraintLevel = (
|
||||
str: string,
|
||||
offset: number = 0
|
||||
): null => {
|
||||
const index = str.indexOf(`// ${constraintLevel}`, offset)
|
||||
if (index === -1) {
|
||||
return null
|
||||
}
|
||||
const offsetIndex = index - 7
|
||||
const expectedConstraintLevel = getConstraintLevelFromSourceRange(
|
||||
[offsetIndex, offsetIndex],
|
||||
ast
|
||||
)
|
||||
expect(expectedConstraintLevel).toBe(constraintLevel)
|
||||
return recursivelySeachCommentsAndCheckConstraintLevel(
|
||||
str,
|
||||
index + constraintLevel.length
|
||||
)
|
||||
}
|
||||
recursivelySeachCommentsAndCheckConstraintLevel(code)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@ -1220,3 +1220,38 @@ function createLastSeg(isX: boolean): CallExpression {
|
||||
function getArgLiteralVal(arg: Value): number {
|
||||
return arg?.type === 'Literal' ? Number(arg.value) : 0
|
||||
}
|
||||
|
||||
export function getConstraintLevelFromSourceRange(
|
||||
cursorRange: Range,
|
||||
ast: Program
|
||||
): 'free' | 'partial' | 'full' {
|
||||
const { node: sketchFnExp } = getNodeFromPath<CallExpression>(
|
||||
ast,
|
||||
getNodePathFromSourceRange(ast, cursorRange)
|
||||
)
|
||||
const name = sketchFnExp?.callee?.name as TooTip
|
||||
if (!toolTips.includes(name)) return 'free'
|
||||
|
||||
const firstArg = getFirstArg(sketchFnExp)
|
||||
|
||||
// check if the function is fully constrained
|
||||
if (Array.isArray(firstArg.val)) {
|
||||
const [a, b] = firstArg.val
|
||||
if (a?.type !== 'Literal' && b?.type !== 'Literal') return 'full'
|
||||
} else {
|
||||
if (firstArg.val?.type !== 'Literal') return 'full'
|
||||
}
|
||||
|
||||
// check if the function has no constraints
|
||||
const isTwoValFree =
|
||||
Array.isArray(firstArg.val) &&
|
||||
firstArg.val?.[0]?.type === 'Literal' &&
|
||||
firstArg.val?.[1]?.type === 'Literal'
|
||||
const isOneValFree =
|
||||
!Array.isArray(firstArg.val) && firstArg.val?.type === 'Literal'
|
||||
|
||||
if (isTwoValFree) return 'free'
|
||||
if (isOneValFree) return 'partial'
|
||||
|
||||
return 'partial'
|
||||
}
|
||||
|
Reference in New Issue
Block a user