functional sketch working (#26)
* functional sketch working With old sketch block still there * get all version of lines working with add line and update line * remove old ui state types * some clean up * rename some things * add todo for multi cursor * shorten useStore repitition * small type improvement * big overhaul to group sketch function and they ast modifying helpers together * unneeded tweak * ruthlessly rip out sketch logic * clean up path keyword * getting sketch on face working again with all the new sketch line types * add a bunch of tests and re-arrage file structure
This commit is contained in:
		@ -69,6 +69,7 @@ export const BasePlanes = () => {
 | 
			
		||||
      rotation: quaternion.toArray() as [number, number, number, number],
 | 
			
		||||
      position: [0, 0, 0],
 | 
			
		||||
      pathToNode,
 | 
			
		||||
      isTooltip: true,
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    updateAst(modifiedAst)
 | 
			
		||||
 | 
			
		||||
@ -11,17 +11,15 @@ const myFn = (a) => {
 | 
			
		||||
}
 | 
			
		||||
const otherVar = myFn(5)
 | 
			
		||||
 | 
			
		||||
sketch theExtrude {
 | 
			
		||||
  lineTo(-2.4, myVar)
 | 
			
		||||
  lineTo(-0.76, otherVar)
 | 
			
		||||
}
 | 
			
		||||
const theExtrude = startSketchAt([0, 0]) 
 | 
			
		||||
  |> lineTo([-2.4, myVar], %)
 | 
			
		||||
  |> lineTo([-0.76, otherVar], %)
 | 
			
		||||
  |> extrude(4, %)
 | 
			
		||||
 | 
			
		||||
sketch theSketch {
 | 
			
		||||
  lineTo(-3.35, 0.17)
 | 
			
		||||
  lineTo(0.98, 5.16)
 | 
			
		||||
  lineTo(2.15, 4.32)
 | 
			
		||||
}
 | 
			
		||||
const theSketch = startSketchAt([0, 0])
 | 
			
		||||
  |> lineTo([-3.35, 0.17], %)
 | 
			
		||||
  |> lineTo([0.98, 5.16], %)
 | 
			
		||||
  |> lineTo([2.15, 4.32], %)
 | 
			
		||||
  |> rx(90, %)
 | 
			
		||||
show(theExtrude, theSketch)`
 | 
			
		||||
  const tokens = lexer(code)
 | 
			
		||||
 | 
			
		||||
@ -3,8 +3,9 @@ import {
 | 
			
		||||
  getNodePathFromSourceRange,
 | 
			
		||||
  getNodeFromPath,
 | 
			
		||||
  CallExpression,
 | 
			
		||||
  ArrayExpression,
 | 
			
		||||
} from '../lang/abstractSyntaxTree'
 | 
			
		||||
import { changeArguments } from '../lang/modifyAst'
 | 
			
		||||
import { changeSketchArguments } from '../lang/std/sketch'
 | 
			
		||||
import {
 | 
			
		||||
  ExtrudeGroup,
 | 
			
		||||
  ExtrudeSurface,
 | 
			
		||||
@ -17,14 +18,10 @@ import {
 | 
			
		||||
} from '../lang/executor'
 | 
			
		||||
import { BufferGeometry } from 'three'
 | 
			
		||||
import { useStore } from '../useStore'
 | 
			
		||||
import { isOverlapping } from '../lib/utils'
 | 
			
		||||
import { isOverlap } from '../lib/utils'
 | 
			
		||||
import { Vector3, DoubleSide, Quaternion } from 'three'
 | 
			
		||||
import { useSetCursor } from '../hooks/useSetCursor'
 | 
			
		||||
 | 
			
		||||
const roundOff = (num: number, places: number): number => {
 | 
			
		||||
  const x = Math.pow(10, places)
 | 
			
		||||
  return Math.round(num * x) / x
 | 
			
		||||
}
 | 
			
		||||
import { roundOff } from '../lib/utils'
 | 
			
		||||
 | 
			
		||||
function MovingSphere({
 | 
			
		||||
  geo,
 | 
			
		||||
@ -32,12 +29,14 @@ function MovingSphere({
 | 
			
		||||
  editorCursor,
 | 
			
		||||
  rotation,
 | 
			
		||||
  position,
 | 
			
		||||
  from,
 | 
			
		||||
}: {
 | 
			
		||||
  geo: BufferGeometry
 | 
			
		||||
  sourceRange: [number, number]
 | 
			
		||||
  editorCursor: boolean
 | 
			
		||||
  rotation: Rotation
 | 
			
		||||
  position: Position
 | 
			
		||||
  from: [number, number]
 | 
			
		||||
}) {
 | 
			
		||||
  const ref = useRef<BufferGeometry | undefined>() as any
 | 
			
		||||
  const detectionPlaneRef = useRef<BufferGeometry | undefined>() as any
 | 
			
		||||
@ -46,12 +45,14 @@ function MovingSphere({
 | 
			
		||||
  const [hovered, setHover] = useState(false)
 | 
			
		||||
  const [isMouseDown, setIsMouseDown] = useState(false)
 | 
			
		||||
 | 
			
		||||
  const { setHighlightRange, guiMode, ast, updateAst } = useStore((s) => ({
 | 
			
		||||
    setHighlightRange: s.setHighlightRange,
 | 
			
		||||
    guiMode: s.guiMode,
 | 
			
		||||
    ast: s.ast,
 | 
			
		||||
    updateAst: s.updateAst,
 | 
			
		||||
  }))
 | 
			
		||||
  const { setHighlightRange, guiMode, ast, updateAst, programMemory } =
 | 
			
		||||
    useStore((s) => ({
 | 
			
		||||
      setHighlightRange: s.setHighlightRange,
 | 
			
		||||
      guiMode: s.guiMode,
 | 
			
		||||
      ast: s.ast,
 | 
			
		||||
      updateAst: s.updateAst,
 | 
			
		||||
      programMemory: s.programMemory,
 | 
			
		||||
    }))
 | 
			
		||||
  const { originalXY } = useMemo(() => {
 | 
			
		||||
    if (ast) {
 | 
			
		||||
      const thePath = getNodePathFromSourceRange(ast, sourceRange)
 | 
			
		||||
@ -59,7 +60,10 @@ function MovingSphere({
 | 
			
		||||
        ast,
 | 
			
		||||
        thePath
 | 
			
		||||
      )
 | 
			
		||||
      const [xArg, yArg] = callExpression?.arguments || []
 | 
			
		||||
      const [xArg, yArg] =
 | 
			
		||||
        guiMode.mode === 'sketch'
 | 
			
		||||
          ? callExpression?.arguments || []
 | 
			
		||||
          : (callExpression?.arguments?.[0] as ArrayExpression)?.elements || []
 | 
			
		||||
      const x = xArg?.type === 'Literal' ? xArg.value : -1
 | 
			
		||||
      const y = yArg?.type === 'Literal' ? yArg.value : -1
 | 
			
		||||
      return {
 | 
			
		||||
@ -87,7 +91,15 @@ function MovingSphere({
 | 
			
		||||
        yo.sub(new Vector3(...position).applyQuaternion(inverseQuaternion))
 | 
			
		||||
        let [x, y] = [roundOff(yo.x, 2), roundOff(yo.y, 2)]
 | 
			
		||||
        let theNewPoints: [number, number] = [x, y]
 | 
			
		||||
        const { modifiedAst } = changeArguments(ast, thePath, theNewPoints)
 | 
			
		||||
        const { modifiedAst } = changeSketchArguments(
 | 
			
		||||
          ast,
 | 
			
		||||
          programMemory,
 | 
			
		||||
          sourceRange,
 | 
			
		||||
          theNewPoints,
 | 
			
		||||
          guiMode,
 | 
			
		||||
          from
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        updateAst(modifiedAst)
 | 
			
		||||
        ref.current.position.set(...position)
 | 
			
		||||
      }
 | 
			
		||||
@ -285,7 +297,7 @@ function WallRender({
 | 
			
		||||
 | 
			
		||||
  const [editorCursor, setEditorCursor] = useState(false)
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    const shouldHighlight = isOverlapping(
 | 
			
		||||
    const shouldHighlight = isOverlap(
 | 
			
		||||
      geoInfo.__geoMeta.sourceRange,
 | 
			
		||||
      selectionRange
 | 
			
		||||
    )
 | 
			
		||||
@ -340,7 +352,7 @@ function PathRender({
 | 
			
		||||
  }))
 | 
			
		||||
  const [editorCursor, setEditorCursor] = useState(false)
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    const shouldHighlight = isOverlapping(
 | 
			
		||||
    const shouldHighlight = isOverlap(
 | 
			
		||||
      geoInfo.__geoMeta.sourceRange,
 | 
			
		||||
      selectionRange
 | 
			
		||||
    )
 | 
			
		||||
@ -366,6 +378,7 @@ function PathRender({
 | 
			
		||||
            <MovingSphere
 | 
			
		||||
              key={i}
 | 
			
		||||
              geo={meta.geo}
 | 
			
		||||
              from={geoInfo.from}
 | 
			
		||||
              sourceRange={geoInfo.__geoMeta.sourceRange}
 | 
			
		||||
              editorCursor={forceHighlight || editorCursor}
 | 
			
		||||
              rotation={rotation}
 | 
			
		||||
@ -424,9 +437,9 @@ function LineRender({
 | 
			
		||||
  )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Boop = ExtrudeGroup | SketchGroup
 | 
			
		||||
type Artifact = ExtrudeGroup | SketchGroup
 | 
			
		||||
 | 
			
		||||
function useSetAppModeFromCursorLocation(artifacts: Boop[]) {
 | 
			
		||||
function useSetAppModeFromCursorLocation(artifacts: Artifact[]) {
 | 
			
		||||
  const { selectionRange, guiMode, setGuiMode, ast } = useStore(
 | 
			
		||||
    ({ selectionRange, guiMode, setGuiMode, ast }) => ({
 | 
			
		||||
      selectionRange,
 | 
			
		||||
@ -438,7 +451,7 @@ function useSetAppModeFromCursorLocation(artifacts: Boop[]) {
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    const artifactsWithinCursorRange: (
 | 
			
		||||
      | {
 | 
			
		||||
          parentType: Boop['type']
 | 
			
		||||
          parentType: Artifact['type']
 | 
			
		||||
          isParent: true
 | 
			
		||||
          pathToNode: PathToNode
 | 
			
		||||
          sourceRange: SourceRange
 | 
			
		||||
@ -446,25 +459,29 @@ function useSetAppModeFromCursorLocation(artifacts: Boop[]) {
 | 
			
		||||
          position: Position
 | 
			
		||||
        }
 | 
			
		||||
      | {
 | 
			
		||||
          parentType: Boop['type']
 | 
			
		||||
          parentType: Artifact['type']
 | 
			
		||||
          isParent: false
 | 
			
		||||
          pathToNode: PathToNode
 | 
			
		||||
          sourceRange: SourceRange
 | 
			
		||||
          rotation: Rotation
 | 
			
		||||
          position: Position
 | 
			
		||||
        }
 | 
			
		||||
    )[] = []
 | 
			
		||||
    artifacts?.forEach((artifact) => {
 | 
			
		||||
      artifact.value.forEach((geo) => {
 | 
			
		||||
        if (isOverlapping(geo.__geoMeta.sourceRange, selectionRange)) {
 | 
			
		||||
        if (isOverlap(geo.__geoMeta.sourceRange, selectionRange)) {
 | 
			
		||||
          artifactsWithinCursorRange.push({
 | 
			
		||||
            parentType: artifact.type,
 | 
			
		||||
            isParent: false,
 | 
			
		||||
            pathToNode: geo.__geoMeta.pathToNode,
 | 
			
		||||
            sourceRange: geo.__geoMeta.sourceRange,
 | 
			
		||||
            rotation: artifact.rotation,
 | 
			
		||||
            position: artifact.position,
 | 
			
		||||
          })
 | 
			
		||||
        }
 | 
			
		||||
      })
 | 
			
		||||
      artifact.__meta.forEach((meta) => {
 | 
			
		||||
        if (isOverlapping(meta.sourceRange, selectionRange)) {
 | 
			
		||||
        if (isOverlap(meta.sourceRange, selectionRange)) {
 | 
			
		||||
          artifactsWithinCursorRange.push({
 | 
			
		||||
            parentType: artifact.type,
 | 
			
		||||
            isParent: true,
 | 
			
		||||
@ -477,35 +494,39 @@ function useSetAppModeFromCursorLocation(artifacts: Boop[]) {
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
    const parentArtifacts = artifactsWithinCursorRange.filter((a) => a.isParent)
 | 
			
		||||
    if (parentArtifacts.length > 1) {
 | 
			
		||||
      console.log('multiple parents, might be an issue?', parentArtifacts)
 | 
			
		||||
    }
 | 
			
		||||
    const hasSketchArtifact = artifactsWithinCursorRange.filter(
 | 
			
		||||
      ({ parentType }) => parentType === 'sketchGroup'
 | 
			
		||||
    )
 | 
			
		||||
    const hasExtrudeArtifact = artifactsWithinCursorRange.filter(
 | 
			
		||||
      ({ parentType }) => parentType === 'extrudeGroup'
 | 
			
		||||
    )
 | 
			
		||||
    const artifact = parentArtifacts[0]
 | 
			
		||||
    const shouldHighlight = !!artifact
 | 
			
		||||
    const shouldHighlight = !!artifact || hasSketchArtifact.length
 | 
			
		||||
    if (
 | 
			
		||||
      shouldHighlight &&
 | 
			
		||||
      (guiMode.mode === 'default' || guiMode.mode === 'canEditSketch') &&
 | 
			
		||||
      ast &&
 | 
			
		||||
      artifact.parentType === 'sketchGroup' &&
 | 
			
		||||
      artifact.isParent
 | 
			
		||||
      hasSketchArtifact.length
 | 
			
		||||
    ) {
 | 
			
		||||
      const pathToNode = getNodePathFromSourceRange(ast, artifact.sourceRange)
 | 
			
		||||
      const { rotation, position } = artifact
 | 
			
		||||
      const pathToNode = getNodePathFromSourceRange(
 | 
			
		||||
        ast,
 | 
			
		||||
        hasSketchArtifact[0].sourceRange
 | 
			
		||||
      )
 | 
			
		||||
      const { rotation, position } = hasSketchArtifact[0]
 | 
			
		||||
      setGuiMode({ mode: 'canEditSketch', pathToNode, rotation, position })
 | 
			
		||||
    } else if (
 | 
			
		||||
      shouldHighlight &&
 | 
			
		||||
      (guiMode.mode === 'default' || guiMode.mode === 'canEditSketch') &&
 | 
			
		||||
      ast &&
 | 
			
		||||
      artifact.parentType === 'extrudeGroup' &&
 | 
			
		||||
      artifact.isParent
 | 
			
		||||
      hasExtrudeArtifact.length &&
 | 
			
		||||
      (guiMode.mode === 'default' || guiMode.mode === 'canEditExtrude') &&
 | 
			
		||||
      ast
 | 
			
		||||
    ) {
 | 
			
		||||
      const pathToNode = getNodePathFromSourceRange(ast, artifact.sourceRange)
 | 
			
		||||
      const { rotation, position } = artifact
 | 
			
		||||
      const pathToNode = getNodePathFromSourceRange(
 | 
			
		||||
        ast,
 | 
			
		||||
        hasExtrudeArtifact[0].sourceRange
 | 
			
		||||
      )
 | 
			
		||||
      const { rotation, position } = hasExtrudeArtifact[0]
 | 
			
		||||
      setGuiMode({ mode: 'canEditExtrude', pathToNode, rotation, position })
 | 
			
		||||
    } else if (
 | 
			
		||||
      !shouldHighlight &&
 | 
			
		||||
      (guiMode.mode === 'canEditSketch' || guiMode.mode === 'canEditExtrude')
 | 
			
		||||
      // (artifact.parentType === 'extrudeGroup' || artifact.type === 'extrudeGroup')
 | 
			
		||||
      (guiMode.mode === 'canEditExtrude' || guiMode.mode === 'canEditSketch')
 | 
			
		||||
    ) {
 | 
			
		||||
      setGuiMode({ mode: 'default' })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -1,20 +1,20 @@
 | 
			
		||||
import { useStore } from '../useStore'
 | 
			
		||||
import { DoubleSide, Vector3, Quaternion } from 'three'
 | 
			
		||||
import { Program } from '../lang/abstractSyntaxTree'
 | 
			
		||||
import { addLine } from '../lang/modifyAst'
 | 
			
		||||
import { toolTipModification } from '../lang/std/sketch'
 | 
			
		||||
import { roundOff } from '../lib/utils'
 | 
			
		||||
 | 
			
		||||
export const SketchPlane = () => {
 | 
			
		||||
  const { ast, guiMode, updateAst } = useStore(
 | 
			
		||||
    ({ guiMode, ast, updateAst }) => ({
 | 
			
		||||
      guiMode,
 | 
			
		||||
      ast,
 | 
			
		||||
      updateAst,
 | 
			
		||||
    })
 | 
			
		||||
  )
 | 
			
		||||
  const { ast, guiMode, updateAst, programMemory } = useStore((s) => ({
 | 
			
		||||
    guiMode: s.guiMode,
 | 
			
		||||
    ast: s.ast,
 | 
			
		||||
    updateAst: s.updateAst,
 | 
			
		||||
    programMemory: s.programMemory,
 | 
			
		||||
  }))
 | 
			
		||||
  if (guiMode.mode !== 'sketch') {
 | 
			
		||||
    return null
 | 
			
		||||
  }
 | 
			
		||||
  if (guiMode.sketchMode !== 'points' && guiMode.sketchMode !== 'sketchEdit') {
 | 
			
		||||
  if (!(guiMode.sketchMode === 'lineTo') && !('isTooltip' in guiMode)) {
 | 
			
		||||
    return null
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -39,7 +39,7 @@ export const SketchPlane = () => {
 | 
			
		||||
        position={position}
 | 
			
		||||
        name={sketchGridName}
 | 
			
		||||
        onClick={(e) => {
 | 
			
		||||
          if (guiMode.sketchMode !== 'points') {
 | 
			
		||||
          if (!('isTooltip' in guiMode)) {
 | 
			
		||||
            return
 | 
			
		||||
          }
 | 
			
		||||
          const sketchGridIntersection = e.intersections.find(
 | 
			
		||||
@ -65,10 +65,11 @@ export const SketchPlane = () => {
 | 
			
		||||
                nonCodeMeta: {},
 | 
			
		||||
              }
 | 
			
		||||
          const addLinePoint: [number, number] = [point.x, point.y]
 | 
			
		||||
          const { modifiedAst } = addLine(
 | 
			
		||||
          const { modifiedAst } = toolTipModification(
 | 
			
		||||
            _ast,
 | 
			
		||||
            guiMode.pathToNode,
 | 
			
		||||
            addLinePoint
 | 
			
		||||
            programMemory,
 | 
			
		||||
            addLinePoint,
 | 
			
		||||
            guiMode
 | 
			
		||||
          )
 | 
			
		||||
          updateAst(modifiedAst)
 | 
			
		||||
        }}
 | 
			
		||||
@ -91,10 +92,6 @@ export const SketchPlane = () => {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function roundy({ x, y, z }: any) {
 | 
			
		||||
  const roundOff = (num: number, places: number): number => {
 | 
			
		||||
    const x = Math.pow(10, places)
 | 
			
		||||
    return Math.round(num * x) / x
 | 
			
		||||
  }
 | 
			
		||||
  return {
 | 
			
		||||
    x: roundOff(x, 2),
 | 
			
		||||
    y: roundOff(y, 2),
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user